1 // Copyright (C) 2007-2016 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 LinearVariation = false,
2500 CORBA::Boolean ByAverageNormal = false,
2501 CORBA::Boolean UseInputElemsOnly = false,
2502 CORBA::Long Flags = 0,
2503 CORBA::Boolean MakeBoundary = true )
2505 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2506 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2507 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2508 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2509 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2513 ExtrusionParams(const SMESH::DirStruct & theDir,
2514 CORBA::Long theNbOfSteps,
2515 const SMESH::double_array & theScaleFactors,
2516 CORBA::Boolean theLinearVariation,
2517 const SMESH::double_array & theBasePoint,
2518 CORBA::Boolean theMakeGroups):
2519 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2523 toList( theScaleFactors ),
2524 TBasePoint( theBasePoint ),
2525 makeFlags( theMakeGroups, theLinearVariation )),
2526 myIsExtrusionByNormal( false )
2530 ExtrusionParams(const SMESH::DirStruct & theDir,
2531 CORBA::Long theNbOfSteps,
2532 CORBA::Boolean theMakeGroups,
2533 CORBA::Long theExtrFlags,
2534 CORBA::Double theSewTolerance):
2535 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2539 std::list<double>(),
2541 makeFlags( theMakeGroups, false, false, false,
2542 theExtrFlags, false ),
2544 myIsExtrusionByNormal( false )
2547 // params for extrusion by normal
2548 ExtrusionParams(CORBA::Double theStepSize,
2549 CORBA::Long theNbOfSteps,
2550 CORBA::Short theDim,
2551 CORBA::Boolean theByAverageNormal,
2552 CORBA::Boolean theUseInputElemsOnly,
2553 CORBA::Boolean theMakeGroups ):
2554 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2556 makeFlags( theMakeGroups, false,
2557 theByAverageNormal, theUseInputElemsOnly ),
2559 myIsExtrusionByNormal( true )
2565 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2570 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2572 std::list<double> scales;
2573 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2574 scales.push_back( theScaleFactors[i] );
2578 // structure used to convert SMESH::double_array to gp_XYZ*
2582 TBasePoint( const SMESH::double_array & theBasePoint )
2585 if ( theBasePoint.length() == 3 )
2587 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2591 operator const gp_XYZ*() const { return pp; }
2596 //=======================================================================
2598 * \brief Generate dim+1 elements by extrusion of elements along vector
2599 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2600 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2601 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2602 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2603 * \param [in] nbOfSteps - number of elements to generate from one element
2604 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2605 * corresponding to groups the input elements included in.
2606 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2608 //=======================================================================
2610 SMESH::ListOfGroups*
2611 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2612 const SMESH::ListOfIDSources & theEdges,
2613 const SMESH::ListOfIDSources & theFaces,
2614 const SMESH::DirStruct & theStepVector,
2615 CORBA::Long theNbOfSteps,
2616 const SMESH::double_array & theScaleFactors,
2617 CORBA::Boolean theLinearVariation,
2618 const SMESH::double_array & theBasePoint,
2619 CORBA::Boolean theToMakeGroups)
2620 throw (SALOME::SALOME_Exception)
2625 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2626 theLinearVariation, theBasePoint, theToMakeGroups );
2628 TIDSortedElemSet elemsNodes[2];
2629 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2630 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2631 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2633 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2634 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2635 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2636 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2638 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2639 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2640 if ( myIsPreviewMode )
2642 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2643 // previewType = SMDSAbs_Edge;
2645 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2646 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2647 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2648 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2649 workElements = & copyElements[0];
2651 params.SetNoGroups();
2653 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2655 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2656 ::SMESH_MeshEditor::PGroupIDs groupIds =
2657 getEditor().ExtrusionSweep( workElements, params, aHistory );
2659 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2661 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2663 if ( !myIsPreviewMode )
2665 dumpGroupsList( aPythonDump, aGroups );
2666 aPythonDump << this<< ".ExtrusionSweepObjects( "
2670 << theStepVector << ", "
2671 << TVar( theNbOfSteps ) << ", "
2672 << theToMakeGroups << " )";
2676 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2679 return aGroups ? aGroups : new SMESH::ListOfGroups;
2681 SMESH_CATCH( SMESH::throwCorbaException );
2685 //=======================================================================
2686 //function : ExtrusionByNormal
2688 //=======================================================================
2690 SMESH::ListOfGroups*
2691 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2692 CORBA::Double stepSize,
2693 CORBA::Long nbOfSteps,
2694 CORBA::Boolean byAverageNormal,
2695 CORBA::Boolean useInputElemsOnly,
2696 CORBA::Boolean makeGroups,
2698 throw (SALOME::SALOME_Exception)
2703 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2705 ExtrusionParams params( stepSize, nbOfSteps, dim,
2706 byAverageNormal, useInputElemsOnly, makeGroups );
2708 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2709 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2711 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2712 if (( elemTypes->length() == 1 ) &&
2713 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2714 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2717 TIDSortedElemSet elemsNodes[2];
2718 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2719 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2721 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2722 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2723 if ( myIsPreviewMode )
2725 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2726 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2727 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2728 workElements = & copyElements[0];
2730 params.SetNoGroups();
2733 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2734 ::SMESH_MeshEditor::PGroupIDs groupIds =
2735 getEditor().ExtrusionSweep( workElements, params, aHistory );
2737 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2739 if (!myIsPreviewMode) {
2740 dumpGroupsList(aPythonDump, aGroups);
2741 aPythonDump << this << ".ExtrusionByNormal( " << objects
2742 << ", " << TVar( stepSize )
2743 << ", " << TVar( nbOfSteps )
2744 << ", " << byAverageNormal
2745 << ", " << useInputElemsOnly
2746 << ", " << makeGroups
2752 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2755 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2757 return aGroups ? aGroups : new SMESH::ListOfGroups;
2759 SMESH_CATCH( SMESH::throwCorbaException );
2763 //=======================================================================
2764 //function : AdvancedExtrusion
2766 //=======================================================================
2768 SMESH::ListOfGroups*
2769 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2770 const SMESH::DirStruct & theStepVector,
2771 CORBA::Long theNbOfSteps,
2772 CORBA::Long theExtrFlags,
2773 CORBA::Double theSewTolerance,
2774 CORBA::Boolean theMakeGroups)
2775 throw (SALOME::SALOME_Exception)
2780 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2782 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2783 theExtrFlags, theSewTolerance );
2785 TIDSortedElemSet elemsNodes[2];
2786 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2788 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2789 ::SMESH_MeshEditor::PGroupIDs groupIds =
2790 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2792 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2794 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2796 if ( !myIsPreviewMode ) {
2797 dumpGroupsList(aPythonDump, aGroups);
2798 aPythonDump << this << ".AdvancedExtrusion( "
2799 << theIDsOfElements << ", "
2800 << theStepVector << ", "
2801 << theNbOfSteps << ", "
2802 << theExtrFlags << ", "
2803 << theSewTolerance << ", "
2804 << theMakeGroups << " )";
2808 getPreviewMesh()->Remove( SMDSAbs_Volume );
2811 return aGroups ? aGroups : new SMESH::ListOfGroups;
2813 SMESH_CATCH( SMESH::throwCorbaException );
2817 //================================================================================
2819 * \brief Convert extrusion error to IDL enum
2821 //================================================================================
2825 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2827 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2831 RETCASE( EXTR_NO_ELEMENTS );
2832 RETCASE( EXTR_PATH_NOT_EDGE );
2833 RETCASE( EXTR_BAD_PATH_SHAPE );
2834 RETCASE( EXTR_BAD_STARTING_NODE );
2835 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2836 RETCASE( EXTR_CANT_GET_TANGENT );
2838 return SMESH::SMESH_MeshEditor::EXTR_OK;
2842 //=======================================================================
2843 //function : extrusionAlongPath
2845 //=======================================================================
2846 SMESH::ListOfGroups*
2847 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2848 const SMESH::ListOfIDSources & theEdges,
2849 const SMESH::ListOfIDSources & theFaces,
2850 SMESH::SMESH_IDSource_ptr thePathMesh,
2851 GEOM::GEOM_Object_ptr thePathShape,
2852 CORBA::Long theNodeStart,
2853 CORBA::Boolean theHasAngles,
2854 const SMESH::double_array & theAngles,
2855 CORBA::Boolean theLinearVariation,
2856 CORBA::Boolean theHasRefPoint,
2857 const SMESH::PointStruct & theRefPoint,
2859 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2860 throw (SALOME::SALOME_Exception)
2865 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2867 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2868 if ( thePathMesh->_is_nil() )
2869 return aGroups._retn();
2872 SMESH_subMesh* aSubMesh = 0;
2873 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2874 if ( thePathShape->_is_nil() )
2876 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2877 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2879 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2880 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2881 if ( !aMeshImp ) return aGroups._retn();
2882 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2883 if ( !aSubMesh ) return aGroups._retn();
2885 else if ( !aMeshImp ||
2886 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2888 return aGroups._retn();
2893 if ( !aMeshImp ) return aGroups._retn();
2894 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2895 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2896 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2897 return aGroups._retn();
2900 SMDS_MeshNode* nodeStart =
2901 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2903 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2904 return aGroups._retn();
2907 TIDSortedElemSet elemsNodes[2];
2908 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2909 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2910 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2912 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2913 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2914 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2915 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2917 list<double> angles;
2918 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2919 angles.push_back( theAngles[i] );
2922 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2924 int nbOldGroups = myMesh->NbGroup();
2926 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2927 if ( myIsPreviewMode )
2929 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2930 TPreviewMesh * tmpMesh = getPreviewMesh();
2931 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2932 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2933 workElements = & copyElements[0];
2934 theMakeGroups = false;
2937 ::SMESH_MeshEditor::Extrusion_Error error;
2939 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2940 theHasAngles, angles, theLinearVariation,
2941 theHasRefPoint, refPnt, theMakeGroups );
2943 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2944 theHasAngles, angles, theLinearVariation,
2945 theHasRefPoint, refPnt, theMakeGroups );
2947 declareMeshModified( /*isReComputeSafe=*/true );
2948 theError = convExtrError( error );
2950 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2951 if ( theMakeGroups ) {
2952 list<int> groupIDs = myMesh->GetGroupIds();
2953 list<int>::iterator newBegin = groupIDs.begin();
2954 std::advance( newBegin, nbOldGroups ); // skip old groups
2955 groupIDs.erase( groupIDs.begin(), newBegin );
2956 aGroups = getGroups( & groupIDs );
2957 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2960 if ( !myIsPreviewMode ) {
2961 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2962 else aPythonDump << "(_noGroups, error) = ";
2963 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2967 << thePathMesh << ", "
2968 << thePathShape << ", "
2969 << theNodeStart << ", "
2970 << theHasAngles << ", "
2971 << TVar( theAngles ) << ", "
2972 << theLinearVariation << ", "
2973 << theHasRefPoint << ", "
2974 << "SMESH.PointStruct( "
2975 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2976 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2977 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2978 << theMakeGroups << " )";
2982 getPreviewMesh()->Remove( SMDSAbs_Volume );
2985 return aGroups._retn();
2987 SMESH_CATCH( SMESH::throwCorbaException );
2991 //================================================================================
2993 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2994 * of given angles along path steps
2995 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2996 * which proceeds the extrusion
2997 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2998 * is used to define the sub-mesh for the path
3000 //================================================================================
3002 SMESH::double_array*
3003 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3004 GEOM::GEOM_Object_ptr thePathShape,
3005 const SMESH::double_array & theAngles)
3007 SMESH::double_array_var aResult = new SMESH::double_array();
3008 int nbAngles = theAngles.length();
3009 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3011 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3012 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3013 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3014 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3015 return aResult._retn();
3016 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3017 if ( nbSteps == nbAngles )
3019 aResult.inout() = theAngles;
3023 aResult->length( nbSteps );
3024 double rAn2St = double( nbAngles ) / double( nbSteps );
3025 double angPrev = 0, angle;
3026 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3028 double angCur = rAn2St * ( iSt+1 );
3029 double angCurFloor = floor( angCur );
3030 double angPrevFloor = floor( angPrev );
3031 if ( angPrevFloor == angCurFloor )
3032 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3035 int iP = int( angPrevFloor );
3036 double angPrevCeil = ceil(angPrev);
3037 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3039 int iC = int( angCurFloor );
3040 if ( iC < nbAngles )
3041 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3043 iP = int( angPrevCeil );
3045 angle += theAngles[ iC ];
3047 aResult[ iSt ] = angle;
3052 // Update Python script
3053 TPythonDump() << "rotAngles = " << theAngles;
3054 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3055 << thePathMesh << ", "
3056 << thePathShape << ", "
3059 return aResult._retn();
3062 //=======================================================================
3065 //=======================================================================
3067 SMESH::ListOfGroups*
3068 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3069 const SMESH::AxisStruct & theAxis,
3070 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3071 CORBA::Boolean theCopy,
3073 ::SMESH_Mesh* theTargetMesh)
3074 throw (SALOME::SALOME_Exception)
3079 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3080 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3082 if ( theTargetMesh )
3086 switch ( theMirrorType ) {
3087 case SMESH::SMESH_MeshEditor::POINT:
3088 aTrsf.SetMirror( P );
3090 case SMESH::SMESH_MeshEditor::AXIS:
3091 aTrsf.SetMirror( gp_Ax1( P, V ));
3094 aTrsf.SetMirror( gp_Ax2( P, V ));
3097 TIDSortedElemSet copyElements;
3098 TIDSortedElemSet* workElements = & theElements;
3100 if ( myIsPreviewMode )
3102 TPreviewMesh * tmpMesh = getPreviewMesh();
3103 tmpMesh->Copy( theElements, copyElements);
3104 if ( !theCopy && !theTargetMesh )
3106 TIDSortedElemSet elemsAround, elemsAroundCopy;
3107 getElementsAround( theElements, getMeshDS(), elemsAround );
3108 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3110 workElements = & copyElements;
3111 theMakeGroups = false;
3114 ::SMESH_MeshEditor::PGroupIDs groupIds =
3115 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3117 if ( !myIsPreviewMode )
3119 if ( theTargetMesh )
3120 theTargetMesh->GetMeshDS()->Modified();
3122 declareMeshModified( /*isReComputeSafe=*/false );
3125 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3127 SMESH_CATCH( SMESH::throwCorbaException );
3131 //=======================================================================
3134 //=======================================================================
3136 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3137 const SMESH::AxisStruct & theAxis,
3138 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3139 CORBA::Boolean theCopy)
3140 throw (SALOME::SALOME_Exception)
3142 if ( !myIsPreviewMode ) {
3143 TPythonDump() << this << ".Mirror( "
3144 << theIDsOfElements << ", "
3146 << mirrorTypeName(theMirrorType) << ", "
3149 if ( theIDsOfElements.length() > 0 )
3151 TIDSortedElemSet elements;
3152 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3153 mirror(elements, theAxis, theMirrorType, theCopy, false);
3158 //=======================================================================
3159 //function : MirrorObject
3161 //=======================================================================
3163 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3164 const SMESH::AxisStruct & theAxis,
3165 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3166 CORBA::Boolean theCopy)
3167 throw (SALOME::SALOME_Exception)
3169 if ( !myIsPreviewMode ) {
3170 TPythonDump() << this << ".MirrorObject( "
3171 << theObject << ", "
3173 << mirrorTypeName(theMirrorType) << ", "
3176 TIDSortedElemSet elements;
3178 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3180 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3181 mirror(elements, theAxis, theMirrorType, theCopy, false);
3184 //=======================================================================
3185 //function : MirrorMakeGroups
3187 //=======================================================================
3189 SMESH::ListOfGroups*
3190 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3191 const SMESH::AxisStruct& theMirror,
3192 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3193 throw (SALOME::SALOME_Exception)
3195 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3197 SMESH::ListOfGroups * aGroups = 0;
3198 if ( theIDsOfElements.length() > 0 )
3200 TIDSortedElemSet elements;
3201 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3202 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3204 if (!myIsPreviewMode) {
3205 dumpGroupsList(aPythonDump, aGroups);
3206 aPythonDump << this << ".MirrorMakeGroups( "
3207 << theIDsOfElements << ", "
3208 << theMirror << ", "
3209 << mirrorTypeName(theMirrorType) << " )";
3214 //=======================================================================
3215 //function : MirrorObjectMakeGroups
3217 //=======================================================================
3219 SMESH::ListOfGroups*
3220 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3221 const SMESH::AxisStruct& theMirror,
3222 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3223 throw (SALOME::SALOME_Exception)
3225 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3227 SMESH::ListOfGroups * aGroups = 0;
3228 TIDSortedElemSet elements;
3229 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3230 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3232 if (!myIsPreviewMode)
3234 dumpGroupsList(aPythonDump,aGroups);
3235 aPythonDump << this << ".MirrorObjectMakeGroups( "
3236 << theObject << ", "
3237 << theMirror << ", "
3238 << mirrorTypeName(theMirrorType) << " )";
3243 //=======================================================================
3244 //function : MirrorMakeMesh
3246 //=======================================================================
3248 SMESH::SMESH_Mesh_ptr
3249 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3250 const SMESH::AxisStruct& theMirror,
3251 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3252 CORBA::Boolean theCopyGroups,
3253 const char* theMeshName)
3254 throw (SALOME::SALOME_Exception)
3256 SMESH_Mesh_i* mesh_i;
3257 SMESH::SMESH_Mesh_var mesh;
3258 { // open new scope to dump "MakeMesh" command
3259 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3261 TPythonDump pydump; // to prevent dump at mesh creation
3263 mesh = makeMesh( theMeshName );
3264 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3265 if (mesh_i && theIDsOfElements.length() > 0 )
3267 TIDSortedElemSet elements;
3268 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3269 mirror(elements, theMirror, theMirrorType,
3270 false, theCopyGroups, & mesh_i->GetImpl());
3271 mesh_i->CreateGroupServants();
3274 if (!myIsPreviewMode) {
3275 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3276 << theIDsOfElements << ", "
3277 << theMirror << ", "
3278 << mirrorTypeName(theMirrorType) << ", "
3279 << theCopyGroups << ", '"
3280 << theMeshName << "' )";
3285 if (!myIsPreviewMode && mesh_i)
3286 mesh_i->GetGroups();
3288 return mesh._retn();
3291 //=======================================================================
3292 //function : MirrorObjectMakeMesh
3294 //=======================================================================
3296 SMESH::SMESH_Mesh_ptr
3297 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3298 const SMESH::AxisStruct& theMirror,
3299 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3300 CORBA::Boolean theCopyGroups,
3301 const char* theMeshName)
3302 throw (SALOME::SALOME_Exception)
3304 SMESH_Mesh_i* mesh_i;
3305 SMESH::SMESH_Mesh_var mesh;
3306 { // open new scope to dump "MakeMesh" command
3307 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3309 TPythonDump pydump; // to prevent dump at mesh creation
3311 mesh = makeMesh( theMeshName );
3312 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3313 TIDSortedElemSet elements;
3315 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3317 mirror(elements, theMirror, theMirrorType,
3318 false, theCopyGroups, & mesh_i->GetImpl());
3319 mesh_i->CreateGroupServants();
3321 if (!myIsPreviewMode) {
3322 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3323 << theObject << ", "
3324 << theMirror << ", "
3325 << mirrorTypeName(theMirrorType) << ", "
3326 << theCopyGroups << ", '"
3327 << theMeshName << "' )";
3332 if (!myIsPreviewMode && mesh_i)
3333 mesh_i->GetGroups();
3335 return mesh._retn();
3338 //=======================================================================
3339 //function : translate
3341 //=======================================================================
3343 SMESH::ListOfGroups*
3344 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3345 const SMESH::DirStruct & theVector,
3346 CORBA::Boolean theCopy,
3348 ::SMESH_Mesh* theTargetMesh)
3349 throw (SALOME::SALOME_Exception)
3354 if ( theTargetMesh )
3358 const SMESH::PointStruct * P = &theVector.PS;
3359 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3361 TIDSortedElemSet copyElements;
3362 TIDSortedElemSet* workElements = &theElements;
3364 if ( myIsPreviewMode )
3366 TPreviewMesh * tmpMesh = getPreviewMesh();
3367 tmpMesh->Copy( theElements, copyElements);
3368 if ( !theCopy && !theTargetMesh )
3370 TIDSortedElemSet elemsAround, elemsAroundCopy;
3371 getElementsAround( theElements, getMeshDS(), elemsAround );
3372 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3374 workElements = & copyElements;
3375 theMakeGroups = false;
3378 ::SMESH_MeshEditor::PGroupIDs groupIds =
3379 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3381 if ( !myIsPreviewMode )
3383 if ( theTargetMesh )
3384 theTargetMesh->GetMeshDS()->Modified();
3386 declareMeshModified( /*isReComputeSafe=*/false );
3389 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3391 SMESH_CATCH( SMESH::throwCorbaException );
3395 //=======================================================================
3396 //function : Translate
3398 //=======================================================================
3400 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3401 const SMESH::DirStruct & theVector,
3402 CORBA::Boolean theCopy)
3403 throw (SALOME::SALOME_Exception)
3405 if (!myIsPreviewMode) {
3406 TPythonDump() << this << ".Translate( "
3407 << theIDsOfElements << ", "
3408 << theVector << ", "
3411 if (theIDsOfElements.length()) {
3412 TIDSortedElemSet elements;
3413 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3414 translate(elements, theVector, theCopy, false);
3418 //=======================================================================
3419 //function : TranslateObject
3421 //=======================================================================
3423 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3424 const SMESH::DirStruct & theVector,
3425 CORBA::Boolean theCopy)
3426 throw (SALOME::SALOME_Exception)
3428 if (!myIsPreviewMode) {
3429 TPythonDump() << this << ".TranslateObject( "
3430 << theObject << ", "
3431 << theVector << ", "
3434 TIDSortedElemSet elements;
3436 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3438 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3439 translate(elements, theVector, theCopy, false);
3442 //=======================================================================
3443 //function : TranslateMakeGroups
3445 //=======================================================================
3447 SMESH::ListOfGroups*
3448 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3449 const SMESH::DirStruct& theVector)
3450 throw (SALOME::SALOME_Exception)
3452 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3454 SMESH::ListOfGroups * aGroups = 0;
3455 if (theIDsOfElements.length()) {
3456 TIDSortedElemSet elements;
3457 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3458 aGroups = translate(elements,theVector,true,true);
3460 if (!myIsPreviewMode) {
3461 dumpGroupsList(aPythonDump, aGroups);
3462 aPythonDump << this << ".TranslateMakeGroups( "
3463 << theIDsOfElements << ", "
3464 << theVector << " )";
3469 //=======================================================================
3470 //function : TranslateObjectMakeGroups
3472 //=======================================================================
3474 SMESH::ListOfGroups*
3475 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3476 const SMESH::DirStruct& theVector)
3477 throw (SALOME::SALOME_Exception)
3479 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3481 SMESH::ListOfGroups * aGroups = 0;
3482 TIDSortedElemSet elements;
3483 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3484 aGroups = translate(elements, theVector, true, true);
3486 if (!myIsPreviewMode) {
3487 dumpGroupsList(aPythonDump, aGroups);
3488 aPythonDump << this << ".TranslateObjectMakeGroups( "
3489 << theObject << ", "
3490 << theVector << " )";
3495 //=======================================================================
3496 //function : TranslateMakeMesh
3498 //=======================================================================
3500 SMESH::SMESH_Mesh_ptr
3501 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3502 const SMESH::DirStruct& theVector,
3503 CORBA::Boolean theCopyGroups,
3504 const char* theMeshName)
3505 throw (SALOME::SALOME_Exception)
3507 SMESH_Mesh_i* mesh_i;
3508 SMESH::SMESH_Mesh_var mesh;
3510 { // open new scope to dump "MakeMesh" command
3511 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3513 TPythonDump pydump; // to prevent dump at mesh creation
3515 mesh = makeMesh( theMeshName );
3516 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3518 if ( mesh_i && theIDsOfElements.length() )
3520 TIDSortedElemSet elements;
3521 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3522 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3523 mesh_i->CreateGroupServants();
3526 if ( !myIsPreviewMode ) {
3527 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3528 << theIDsOfElements << ", "
3529 << theVector << ", "
3530 << theCopyGroups << ", '"
3531 << theMeshName << "' )";
3536 if (!myIsPreviewMode && mesh_i)
3537 mesh_i->GetGroups();
3539 return mesh._retn();
3542 //=======================================================================
3543 //function : TranslateObjectMakeMesh
3545 //=======================================================================
3547 SMESH::SMESH_Mesh_ptr
3548 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3549 const SMESH::DirStruct& theVector,
3550 CORBA::Boolean theCopyGroups,
3551 const char* theMeshName)
3552 throw (SALOME::SALOME_Exception)
3555 SMESH_Mesh_i* mesh_i;
3556 SMESH::SMESH_Mesh_var mesh;
3557 { // open new scope to dump "MakeMesh" command
3558 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3560 TPythonDump pydump; // to prevent dump at mesh creation
3561 mesh = makeMesh( theMeshName );
3562 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3564 TIDSortedElemSet elements;
3566 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3568 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3569 mesh_i->CreateGroupServants();
3571 if ( !myIsPreviewMode ) {
3572 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3573 << theObject << ", "
3574 << theVector << ", "
3575 << theCopyGroups << ", '"
3576 << theMeshName << "' )";
3581 if (!myIsPreviewMode && mesh_i)
3582 mesh_i->GetGroups();
3584 return mesh._retn();
3586 SMESH_CATCH( SMESH::throwCorbaException );
3590 //=======================================================================
3593 //=======================================================================
3595 SMESH::ListOfGroups*
3596 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3597 const SMESH::AxisStruct & theAxis,
3598 CORBA::Double theAngle,
3599 CORBA::Boolean theCopy,
3601 ::SMESH_Mesh* theTargetMesh)
3602 throw (SALOME::SALOME_Exception)
3607 if ( theTargetMesh )
3610 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3611 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3614 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3616 TIDSortedElemSet copyElements;
3617 TIDSortedElemSet* workElements = &theElements;
3618 if ( myIsPreviewMode ) {
3619 TPreviewMesh * tmpMesh = getPreviewMesh();
3620 tmpMesh->Copy( theElements, copyElements );
3621 if ( !theCopy && !theTargetMesh )
3623 TIDSortedElemSet elemsAround, elemsAroundCopy;
3624 getElementsAround( theElements, getMeshDS(), elemsAround );
3625 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3627 workElements = ©Elements;
3628 theMakeGroups = false;
3631 ::SMESH_MeshEditor::PGroupIDs groupIds =
3632 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3634 if ( !myIsPreviewMode)
3636 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3637 else declareMeshModified( /*isReComputeSafe=*/false );
3640 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3642 SMESH_CATCH( SMESH::throwCorbaException );
3646 //=======================================================================
3649 //=======================================================================
3651 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3652 const SMESH::AxisStruct & theAxis,
3653 CORBA::Double theAngle,
3654 CORBA::Boolean theCopy)
3655 throw (SALOME::SALOME_Exception)
3657 if (!myIsPreviewMode) {
3658 TPythonDump() << this << ".Rotate( "
3659 << theIDsOfElements << ", "
3661 << TVar( theAngle ) << ", "
3664 if (theIDsOfElements.length() > 0)
3666 TIDSortedElemSet elements;
3667 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3668 rotate(elements,theAxis,theAngle,theCopy,false);
3672 //=======================================================================
3673 //function : RotateObject
3675 //=======================================================================
3677 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3678 const SMESH::AxisStruct & theAxis,
3679 CORBA::Double theAngle,
3680 CORBA::Boolean theCopy)
3681 throw (SALOME::SALOME_Exception)
3683 if ( !myIsPreviewMode ) {
3684 TPythonDump() << this << ".RotateObject( "
3685 << theObject << ", "
3687 << TVar( theAngle ) << ", "
3690 TIDSortedElemSet elements;
3691 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3692 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3693 rotate(elements,theAxis,theAngle,theCopy,false);
3696 //=======================================================================
3697 //function : RotateMakeGroups
3699 //=======================================================================
3701 SMESH::ListOfGroups*
3702 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3703 const SMESH::AxisStruct& theAxis,
3704 CORBA::Double theAngle)
3705 throw (SALOME::SALOME_Exception)
3707 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3709 SMESH::ListOfGroups * aGroups = 0;
3710 if (theIDsOfElements.length() > 0)
3712 TIDSortedElemSet elements;
3713 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3714 aGroups = rotate(elements,theAxis,theAngle,true,true);
3716 if (!myIsPreviewMode) {
3717 dumpGroupsList(aPythonDump, aGroups);
3718 aPythonDump << this << ".RotateMakeGroups( "
3719 << theIDsOfElements << ", "
3721 << TVar( theAngle ) << " )";
3726 //=======================================================================
3727 //function : RotateObjectMakeGroups
3729 //=======================================================================
3731 SMESH::ListOfGroups*
3732 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3733 const SMESH::AxisStruct& theAxis,
3734 CORBA::Double theAngle)
3735 throw (SALOME::SALOME_Exception)
3737 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3739 SMESH::ListOfGroups * aGroups = 0;
3740 TIDSortedElemSet elements;
3741 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3742 aGroups = rotate(elements, theAxis, theAngle, true, true);
3744 if (!myIsPreviewMode) {
3745 dumpGroupsList(aPythonDump, aGroups);
3746 aPythonDump << this << ".RotateObjectMakeGroups( "
3747 << theObject << ", "
3749 << TVar( theAngle ) << " )";
3754 //=======================================================================
3755 //function : RotateMakeMesh
3757 //=======================================================================
3759 SMESH::SMESH_Mesh_ptr
3760 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3761 const SMESH::AxisStruct& theAxis,
3762 CORBA::Double theAngleInRadians,
3763 CORBA::Boolean theCopyGroups,
3764 const char* theMeshName)
3765 throw (SALOME::SALOME_Exception)
3768 SMESH::SMESH_Mesh_var mesh;
3769 SMESH_Mesh_i* mesh_i;
3771 { // open new scope to dump "MakeMesh" command
3772 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3774 TPythonDump pydump; // to prevent dump at mesh creation
3776 mesh = makeMesh( theMeshName );
3777 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3779 if ( mesh_i && theIDsOfElements.length() > 0 )
3781 TIDSortedElemSet elements;
3782 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3783 rotate(elements, theAxis, theAngleInRadians,
3784 false, theCopyGroups, & mesh_i->GetImpl());
3785 mesh_i->CreateGroupServants();
3787 if ( !myIsPreviewMode ) {
3788 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3789 << theIDsOfElements << ", "
3791 << TVar( theAngleInRadians ) << ", "
3792 << theCopyGroups << ", '"
3793 << theMeshName << "' )";
3798 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3799 mesh_i->GetGroups();
3801 return mesh._retn();
3803 SMESH_CATCH( SMESH::throwCorbaException );
3807 //=======================================================================
3808 //function : RotateObjectMakeMesh
3810 //=======================================================================
3812 SMESH::SMESH_Mesh_ptr
3813 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3814 const SMESH::AxisStruct& theAxis,
3815 CORBA::Double theAngleInRadians,
3816 CORBA::Boolean theCopyGroups,
3817 const char* theMeshName)
3818 throw (SALOME::SALOME_Exception)
3821 SMESH::SMESH_Mesh_var mesh;
3822 SMESH_Mesh_i* mesh_i;
3824 {// open new scope to dump "MakeMesh" command
3825 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3827 TPythonDump pydump; // to prevent dump at mesh creation
3828 mesh = makeMesh( theMeshName );
3829 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3831 TIDSortedElemSet elements;
3833 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3835 rotate(elements, theAxis, theAngleInRadians,
3836 false, theCopyGroups, & mesh_i->GetImpl());
3837 mesh_i->CreateGroupServants();
3839 if ( !myIsPreviewMode ) {
3840 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3841 << theObject << ", "
3843 << TVar( theAngleInRadians ) << ", "
3844 << theCopyGroups << ", '"
3845 << theMeshName << "' )";
3850 if (!myIsPreviewMode && mesh_i)
3851 mesh_i->GetGroups();
3853 return mesh._retn();
3855 SMESH_CATCH( SMESH::throwCorbaException );
3859 //=======================================================================
3862 //=======================================================================
3864 SMESH::ListOfGroups*
3865 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3866 const SMESH::PointStruct& thePoint,
3867 const SMESH::double_array& theScaleFact,
3868 CORBA::Boolean theCopy,
3870 ::SMESH_Mesh* theTargetMesh)
3871 throw (SALOME::SALOME_Exception)
3875 if ( theScaleFact.length() < 1 )
3876 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3877 if ( theScaleFact.length() == 2 )
3878 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3880 if ( theTargetMesh )
3883 TIDSortedElemSet elements;
3884 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3885 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3890 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3891 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3895 // fight against orthogonalization
3896 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3897 // 0, S[1], 0, thePoint.y * (1-S[1]),
3898 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3899 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3900 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3901 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3902 loc.SetCoord( thePoint.x * (1-S[0]),
3903 thePoint.y * (1-S[1]),
3904 thePoint.z * (1-S[2]));
3905 M.SetDiagonal( S[0], S[1], S[2] );
3907 TIDSortedElemSet copyElements;
3908 TIDSortedElemSet* workElements = &elements;
3909 if ( myIsPreviewMode )
3911 TPreviewMesh * tmpMesh = getPreviewMesh();
3912 tmpMesh->Copy( elements, copyElements);
3913 if ( !theCopy && !theTargetMesh )
3915 TIDSortedElemSet elemsAround, elemsAroundCopy;
3916 getElementsAround( elements, getMeshDS(), elemsAround );
3917 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3919 workElements = & copyElements;
3920 theMakeGroups = false;
3923 ::SMESH_MeshEditor::PGroupIDs groupIds =
3924 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3926 if ( !myIsPreviewMode )
3928 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3929 else declareMeshModified( /*isReComputeSafe=*/false );
3931 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3933 SMESH_CATCH( SMESH::throwCorbaException );
3937 //=======================================================================
3940 //=======================================================================
3942 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3943 const SMESH::PointStruct& thePoint,
3944 const SMESH::double_array& theScaleFact,
3945 CORBA::Boolean theCopy)
3946 throw (SALOME::SALOME_Exception)
3948 if ( !myIsPreviewMode ) {
3949 TPythonDump() << this << ".Scale( "
3950 << theObject << ", "
3952 << TVar( theScaleFact ) << ", "
3955 scale(theObject, thePoint, theScaleFact, theCopy, false);
3959 //=======================================================================
3960 //function : ScaleMakeGroups
3962 //=======================================================================
3964 SMESH::ListOfGroups*
3965 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3966 const SMESH::PointStruct& thePoint,
3967 const SMESH::double_array& theScaleFact)
3968 throw (SALOME::SALOME_Exception)
3970 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3972 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3973 if (!myIsPreviewMode) {
3974 dumpGroupsList(aPythonDump, aGroups);
3975 aPythonDump << this << ".Scale("
3978 << TVar( theScaleFact ) << ",True,True)";
3984 //=======================================================================
3985 //function : ScaleMakeMesh
3987 //=======================================================================
3989 SMESH::SMESH_Mesh_ptr
3990 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3991 const SMESH::PointStruct& thePoint,
3992 const SMESH::double_array& theScaleFact,
3993 CORBA::Boolean theCopyGroups,
3994 const char* theMeshName)
3995 throw (SALOME::SALOME_Exception)
3997 SMESH_Mesh_i* mesh_i;
3998 SMESH::SMESH_Mesh_var mesh;
3999 { // open new scope to dump "MakeMesh" command
4000 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4002 TPythonDump pydump; // to prevent dump at mesh creation
4003 mesh = makeMesh( theMeshName );
4004 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4008 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4009 mesh_i->CreateGroupServants();
4011 if ( !myIsPreviewMode )
4012 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4013 << theObject << ", "
4015 << TVar( theScaleFact ) << ", "
4016 << theCopyGroups << ", '"
4017 << theMeshName << "' )";
4021 if (!myIsPreviewMode && mesh_i)
4022 mesh_i->GetGroups();
4024 return mesh._retn();
4027 //================================================================================
4029 * \brief Make an offset mesh from a source 2D mesh
4030 * \param [inout] theObject - source mesh. New elements are added to this mesh
4031 * if \a theMeshName is empty.
4032 * \param [in] theValue - offset value
4033 * \param [in] theCopyGroups - to generate groups
4034 * \param [in] theMeshName - optional name of a new mesh
4035 * \param [out] theGroups - new groups
4036 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4038 //================================================================================
4040 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4041 CORBA::Double theValue,
4042 CORBA::Boolean theCopyGroups,
4043 CORBA::Boolean theCopyElements,
4044 const char* theMeshName,
4045 SMESH::ListOfGroups_out theGroups)
4046 throw (SALOME::SALOME_Exception)
4051 SMESHDS_Mesh* aMeshDS = getMeshDS();
4053 SMESH::SMESH_Mesh_var mesh_var;
4054 ::SMESH_MeshEditor::PGroupIDs groupIds;
4058 TIDSortedElemSet elements, copyElements;
4059 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4060 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4063 SMESH_Mesh* tgtMesh = 0;
4064 if ( myIsPreviewMode )
4066 TPreviewMesh * tmpMesh = getPreviewMesh();
4068 tmpMesh->Copy( elements, copyElements );
4069 elements.swap( copyElements );
4070 theCopyGroups = false;
4071 theCopyElements = false;
4076 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4077 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4078 tgtMesh = & mesh_i->GetImpl();
4080 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4081 theCopyGroups, theCopyElements, !myIsPreviewMode );
4083 tgtMesh->GetMeshDS()->Modified();
4086 if ( myIsPreviewMode )
4088 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4092 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4094 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4096 // new mesh empty, remove it
4097 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4098 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4099 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4100 builder->RemoveObjectWithChildren( meshSO );
4101 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4104 // result of Offset() is a tuple (mesh, groups)
4105 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4106 else pyDump << mesh_var << ", ";
4107 pyDump << theGroups << " = " << this << ".Offset( "
4108 << theObject << ", "
4110 << theCopyGroups << ", "
4111 << theCopyElements << ", "
4112 << "'" << theMeshName<< "')";
4115 return mesh_var._retn();
4117 SMESH_CATCH( SMESH::throwCorbaException );
4118 return SMESH::SMESH_Mesh::_nil();
4121 //=======================================================================
4122 //function : findCoincidentNodes
4124 //=======================================================================
4126 void SMESH_MeshEditor_i::
4127 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4128 CORBA::Double Tolerance,
4129 SMESH::array_of_long_array_out GroupsOfNodes,
4130 CORBA::Boolean SeparateCornersAndMedium)
4132 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4133 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4135 GroupsOfNodes = new SMESH::array_of_long_array;
4136 GroupsOfNodes->length( aListOfListOfNodes.size() );
4137 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4138 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4140 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4141 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4142 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4143 aGroup.length( aListOfNodes.size() );
4144 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4145 aGroup[ j ] = (*lIt)->GetID();
4149 //=======================================================================
4150 //function : FindCoincidentNodes
4152 //=======================================================================
4154 void SMESH_MeshEditor_i::
4155 FindCoincidentNodes (CORBA::Double Tolerance,
4156 SMESH::array_of_long_array_out GroupsOfNodes,
4157 CORBA::Boolean SeparateCornersAndMedium)
4158 throw (SALOME::SALOME_Exception)
4163 TIDSortedNodeSet nodes; // no input nodes
4164 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4166 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4167 << Tolerance << ", "
4168 << SeparateCornersAndMedium << " )";
4170 SMESH_CATCH( SMESH::throwCorbaException );
4173 //=======================================================================
4174 //function : FindCoincidentNodesOnPart
4176 //=======================================================================
4178 void SMESH_MeshEditor_i::
4179 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4180 CORBA::Double Tolerance,
4181 SMESH::array_of_long_array_out GroupsOfNodes,
4182 CORBA::Boolean SeparateCornersAndMedium)
4183 throw (SALOME::SALOME_Exception)
4188 TIDSortedNodeSet nodes;
4189 prepareIdSource( theObject );
4190 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4192 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4194 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4196 << Tolerance << ", "
4197 << SeparateCornersAndMedium << " )";
4199 SMESH_CATCH( SMESH::throwCorbaException );
4202 //================================================================================
4204 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4205 * ExceptSubMeshOrGroups
4207 //================================================================================
4209 void SMESH_MeshEditor_i::
4210 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4211 CORBA::Double theTolerance,
4212 SMESH::array_of_long_array_out theGroupsOfNodes,
4213 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4214 CORBA::Boolean theSeparateCornersAndMedium)
4215 throw (SALOME::SALOME_Exception)
4220 TIDSortedNodeSet nodes;
4221 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4223 prepareIdSource( theObjects[i] );
4224 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4226 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4228 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4230 while ( nodeIt->more() )
4231 nodes.erase( cast2Node( nodeIt->next() ));
4233 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4235 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4236 << theObjects <<", "
4237 << theTolerance << ", "
4238 << theExceptSubMeshOrGroups << ", "
4239 << theSeparateCornersAndMedium << " )";
4241 SMESH_CATCH( SMESH::throwCorbaException );
4244 //=======================================================================
4245 //function : MergeNodes
4247 //=======================================================================
4249 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4250 const SMESH::ListOfIDSources& NodesToKeep,
4251 CORBA::Boolean AvoidMakingHoles)
4252 throw (SALOME::SALOME_Exception)
4257 SMESHDS_Mesh* aMesh = getMeshDS();
4259 TPythonDump aTPythonDump;
4260 aTPythonDump << this << ".MergeNodes([";
4262 TIDSortedNodeSet setOfNodesToKeep;
4263 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4265 prepareIdSource( NodesToKeep[i] );
4266 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4267 while ( nodeIt->more() )
4268 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4271 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4272 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4274 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4275 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4276 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4277 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4279 CORBA::Long index = aNodeGroup[ j ];
4280 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4282 if ( setOfNodesToKeep.count( node ))
4283 aListOfNodes.push_front( node );
4285 aListOfNodes.push_back( node );
4288 if ( aListOfNodes.size() < 2 )
4289 aListOfListOfNodes.pop_back();
4291 if ( i > 0 ) aTPythonDump << ", ";
4292 aTPythonDump << aNodeGroup;
4295 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4297 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4299 declareMeshModified( /*isReComputeSafe=*/false );
4301 SMESH_CATCH( SMESH::throwCorbaException );
4304 //=======================================================================
4305 //function : FindEqualElements
4307 //=======================================================================
4309 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4310 const SMESH::ListOfIDSources& theExceptObjects,
4311 SMESH::array_of_long_array_out theGroupsOfElementsID)
4312 throw (SALOME::SALOME_Exception)
4317 theGroupsOfElementsID = new SMESH::array_of_long_array;
4319 TIDSortedElemSet elems;
4320 bool hasOkObject = false;
4321 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4323 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4325 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4326 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4327 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4333 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4335 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4336 while ( elemIt->more() )
4337 elems.erase( elemIt->next() );
4340 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4341 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4343 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4345 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4346 aListOfListOfElementsID.begin();
4347 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4349 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4350 list<int>& listOfIDs = *arraysIt;
4351 aGroup.length( listOfIDs.size() );
4352 list<int>::iterator idIt = listOfIDs.begin();
4353 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4354 aGroup[ k ] = *idIt;
4357 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4358 << theObjects << ", "
4359 << theExceptObjects << " )";
4362 SMESH_CATCH( SMESH::throwCorbaException );
4365 //=======================================================================
4366 //function : MergeElements
4368 //=======================================================================
4370 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4371 const SMESH::ListOfIDSources& theElementsToKeep)
4372 throw (SALOME::SALOME_Exception)
4377 TPythonDump aTPythonDump;
4378 aTPythonDump << this << ".MergeElements( [";
4380 NCollection_Map< int > idsToKeep;
4381 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4383 if ( CORBA::is_nil( theElementsToKeep[i] ))
4385 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4386 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4388 SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs();
4389 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4390 idsToKeep.Add( elementsId[ j ]);
4393 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4395 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4397 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4398 aListOfListOfElementsID.push_back( list< int >() );
4399 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4400 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4402 CORBA::Long id = anElemsIDGroup[ j ];
4403 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4404 else aListOfElemsID.push_back( id );
4406 if ( aListOfElemsID.size() < 2 )
4407 aListOfListOfElementsID.pop_back();
4408 if ( i > 0 ) aTPythonDump << ", ";
4409 aTPythonDump << anElemsIDGroup;
4412 getEditor().MergeElements(aListOfListOfElementsID);
4414 declareMeshModified( /*isReComputeSafe=*/true );
4416 aTPythonDump << "], " << theElementsToKeep << " )";
4418 SMESH_CATCH( SMESH::throwCorbaException );
4421 //=======================================================================
4422 //function : MergeEqualElements
4424 //=======================================================================
4426 void SMESH_MeshEditor_i::MergeEqualElements()
4427 throw (SALOME::SALOME_Exception)
4432 getEditor().MergeEqualElements();
4434 declareMeshModified( /*isReComputeSafe=*/true );
4436 TPythonDump() << this << ".MergeEqualElements()";
4438 SMESH_CATCH( SMESH::throwCorbaException );
4441 //=============================================================================
4443 * Move the node to a given point
4445 //=============================================================================
4447 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4451 throw (SALOME::SALOME_Exception)
4454 initData(/*deleteSearchers=*/false);
4456 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4460 if ( theNodeSearcher )
4461 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4463 if ( myIsPreviewMode ) // make preview data
4465 // in a preview mesh, make edges linked to a node
4466 TPreviewMesh& tmpMesh = *getPreviewMesh();
4467 TIDSortedElemSet linkedNodes;
4468 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4469 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4470 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4471 for ( ; nIt != linkedNodes.end(); ++nIt )
4473 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4474 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4478 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4479 // fill preview data
4481 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4482 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4484 getMeshDS()->MoveNode(node, x, y, z);
4486 if ( !myIsPreviewMode )
4488 // Update Python script
4489 TPythonDump() << "isDone = " << this << ".MoveNode( "
4490 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4491 declareMeshModified( /*isReComputeSafe=*/false );
4494 SMESH_CATCH( SMESH::throwCorbaException );
4499 //================================================================================
4501 * \brief Return ID of node closest to a given point
4503 //================================================================================
4505 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4508 throw (SALOME::SALOME_Exception)
4511 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4513 if ( !theNodeSearcher ) {
4514 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4517 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4518 return node->GetID();
4520 SMESH_CATCH( SMESH::throwCorbaException );
4524 //================================================================================
4526 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4527 * move the node closest to the point to point's location and return ID of the node
4529 //================================================================================
4531 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4534 CORBA::Long theNodeID)
4535 throw (SALOME::SALOME_Exception)
4538 // We keep theNodeSearcher until any mesh modification:
4539 // 1) initData() deletes theNodeSearcher at any edition,
4540 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4542 initData(/*deleteSearchers=*/false);
4544 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4546 int nodeID = theNodeID;
4547 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4548 if ( !node ) // preview moving node
4550 if ( !theNodeSearcher ) {
4551 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4554 node = theNodeSearcher->FindClosestTo( p );
4557 nodeID = node->GetID();
4558 if ( myIsPreviewMode ) // make preview data
4560 // in a preview mesh, make edges linked to a node
4561 TPreviewMesh tmpMesh = *getPreviewMesh();
4562 TIDSortedElemSet linkedNodes;
4563 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4564 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4565 for ( ; nIt != linkedNodes.end(); ++nIt )
4567 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4568 tmpMesh.Copy( &edge );
4571 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4573 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4574 // fill preview data
4576 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4578 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4582 getMeshDS()->MoveNode(node, x, y, z);
4586 if ( !myIsPreviewMode )
4588 TPythonDump() << "nodeID = " << this
4589 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4590 << ", " << nodeID << " )";
4592 declareMeshModified( /*isReComputeSafe=*/false );
4597 SMESH_CATCH( SMESH::throwCorbaException );
4601 //=======================================================================
4603 * Return elements of given type where the given point is IN or ON.
4605 * 'ALL' type means elements of any type excluding nodes
4607 //=======================================================================
4609 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4612 SMESH::ElementType type)
4613 throw (SALOME::SALOME_Exception)
4616 SMESH::long_array_var res = new SMESH::long_array;
4617 vector< const SMDS_MeshElement* > foundElems;
4619 theSearchersDeleter.Set( myMesh );
4620 if ( !theElementSearcher ) {
4621 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4623 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4624 SMDSAbs_ElementType( type ),
4626 res->length( foundElems.size() );
4627 for ( size_t i = 0; i < foundElems.size(); ++i )
4628 res[i] = foundElems[i]->GetID();
4632 SMESH_CATCH( SMESH::throwCorbaException );
4636 //=======================================================================
4637 //function : FindAmongElementsByPoint
4638 //purpose : Searching among the given elements, return elements of given type
4639 // where the given point is IN or ON.
4640 // 'ALL' type means elements of any type excluding nodes
4641 //=======================================================================
4644 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4648 SMESH::ElementType type)
4649 throw (SALOME::SALOME_Exception)
4652 SMESH::long_array_var res = new SMESH::long_array;
4654 prepareIdSource( elementIDs );
4655 if ( type != SMESH::NODE )
4657 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4658 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4659 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4660 type != types[0] ) // but search of elements of dim > 0
4664 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4665 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4666 if ( mesh_i != myMesh_i )
4668 SMESH::SMESH_MeshEditor_var editor=
4669 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4670 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4673 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4674 return FindElementsByPoint( x,y,z, type );
4676 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4678 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4679 if ( !theElementSearcher )
4681 // create a searcher from elementIDs
4682 SMDS_ElemIteratorPtr elemIt;
4683 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4685 //prepareIdSource( elementIDs );
4686 elemIt = myMesh_i->GetElements( elementIDs, type );
4690 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4693 vector< const SMDS_MeshElement* > foundElems;
4695 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4696 SMDSAbs_ElementType( type ),
4698 res->length( foundElems.size() );
4699 for ( size_t i = 0; i < foundElems.size(); ++i )
4700 res[i] = foundElems[i]->GetID();
4704 SMESH_CATCH( SMESH::throwCorbaException );
4708 //=======================================================================
4709 //function : ProjectPoint
4710 //purpose : Project a point to a mesh object.
4711 // Return ID of an element of given type where the given point is projected
4712 // and coordinates of the projection point.
4713 // In the case if nothing found, return -1 and []
4714 //=======================================================================
4716 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4719 SMESH::ElementType type,
4720 SMESH::SMESH_IDSource_ptr meshObject,
4721 SMESH::double_array_out projecton)
4722 throw (SALOME::SALOME_Exception)
4724 if ( CORBA::is_nil( meshObject ))
4725 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4729 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4730 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4731 if ( mesh_i != myMesh_i )
4733 SMESH::SMESH_MeshEditor_var editor=
4734 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4735 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4739 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4740 if ( !theElementSearcher )
4742 // create a searcher from meshObject
4744 SMDS_ElemIteratorPtr elemIt;
4745 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4747 prepareIdSource( meshObject );
4748 elemIt = myMesh_i->GetElements( meshObject, type );
4752 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4755 const SMDS_MeshElement* elem = 0;
4756 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4757 SMDSAbs_ElementType( type ),
4760 projecton = new SMESH::double_array();
4761 if ( elem && !elem->IsNull() )
4763 projecton->length( 3 );
4764 projecton[0] = pProj.X();
4765 projecton[1] = pProj.Y();
4766 projecton[2] = pProj.Z();
4767 return elem->GetID();
4770 SMESH_CATCH( SMESH::throwCorbaException );
4774 //=======================================================================
4775 //function : GetPointState
4776 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4777 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4778 //=======================================================================
4780 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4783 throw (SALOME::SALOME_Exception)
4786 theSearchersDeleter.Set( myMesh );
4787 if ( !theElementSearcher ) {
4788 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4790 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4792 SMESH_CATCH( SMESH::throwCorbaException );
4796 //=======================================================================
4797 //function : IsManifold
4798 //purpose : Check if a 2D mesh is manifold
4799 //=======================================================================
4801 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4802 throw (SALOME::SALOME_Exception)
4804 bool isManifold = true;
4807 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4808 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4810 /*closedOnly=*/true,
4812 SMESH_CATCH( SMESH::throwCorbaException );
4817 //=======================================================================
4818 //function : IsCoherentOrientation2D
4819 //purpose : Check if orientation of 2D elements is coherent
4820 //=======================================================================
4822 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4823 throw (SALOME::SALOME_Exception)
4825 bool isGoodOri = true;
4828 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4829 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4831 /*closedOnly=*/true,
4834 SMESH_CATCH( SMESH::throwCorbaException );
4839 //=======================================================================
4840 //function : Get1DBranches
4841 //purpose : Partition given 1D elements into groups of contiguous edges.
4842 // A node where number of meeting edges != 2 is a group end.
4843 // An optional startNode is used to orient groups it belongs to.
4844 //return : a list of edge groups and a list of corresponding node groups.
4845 // If a group is closed, the first and last nodes of the group are same.
4846 //=======================================================================
4848 SMESH::array_of_long_array*
4849 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4850 CORBA::Long theStartNode,
4851 SMESH::array_of_long_array_out theNodeGroups )
4852 throw (SALOME::SALOME_Exception)
4854 if ( CORBA::is_nil( theEdges ))
4855 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4857 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4858 theNodeGroups = new SMESH::array_of_long_array;
4862 prepareIdSource( theEdges );
4864 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4865 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4866 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4869 getMeshDS()->FindNode( theStartNode ));
4871 edgeGroupArray->length( edgeBranches.size() );
4872 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4874 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4875 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4876 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4879 theNodeGroups->length( nodeBranches.size() );
4880 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4882 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4883 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4884 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4887 SMESH_CATCH( SMESH::throwCorbaException );
4889 return edgeGroupArray._retn();
4892 //=======================================================================
4893 //function : FindSharpEdges
4894 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4895 //=======================================================================
4897 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4898 CORBA::Boolean theAddExisting)
4899 throw (SALOME::SALOME_Exception)
4901 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4906 std::vector< SMESH_MeshAlgos::Edge > edges =
4907 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4909 if ( myIsPreviewMode ) // fill a preview mesh with edges
4911 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4912 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4913 for ( size_t i = 0; i < edges.size(); ++i )
4915 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4916 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4917 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4918 if ( edges[i]._medium )
4920 xyz1.Set( edges[i]._medium );
4921 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4922 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4926 mesh->GetMeshDS()->AddEdge( n1, n2 );
4932 resultEdges->length( edges.size() );
4933 for ( size_t i = 0; i < edges.size(); ++i )
4935 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4936 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4937 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4940 SMESH_CATCH( SMESH::throwCorbaException );
4941 return resultEdges._retn();
4944 //=======================================================================
4945 //function : FindFreeBorders
4946 //purpose : Returns all or only closed FreeBorder's.
4947 //=======================================================================
4949 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4950 throw (SALOME::SALOME_Exception)
4952 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4955 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4956 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4958 resBorders->length( foundFreeBordes.size() );
4959 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4961 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4962 SMESH::FreeBorder& bordOut = resBorders[i];
4963 bordOut.nodeIDs.length( bordNodes.size() );
4964 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4965 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4968 SMESH_CATCH( SMESH::throwCorbaException );
4970 return resBorders._retn();
4973 //=======================================================================
4974 //function : FillHole
4975 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4976 //=======================================================================
4978 SMESH::SMESH_Group_ptr
4979 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
4980 const char* theGroupName)
4981 throw (SALOME::SALOME_Exception)
4985 if ( theHole.nodeIDs.length() < 4 )
4986 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4987 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4988 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4989 "First and last nodes must be same", SALOME::BAD_PARAM);
4991 SMESH_MeshAlgos::TFreeBorder bordNodes;
4992 bordNodes.resize( theHole.nodeIDs.length() );
4993 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4995 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4996 if ( !bordNodes[ iN ] )
4997 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4998 << " does not exist", SALOME::BAD_PARAM);
5003 // prepare a preview mesh
5004 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5005 SMDS_Mesh* meshDS = getMeshDS();
5006 if ( myIsPreviewMode )
5008 // copy faces sharing nodes of theHole
5009 TIDSortedElemSet holeFaces;
5010 previewMesh = getPreviewMesh( SMDSAbs_Face );
5011 for ( size_t i = 0; i < bordNodes.size(); ++i )
5013 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5014 while ( fIt->more() )
5016 const SMDS_MeshElement* face = fIt->next();
5017 if ( holeFaces.insert( face ).second )
5018 previewMesh->Copy( face );
5020 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5021 ASSERT( bordNodes[i] );
5023 meshDS = previewMesh->GetMeshDS();
5027 std::vector<const SMDS_MeshElement*> newFaces;
5028 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5030 if ( myIsPreviewMode )
5033 previewMesh->Clear();
5034 for ( size_t i = 0; i < newFaces.size(); ++i )
5035 previewMesh->Copy( newFaces[i] );
5039 // return new faces via a group
5040 SMESH::SMESH_Group_var group;
5041 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5043 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5044 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5046 SMESH::SMESH_GroupBase_var g = groups[ i ];
5047 if ( g->GetType() != SMESH::FACE ) continue;
5048 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5049 if ( standalone->_is_nil() ) continue;
5050 CORBA::String_var name = g->GetName();
5051 if ( strcmp( theGroupName, name.in() ) == 0 )
5057 if ( group->_is_nil() )
5058 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5060 if ( !group->_is_nil() )
5062 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5063 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5064 for ( size_t i = 0; i < newFaces.size(); ++i )
5065 grpDS->Add( newFaces[ i ]);
5070 getEditor().ClearLastCreated();
5071 SMESH_SequenceOfElemPtr& aSeq =
5072 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5073 aSeq.swap( newFaces );
5076 if ( group->_is_nil() ) pyDump << "_group = ";
5077 else pyDump << group << " = ";
5078 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5080 return group._retn();
5083 SMESH_CATCH( SMESH::throwCorbaException );
5085 return SMESH::SMESH_Group::_nil();
5088 //=======================================================================
5089 //function : convError
5091 //=======================================================================
5093 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5095 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5099 RETCASE( SEW_BORDER1_NOT_FOUND );
5100 RETCASE( SEW_BORDER2_NOT_FOUND );
5101 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5102 RETCASE( SEW_BAD_SIDE_NODES );
5103 RETCASE( SEW_VOLUMES_TO_SPLIT );
5104 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5105 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5106 RETCASE( SEW_BAD_SIDE1_NODES );
5107 RETCASE( SEW_BAD_SIDE2_NODES );
5108 RETCASE( SEW_INTERNAL_ERROR );
5110 return SMESH::SMESH_MeshEditor::SEW_OK;
5113 //=======================================================================
5115 * Returns groups of FreeBorder's coincident within the given tolerance.
5116 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5117 * to free borders being compared is used.
5119 //=======================================================================
5121 SMESH::CoincidentFreeBorders*
5122 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5124 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5128 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5129 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5131 // copy free borders
5132 aCFB->borders.length( cfb._borders.size() );
5133 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5135 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5136 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5137 aBRD.nodeIDs.length( nodes.size() );
5138 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5139 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5142 // copy coincident parts
5143 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5144 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5146 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5147 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5148 aGRP.length( grp.size() );
5149 for ( size_t iP = 0; iP < grp.size(); ++iP )
5151 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5152 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5153 aPART.border = part._border;
5154 aPART.node1 = part._node1;
5155 aPART.node2 = part._node2;
5156 aPART.nodeLast = part._nodeLast;
5159 SMESH_CATCH( SMESH::doNothing );
5161 TPythonDump() << "CoincidentFreeBorders = "
5162 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5164 return aCFB._retn();
5167 //=======================================================================
5169 * Sew FreeBorder's of each group
5171 //=======================================================================
5173 CORBA::Short SMESH_MeshEditor_i::
5174 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5175 CORBA::Boolean createPolygons,
5176 CORBA::Boolean createPolyhedra)
5177 throw (SALOME::SALOME_Exception)
5179 CORBA::Short nbSewed = 0;
5181 SMESH_MeshAlgos::TFreeBorderVec groups;
5182 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5184 // check the input and collect nodes
5185 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5187 borderNodes.clear();
5188 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5189 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5191 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5192 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5193 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5195 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5197 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5198 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5199 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5200 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5201 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5202 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5204 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5205 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5206 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5207 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5209 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5211 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5213 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5215 borderNodes.push_back( n1 );
5216 borderNodes.push_back( n2 );
5217 borderNodes.push_back( n3 );
5219 groups.push_back( borderNodes );
5222 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5223 // to get nodes that replace other nodes during merge we create 0D elements
5224 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5227 vector< const SMDS_MeshElement* > tmp0Delems;
5228 for ( size_t i = 0; i < groups.size(); ++i )
5230 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5231 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5233 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5235 tmp0Delems.push_back( it0D->next() );
5237 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5241 // cout << endl << "INIT" << endl;
5242 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5244 // cout << i << " ";
5245 // if ( i % 3 == 0 ) cout << "^ ";
5246 // tmp0Delems[i]->GetNode(0)->Print( cout );
5251 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5253 for ( size_t i = 0; i < groups.size(); ++i )
5255 bool isBordToBord = true;
5256 bool groupSewed = false;
5257 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5258 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5260 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5261 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5262 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5264 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5265 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5266 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5268 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5271 // TIDSortedElemSet emptySet, avoidSet;
5272 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5274 // cout << "WRONG 2nd 1" << endl;
5275 // n0->Print( cout );
5276 // n1->Print( cout );
5278 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5280 // cout << "WRONG 2nd 2" << endl;
5281 // n3->Print( cout );
5282 // n4->Print( cout );
5285 if ( !isBordToBord )
5287 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5288 n2 = 0; // and n2 is not used
5290 // 1st border moves to 2nd
5291 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5293 /*2ndIsFreeBorder=*/ isBordToBord,
5294 createPolygons, createPolyhedra);
5295 groupSewed = ( res == ok );
5297 isBordToBord = false;
5298 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5299 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5301 // cout << t << " ";
5302 // if ( t % 3 == 0 ) cout << "^ ";
5303 // tmp0Delems[t]->GetNode(0)->Print( cout );
5306 i0D += nodes.size();
5307 nbSewed += groupSewed;
5310 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5311 << freeBorders << ", "
5312 << createPolygons << ", "
5313 << createPolyhedra << " )";
5315 SMESH_CATCH( SMESH::doNothing );
5317 declareMeshModified( /*isReComputeSafe=*/false );
5319 // remove tmp 0D elements
5321 set< const SMDS_MeshElement* > removed0D;
5322 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5324 if ( removed0D.insert( tmp0Delems[i] ).second )
5325 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5327 SMESH_CATCH( SMESH::throwCorbaException );
5332 //=======================================================================
5333 //function : SewFreeBorders
5335 //=======================================================================
5337 SMESH::SMESH_MeshEditor::Sew_Error
5338 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5339 CORBA::Long SecondNodeID1,
5340 CORBA::Long LastNodeID1,
5341 CORBA::Long FirstNodeID2,
5342 CORBA::Long SecondNodeID2,
5343 CORBA::Long LastNodeID2,
5344 CORBA::Boolean CreatePolygons,
5345 CORBA::Boolean CreatePolyedrs)
5346 throw (SALOME::SALOME_Exception)
5351 SMESHDS_Mesh* aMesh = getMeshDS();
5353 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5354 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5355 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5356 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5357 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5358 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5360 if (!aBorderFirstNode ||
5361 !aBorderSecondNode||
5363 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5364 if (!aSide2FirstNode ||
5365 !aSide2SecondNode ||
5367 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5369 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5370 << FirstNodeID1 << ", "
5371 << SecondNodeID1 << ", "
5372 << LastNodeID1 << ", "
5373 << FirstNodeID2 << ", "
5374 << SecondNodeID2 << ", "
5375 << LastNodeID2 << ", "
5376 << CreatePolygons<< ", "
5377 << CreatePolyedrs<< " )";
5379 SMESH::SMESH_MeshEditor::Sew_Error error =
5380 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5391 declareMeshModified( /*isReComputeSafe=*/false );
5394 SMESH_CATCH( SMESH::throwCorbaException );
5395 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5399 //=======================================================================
5400 //function : SewConformFreeBorders
5402 //=======================================================================
5404 SMESH::SMESH_MeshEditor::Sew_Error
5405 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5406 CORBA::Long SecondNodeID1,
5407 CORBA::Long LastNodeID1,
5408 CORBA::Long FirstNodeID2,
5409 CORBA::Long SecondNodeID2)
5410 throw (SALOME::SALOME_Exception)
5415 SMESHDS_Mesh* aMesh = getMeshDS();
5417 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5418 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5419 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5420 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5421 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5422 const SMDS_MeshNode* aSide2ThirdNode = 0;
5424 if (!aBorderFirstNode ||
5425 !aBorderSecondNode||
5427 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5428 if (!aSide2FirstNode ||
5430 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5432 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5433 << FirstNodeID1 << ", "
5434 << SecondNodeID1 << ", "
5435 << LastNodeID1 << ", "
5436 << FirstNodeID2 << ", "
5437 << SecondNodeID2 << " )";
5439 SMESH::SMESH_MeshEditor::Sew_Error error =
5440 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5449 declareMeshModified( /*isReComputeSafe=*/false );
5452 SMESH_CATCH( SMESH::throwCorbaException );
5453 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5457 //=======================================================================
5458 //function : SewBorderToSide
5460 //=======================================================================
5462 SMESH::SMESH_MeshEditor::Sew_Error
5463 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5464 CORBA::Long SecondNodeIDOnFreeBorder,
5465 CORBA::Long LastNodeIDOnFreeBorder,
5466 CORBA::Long FirstNodeIDOnSide,
5467 CORBA::Long LastNodeIDOnSide,
5468 CORBA::Boolean CreatePolygons,
5469 CORBA::Boolean CreatePolyedrs)
5470 throw (SALOME::SALOME_Exception)
5475 SMESHDS_Mesh* aMesh = getMeshDS();
5477 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5478 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5479 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5480 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5481 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5482 const SMDS_MeshNode* aSide2ThirdNode = 0;
5484 if (!aBorderFirstNode ||
5485 !aBorderSecondNode||
5487 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5488 if (!aSide2FirstNode ||
5490 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5492 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5493 << FirstNodeIDOnFreeBorder << ", "
5494 << SecondNodeIDOnFreeBorder << ", "
5495 << LastNodeIDOnFreeBorder << ", "
5496 << FirstNodeIDOnSide << ", "
5497 << LastNodeIDOnSide << ", "
5498 << CreatePolygons << ", "
5499 << CreatePolyedrs << ") ";
5501 SMESH::SMESH_MeshEditor::Sew_Error error =
5502 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5512 declareMeshModified( /*isReComputeSafe=*/false );
5515 SMESH_CATCH( SMESH::throwCorbaException );
5516 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5520 //=======================================================================
5521 //function : SewSideElements
5523 //=======================================================================
5525 SMESH::SMESH_MeshEditor::Sew_Error
5526 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5527 const SMESH::long_array& IDsOfSide2Elements,
5528 CORBA::Long NodeID1OfSide1ToMerge,
5529 CORBA::Long NodeID1OfSide2ToMerge,
5530 CORBA::Long NodeID2OfSide1ToMerge,
5531 CORBA::Long NodeID2OfSide2ToMerge)
5532 throw (SALOME::SALOME_Exception)
5537 SMESHDS_Mesh* aMesh = getMeshDS();
5539 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5540 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5541 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5542 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5544 if (!aFirstNode1ToMerge ||
5545 !aFirstNode2ToMerge )
5546 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5547 if (!aSecondNode1ToMerge||
5548 !aSecondNode2ToMerge)
5549 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5551 TIDSortedElemSet aSide1Elems, aSide2Elems;
5552 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5553 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5555 TPythonDump() << "error = " << this << ".SewSideElements( "
5556 << IDsOfSide1Elements << ", "
5557 << IDsOfSide2Elements << ", "
5558 << NodeID1OfSide1ToMerge << ", "
5559 << NodeID1OfSide2ToMerge << ", "
5560 << NodeID2OfSide1ToMerge << ", "
5561 << NodeID2OfSide2ToMerge << ")";
5563 SMESH::SMESH_MeshEditor::Sew_Error error =
5564 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5567 aSecondNode1ToMerge,
5568 aSecondNode2ToMerge));
5570 declareMeshModified( /*isReComputeSafe=*/false );
5573 SMESH_CATCH( SMESH::throwCorbaException );
5574 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5577 //================================================================================
5579 * \brief Set new nodes for given element
5580 * \param ide - element id
5581 * \param newIDs - new node ids
5582 * \retval CORBA::Boolean - true if result is OK
5584 //================================================================================
5586 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5587 const SMESH::long_array& newIDs)
5588 throw (SALOME::SALOME_Exception)
5593 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5594 if(!elem) return false;
5596 int nbn = newIDs.length();
5598 vector<const SMDS_MeshNode*> aNodes(nbn);
5601 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5604 aNodes[nbn1] = aNode;
5607 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5608 << ide << ", " << newIDs << " )";
5610 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5612 declareMeshModified( /*isReComputeSafe=*/ !res );
5616 SMESH_CATCH( SMESH::throwCorbaException );
5620 //=======================================================================
5622 * \brief Makes a part of the mesh quadratic or bi-quadratic
5624 //=======================================================================
5626 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5627 CORBA::Boolean theToBiQuad,
5628 SMESH::SMESH_IDSource_ptr theObject)
5629 throw (SALOME::SALOME_Exception)
5634 TIDSortedElemSet elems;
5636 if ( !( elemsOK = CORBA::is_nil( theObject )))
5638 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5639 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5643 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5644 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5646 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5647 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5649 declareMeshModified( /*isReComputeSafe=*/false );
5652 SMESH_CATCH( SMESH::throwCorbaException );
5655 //=======================================================================
5656 //function : ConvertFromQuadratic
5658 //=======================================================================
5660 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5661 throw (SALOME::SALOME_Exception)
5666 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5667 TPythonDump() << this << ".ConvertFromQuadratic()";
5668 declareMeshModified( /*isReComputeSafe=*/!isDone );
5671 SMESH_CATCH( SMESH::throwCorbaException );
5675 //=======================================================================
5676 //function : ConvertToQuadratic
5678 //=======================================================================
5680 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5681 throw (SALOME::SALOME_Exception)
5683 convertToQuadratic( theForce3d, false );
5684 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5687 //================================================================================
5689 * \brief Makes a part of the mesh quadratic
5691 //================================================================================
5693 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5694 SMESH::SMESH_IDSource_ptr theObject)
5695 throw (SALOME::SALOME_Exception)
5697 convertToQuadratic( theForce3d, false, theObject );
5698 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5701 //================================================================================
5703 * \brief Makes a part of the mesh bi-quadratic
5705 //================================================================================
5707 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5708 SMESH::SMESH_IDSource_ptr theObject)
5709 throw (SALOME::SALOME_Exception)
5711 convertToQuadratic( theForce3d, true, theObject );
5712 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5715 //================================================================================
5717 * \brief Makes a part of the mesh linear
5719 //================================================================================
5721 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5722 throw (SALOME::SALOME_Exception)
5729 TIDSortedElemSet elems;
5730 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5732 if ( elems.empty() )
5734 ConvertFromQuadratic();
5736 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5738 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5742 getEditor().ConvertFromQuadratic(elems);
5745 declareMeshModified( /*isReComputeSafe=*/false );
5747 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5749 SMESH_CATCH( SMESH::throwCorbaException );
5752 //=======================================================================
5753 //function : makeMesh
5754 //purpose : create a named imported mesh
5755 //=======================================================================
5757 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5759 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5760 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5761 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5762 gen->SetName( meshSO, theMeshName, "Mesh" );
5763 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5765 return mesh._retn();
5768 //=======================================================================
5769 //function : dumpGroupsList
5771 //=======================================================================
5773 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5774 const SMESH::ListOfGroups * theGroupList)
5776 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5777 if ( isDumpGroupList )
5778 theDumpPython << theGroupList << " = ";
5781 //================================================================================
5783 \brief Generates the unique group name.
5784 \param thePrefix name prefix
5787 //================================================================================
5789 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5791 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5792 set<std::string> groupNames;
5794 // Get existing group names
5795 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5796 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5797 if (CORBA::is_nil(aGroup))
5800 CORBA::String_var name = aGroup->GetName();
5801 groupNames.insert( name.in() );
5805 std::string name = thePrefix;
5808 while (!groupNames.insert(name).second)
5809 name = SMESH_Comment( thePrefix ) << "_" << index++;
5814 //================================================================================
5816 * \brief Prepare SMESH_IDSource for work
5818 //================================================================================
5820 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5822 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5824 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5825 filter->SetMesh( mesh );
5828 //================================================================================
5830 * \brief Retrieve elements of given type from SMESH_IDSource
5832 //================================================================================
5834 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5835 const SMESHDS_Mesh* theMeshDS,
5836 TIDSortedElemSet& theElemSet,
5837 const SMDSAbs_ElementType theType,
5838 const bool emptyIfIsMesh,
5839 IDSource_Error* error)
5842 if ( error ) *error = IDSource_OK;
5844 if ( CORBA::is_nil( theIDSource ))
5846 if ( error ) *error = IDSource_INVALID;
5849 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5851 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5852 *error = IDSource_EMPTY;
5855 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5857 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5858 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5859 if ( mesh_i && mesh_i != myMesh_i )
5862 *error = IDSource_INVALID;
5866 prepareIdSource( theIDSource );
5867 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5868 if ( anIDs->length() == 0 )
5870 if ( error ) *error = IDSource_EMPTY;
5873 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5874 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5876 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5878 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5882 if ( error ) *error = IDSource_INVALID;
5888 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5889 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5891 if ( error ) *error = IDSource_INVALID;
5898 //================================================================================
5900 * \brief Duplicates given elements, i.e. creates new elements based on the
5901 * same nodes as the given ones.
5902 * \param theElements - container of elements to duplicate.
5903 * \param theGroupName - a name of group to contain the generated elements.
5904 * If a group with such a name already exists, the new elements
5905 * are added to the existing group, else a new group is created.
5906 * If \a theGroupName is empty, new elements are not added
5908 * \return a group where the new elements are added. NULL if theGroupName == "".
5911 //================================================================================
5913 SMESH::SMESH_Group_ptr
5914 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5915 const char* theGroupName)
5916 throw (SALOME::SALOME_Exception)
5918 SMESH::SMESH_Group_var newGroup;
5925 TIDSortedElemSet elems;
5926 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5928 getEditor().DoubleElements( elems );
5930 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5933 SMESH::ElementType type =
5934 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5935 // find existing group
5936 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5937 for ( size_t i = 0; i < groups->length(); ++i )
5938 if ( groups[i]->GetType() == type )
5940 CORBA::String_var name = groups[i]->GetName();
5941 if ( strcmp( name, theGroupName ) == 0 ) {
5942 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5946 // create a new group
5947 if ( newGroup->_is_nil() )
5948 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5950 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5952 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5953 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5954 for ( size_t i = 0; i < aSeq.size(); i++ )
5955 groupDS->SMDSGroup().Add( aSeq[i] );
5960 if ( !newGroup->_is_nil() )
5961 pyDump << newGroup << " = ";
5962 pyDump << this << ".DoubleElements( "
5963 << theElements << ", " << "'" << theGroupName <<"')";
5965 SMESH_CATCH( SMESH::throwCorbaException );
5967 return newGroup._retn();
5970 //================================================================================
5972 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5973 \param theNodes - identifiers of nodes to be doubled
5974 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5975 nodes. If list of element identifiers is empty then nodes are doubled but
5976 they not assigned to elements
5977 \return TRUE if operation has been completed successfully, FALSE otherwise
5978 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5980 //================================================================================
5982 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5983 const SMESH::long_array& theModifiedElems )
5984 throw (SALOME::SALOME_Exception)
5989 list< int > aListOfNodes;
5991 for ( i = 0, n = theNodes.length(); i < n; i++ )
5992 aListOfNodes.push_back( theNodes[ i ] );
5994 list< int > aListOfElems;
5995 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5996 aListOfElems.push_back( theModifiedElems[ i ] );
5998 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6000 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6002 // Update Python script
6003 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6007 SMESH_CATCH( SMESH::throwCorbaException );
6011 //================================================================================
6013 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6014 This method provided for convenience works as DoubleNodes() described above.
6015 \param theNodeId - identifier of node to be doubled.
6016 \param theModifiedElems - identifiers of elements to be updated.
6017 \return TRUE if operation has been completed successfully, FALSE otherwise
6018 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6020 //================================================================================
6022 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
6023 const SMESH::long_array& theModifiedElems )
6024 throw (SALOME::SALOME_Exception)
6027 SMESH::long_array_var aNodes = new SMESH::long_array;
6028 aNodes->length( 1 );
6029 aNodes[ 0 ] = theNodeId;
6031 TPythonDump pyDump; // suppress dump by the next line
6033 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6035 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6039 SMESH_CATCH( SMESH::throwCorbaException );
6043 //================================================================================
6045 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6046 This method provided for convenience works as DoubleNodes() described above.
6047 \param theNodes - group of nodes to be doubled.
6048 \param theModifiedElems - group of elements to be updated.
6049 \return TRUE if operation has been completed successfully, FALSE otherwise
6050 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6052 //================================================================================
6054 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6055 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6056 throw (SALOME::SALOME_Exception)
6059 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6062 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6063 SMESH::long_array_var aModifiedElems;
6064 if ( !CORBA::is_nil( theModifiedElems ) )
6065 aModifiedElems = theModifiedElems->GetListOfID();
6067 aModifiedElems = new SMESH::long_array;
6069 TPythonDump pyDump; // suppress dump by the next line
6071 bool done = DoubleNodes( aNodes, aModifiedElems );
6073 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6077 SMESH_CATCH( SMESH::throwCorbaException );
6081 //================================================================================
6083 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6084 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6085 * \param theNodes - group of nodes to be doubled.
6086 * \param theModifiedElems - group of elements to be updated.
6087 * \return a new group with newly created nodes
6088 * \sa DoubleNodeGroup()
6090 //================================================================================
6092 SMESH::SMESH_Group_ptr
6093 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6094 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6095 throw (SALOME::SALOME_Exception)
6098 SMESH::SMESH_Group_var aNewGroup;
6100 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6101 return aNewGroup._retn();
6104 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6105 SMESH::long_array_var aModifiedElems;
6106 if ( !CORBA::is_nil( theModifiedElems ) )
6107 aModifiedElems = theModifiedElems->GetListOfID();
6109 aModifiedElems = new SMESH::long_array;
6110 aModifiedElems->length( 0 );
6113 TPythonDump pyDump; // suppress dump by the next line
6115 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6118 // Create group with newly created nodes
6119 SMESH::long_array_var anIds = GetLastCreatedNodes();
6120 if (anIds->length() > 0) {
6121 std::string anUnindexedName (theNodes->GetName());
6122 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6123 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6124 aNewGroup->Add(anIds);
6125 pyDump << aNewGroup << " = ";
6129 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6130 << theModifiedElems << " )";
6132 return aNewGroup._retn();
6134 SMESH_CATCH( SMESH::throwCorbaException );
6138 //================================================================================
6140 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6141 This method provided for convenience works as DoubleNodes() described above.
6142 \param theNodes - list of groups of nodes to be doubled
6143 \param theModifiedElems - list of groups of elements to be updated.
6144 \return TRUE if operation has been completed successfully, FALSE otherwise
6145 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6147 //================================================================================
6149 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6150 const SMESH::ListOfGroups& theModifiedElems )
6151 throw (SALOME::SALOME_Exception)
6156 std::list< int > aNodes;
6158 for ( i = 0, n = theNodes.length(); i < n; i++ )
6160 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6161 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6163 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6164 for ( j = 0, m = aCurr->length(); j < m; j++ )
6165 aNodes.push_back( aCurr[ j ] );
6169 std::list< int > anElems;
6170 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6172 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6173 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6175 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6176 for ( j = 0, m = aCurr->length(); j < m; j++ )
6177 anElems.push_back( aCurr[ j ] );
6181 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6183 declareMeshModified( /*isReComputeSafe=*/false );
6185 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6189 SMESH_CATCH( SMESH::throwCorbaException );
6193 //================================================================================
6195 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6196 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6197 * \param theNodes - group of nodes to be doubled.
6198 * \param theModifiedElems - group of elements to be updated.
6199 * \return a new group with newly created nodes
6200 * \sa DoubleNodeGroups()
6202 //================================================================================
6204 SMESH::SMESH_Group_ptr
6205 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6206 const SMESH::ListOfGroups& theModifiedElems )
6207 throw (SALOME::SALOME_Exception)
6209 SMESH::SMESH_Group_var aNewGroup;
6211 TPythonDump pyDump; // suppress dump by the next line
6213 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6217 // Create group with newly created nodes
6218 SMESH::long_array_var anIds = GetLastCreatedNodes();
6219 if (anIds->length() > 0) {
6220 std::string anUnindexedName (theNodes[0]->GetName());
6221 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6222 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6223 aNewGroup->Add(anIds);
6224 pyDump << aNewGroup << " = ";
6228 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6229 << theModifiedElems << " )";
6231 return aNewGroup._retn();
6235 //================================================================================
6237 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6238 \param theElems - the list of elements (edges or faces) to be replicated
6239 The nodes for duplication could be found from these elements
6240 \param theNodesNot - list of nodes to NOT replicate
6241 \param theAffectedElems - the list of elements (cells and edges) to which the
6242 replicated nodes should be associated to.
6243 \return TRUE if operation has been completed successfully, FALSE otherwise
6244 \sa DoubleNodeGroup(), DoubleNodeGroups()
6246 //================================================================================
6248 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6249 const SMESH::long_array& theNodesNot,
6250 const SMESH::long_array& theAffectedElems )
6251 throw (SALOME::SALOME_Exception)
6256 SMESHDS_Mesh* aMeshDS = getMeshDS();
6257 TIDSortedElemSet anElems, aNodes, anAffected;
6258 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6259 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6260 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6262 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6264 // Update Python script
6265 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6266 << theNodesNot << ", " << theAffectedElems << " )";
6268 declareMeshModified( /*isReComputeSafe=*/false );
6271 SMESH_CATCH( SMESH::throwCorbaException );
6275 //================================================================================
6277 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6278 \param theElems - the list of elements (edges or faces) to be replicated
6279 The nodes for duplication could be found from these elements
6280 \param theNodesNot - list of nodes to NOT replicate
6281 \param theShape - shape to detect affected elements (element which geometric center
6282 located on or inside shape).
6283 The replicated nodes should be associated to affected elements.
6284 \return TRUE if operation has been completed successfully, FALSE otherwise
6285 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6287 //================================================================================
6289 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6290 const SMESH::long_array& theNodesNot,
6291 GEOM::GEOM_Object_ptr theShape )
6292 throw (SALOME::SALOME_Exception)
6298 SMESHDS_Mesh* aMeshDS = getMeshDS();
6299 TIDSortedElemSet anElems, aNodes;
6300 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6301 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6303 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6304 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6306 // Update Python script
6307 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6308 << theNodesNot << ", " << theShape << " )";
6310 declareMeshModified( /*isReComputeSafe=*/false );
6313 SMESH_CATCH( SMESH::throwCorbaException );
6317 //================================================================================
6319 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6320 \param theElems - group of of elements (edges or faces) to be replicated
6321 \param theNodesNot - group of nodes not to replicated
6322 \param theAffectedElems - group of elements to which the replicated nodes
6323 should be associated to.
6324 \return TRUE if operation has been completed successfully, FALSE otherwise
6325 \sa DoubleNodes(), DoubleNodeGroups()
6327 //================================================================================
6330 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6331 SMESH::SMESH_GroupBase_ptr theNodesNot,
6332 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6333 throw (SALOME::SALOME_Exception)
6336 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6342 SMESHDS_Mesh* aMeshDS = getMeshDS();
6343 TIDSortedElemSet anElems, aNodes, anAffected;
6344 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6345 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6346 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6348 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6350 // Update Python script
6351 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6352 << theNodesNot << ", " << theAffectedElems << " )";
6354 declareMeshModified( /*isReComputeSafe=*/false );
6357 SMESH_CATCH( SMESH::throwCorbaException );
6361 //================================================================================
6363 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6364 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6365 * \param theElems - group of of elements (edges or faces) to be replicated
6366 * \param theNodesNot - group of nodes not to replicated
6367 * \param theAffectedElems - group of elements to which the replicated nodes
6368 * should be associated to.
6369 * \return a new group with newly created elements
6370 * \sa DoubleNodeElemGroup()
6372 //================================================================================
6374 SMESH::SMESH_Group_ptr
6375 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6376 SMESH::SMESH_GroupBase_ptr theNodesNot,
6377 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6378 throw (SALOME::SALOME_Exception)
6381 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6385 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6386 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6388 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6390 << theNodesNot << ", "
6391 << theAffectedElems << " )";
6393 return elemGroup._retn();
6396 //================================================================================
6398 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6399 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6400 * \param theElems - group of of elements (edges or faces) to be replicated
6401 * \param theNodesNot - group of nodes not to replicated
6402 * \param theAffectedElems - group of elements to which the replicated nodes
6403 * should be associated to.
6404 * \return a new group with newly created elements
6405 * \sa DoubleNodeElemGroup()
6407 //================================================================================
6409 SMESH::ListOfGroups*
6410 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6411 SMESH::SMESH_GroupBase_ptr theNodesNot,
6412 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6413 CORBA::Boolean theElemGroupNeeded,
6414 CORBA::Boolean theNodeGroupNeeded)
6415 throw (SALOME::SALOME_Exception)
6418 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6419 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6420 aTwoGroups->length( 2 );
6422 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6423 return aTwoGroups._retn();
6428 SMESHDS_Mesh* aMeshDS = getMeshDS();
6429 TIDSortedElemSet anElems, aNodes, anAffected;
6430 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6431 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6432 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6435 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6437 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6443 // Create group with newly created elements
6444 CORBA::String_var elemGroupName = theElems->GetName();
6445 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6446 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6448 SMESH::long_array_var anIds = GetLastCreatedElems();
6449 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6450 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6451 aNewElemGroup->Add(anIds);
6453 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6455 SMESH::long_array_var anIds = GetLastCreatedNodes();
6456 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6457 aNewNodeGroup->Add(anIds);
6461 // Update Python script
6464 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6465 else pyDump << aNewElemGroup << ", ";
6466 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6467 else pyDump << aNewNodeGroup << " ] = ";
6469 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6470 << theNodesNot << ", "
6471 << theAffectedElems << ", "
6472 << theElemGroupNeeded << ", "
6473 << theNodeGroupNeeded <<" )";
6475 aTwoGroups[0] = aNewElemGroup._retn();
6476 aTwoGroups[1] = aNewNodeGroup._retn();
6477 return aTwoGroups._retn();
6479 SMESH_CATCH( SMESH::throwCorbaException );
6483 //================================================================================
6485 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6486 \param theElems - group of of elements (edges or faces) to be replicated
6487 \param theNodesNot - group of nodes not to replicated
6488 \param theShape - shape to detect affected elements (element which geometric center
6489 located on or inside shape).
6490 The replicated nodes should be associated to affected elements.
6491 \return TRUE if operation has been completed successfully, FALSE otherwise
6492 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6494 //================================================================================
6497 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6498 SMESH::SMESH_GroupBase_ptr theNodesNot,
6499 GEOM::GEOM_Object_ptr theShape )
6500 throw (SALOME::SALOME_Exception)
6503 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6509 SMESHDS_Mesh* aMeshDS = getMeshDS();
6510 TIDSortedElemSet anElems, aNodes, anAffected;
6511 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6512 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6514 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6515 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6518 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6520 // Update Python script
6521 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6522 << theNodesNot << ", " << theShape << " )";
6525 SMESH_CATCH( SMESH::throwCorbaException );
6529 //================================================================================
6531 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6532 * \param [in] theGrpList - groups
6533 * \param [in] theMeshDS - mesh
6534 * \param [out] theElemSet - set of elements
6535 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6537 //================================================================================
6539 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6540 SMESHDS_Mesh* theMeshDS,
6541 TIDSortedElemSet& theElemSet,
6542 const bool theIsNodeGrp)
6544 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6546 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6547 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6548 : aGrp->GetType() != SMESH::NODE ) )
6550 SMESH::long_array_var anIDs = aGrp->GetIDs();
6551 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6556 //================================================================================
6558 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6559 This method provided for convenience works as DoubleNodes() described above.
6560 \param theElems - list of groups of elements (edges or faces) to be replicated
6561 \param theNodesNot - list of groups of nodes not to replicated
6562 \param theAffectedElems - group of elements to which the replicated nodes
6563 should be associated to.
6564 \return TRUE if operation has been completed successfully, FALSE otherwise
6565 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6567 //================================================================================
6570 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6571 const SMESH::ListOfGroups& theNodesNot,
6572 const SMESH::ListOfGroups& theAffectedElems)
6573 throw (SALOME::SALOME_Exception)
6579 SMESHDS_Mesh* aMeshDS = getMeshDS();
6580 TIDSortedElemSet anElems, aNodes, anAffected;
6581 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6582 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6583 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6585 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6587 // Update Python script
6588 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6589 << &theNodesNot << ", " << &theAffectedElems << " )";
6591 declareMeshModified( /*isReComputeSafe=*/false );
6594 SMESH_CATCH( SMESH::throwCorbaException );
6598 //================================================================================
6600 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6601 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6602 \param theElems - list of groups of elements (edges or faces) to be replicated
6603 \param theNodesNot - list of groups of nodes not to replicated
6604 \param theAffectedElems - group of elements to which the replicated nodes
6605 should be associated to.
6606 * \return a new group with newly created elements
6607 * \sa DoubleNodeElemGroups()
6609 //================================================================================
6611 SMESH::SMESH_Group_ptr
6612 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6613 const SMESH::ListOfGroups& theNodesNot,
6614 const SMESH::ListOfGroups& theAffectedElems)
6615 throw (SALOME::SALOME_Exception)
6618 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6622 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6623 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6625 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6627 << theNodesNot << ", "
6628 << theAffectedElems << " )";
6630 return elemGroup._retn();
6633 //================================================================================
6635 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6636 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6637 \param theElems - list of groups of elements (edges or faces) to be replicated
6638 \param theNodesNot - list of groups of nodes not to replicated
6639 \param theAffectedElems - group of elements to which the replicated nodes
6640 should be associated to.
6641 * \return a new group with newly created elements
6642 * \sa DoubleNodeElemGroups()
6644 //================================================================================
6646 SMESH::ListOfGroups*
6647 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6648 const SMESH::ListOfGroups& theNodesNot,
6649 const SMESH::ListOfGroups& theAffectedElems,
6650 CORBA::Boolean theElemGroupNeeded,
6651 CORBA::Boolean theNodeGroupNeeded)
6652 throw (SALOME::SALOME_Exception)
6655 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6656 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6657 aTwoGroups->length( 2 );
6662 SMESHDS_Mesh* aMeshDS = getMeshDS();
6663 TIDSortedElemSet anElems, aNodes, anAffected;
6664 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6665 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6666 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6668 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6670 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6675 // Create group with newly created elements
6676 CORBA::String_var elemGroupName = theElems[0]->GetName();
6677 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6678 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6680 SMESH::long_array_var anIds = GetLastCreatedElems();
6681 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6682 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6683 aNewElemGroup->Add(anIds);
6685 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6687 SMESH::long_array_var anIds = GetLastCreatedNodes();
6688 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6689 aNewNodeGroup->Add(anIds);
6693 // Update Python script
6696 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6697 else pyDump << aNewElemGroup << ", ";
6698 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6699 else pyDump << aNewNodeGroup << " ] = ";
6701 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6702 << &theNodesNot << ", "
6703 << &theAffectedElems << ", "
6704 << theElemGroupNeeded << ", "
6705 << theNodeGroupNeeded << " )";
6707 aTwoGroups[0] = aNewElemGroup._retn();
6708 aTwoGroups[1] = aNewNodeGroup._retn();
6709 return aTwoGroups._retn();
6711 SMESH_CATCH( SMESH::throwCorbaException );
6715 //================================================================================
6717 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6718 This method provided for convenience works as DoubleNodes() described above.
6719 \param theElems - list of groups of elements (edges or faces) to be replicated
6720 \param theNodesNot - list of groups of nodes not to replicated
6721 \param theShape - shape to detect affected elements (element which geometric center
6722 located on or inside shape).
6723 The replicated nodes should be associated to affected elements.
6724 \return TRUE if operation has been completed successfully, FALSE otherwise
6725 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6727 //================================================================================
6730 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6731 const SMESH::ListOfGroups& theNodesNot,
6732 GEOM::GEOM_Object_ptr theShape )
6733 throw (SALOME::SALOME_Exception)
6739 SMESHDS_Mesh* aMeshDS = getMeshDS();
6740 TIDSortedElemSet anElems, aNodes;
6741 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6742 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6744 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6745 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6747 // Update Python script
6748 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6749 << &theNodesNot << ", " << theShape << " )";
6751 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6754 SMESH_CATCH( SMESH::throwCorbaException );
6758 //================================================================================
6760 \brief Identify the elements that will be affected by node duplication (actual
6761 duplication is not performed.
6762 This method is the first step of DoubleNodeElemGroupsInRegion.
6763 \param theElems - list of groups of elements (edges or faces) to be replicated
6764 \param theNodesNot - list of groups of nodes not to replicated
6765 \param theShape - shape to detect affected elements (element which geometric center
6766 located on or inside shape).
6767 The replicated nodes should be associated to affected elements.
6768 \return groups of affected elements
6769 \sa DoubleNodeElemGroupsInRegion()
6771 //================================================================================
6772 SMESH::ListOfGroups*
6773 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6774 const SMESH::ListOfGroups& theNodesNot,
6775 GEOM::GEOM_Object_ptr theShape )
6776 throw (SALOME::SALOME_Exception)
6779 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6780 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6781 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6782 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6786 ::SMESH_MeshEditor aMeshEditor(myMesh);
6788 SMESHDS_Mesh* aMeshDS = getMeshDS();
6789 TIDSortedElemSet anElems, aNodes;
6790 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6791 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6792 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6794 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6795 TIDSortedElemSet anAffected;
6796 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6798 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6801 if ( aResult && anAffected.size() > 0 )
6803 SMESH::long_array_var volumeIds = new SMESH::long_array;
6804 SMESH::long_array_var faceIds = new SMESH::long_array;
6805 SMESH::long_array_var edgeIds = new SMESH::long_array;
6806 volumeIds->length( anAffected.size() );
6807 faceIds ->length( anAffected.size() );
6808 edgeIds ->length( anAffected.size() );
6813 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6814 for (; eIt != anAffected.end(); ++eIt)
6816 const SMDS_MeshElement* anElem = *eIt;
6817 int elemId = anElem->GetID();
6818 switch ( anElem->GetType() ) {
6819 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6820 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6821 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6825 volumeIds->length(ivol);
6826 faceIds->length(iface);
6827 edgeIds->length(iedge);
6832 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6833 GenerateGroupName("affectedVolumes").c_str());
6834 aNewVolumeGroup->Add(volumeIds);
6835 aListOfGroups->length( nbGroups+1 );
6836 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6840 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6841 GenerateGroupName("affectedFaces").c_str());
6842 aNewFaceGroup->Add(faceIds);
6843 aListOfGroups->length( nbGroups+1 );
6844 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6848 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6849 GenerateGroupName("affectedEdges").c_str());
6850 aNewEdgeGroup->Add(edgeIds);
6851 aListOfGroups->length( nbGroups+1 );
6852 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6856 // Update Python script
6858 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6859 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6861 return aListOfGroups._retn();
6863 SMESH_CATCH( SMESH::throwCorbaException );
6867 //================================================================================
6869 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6870 The created 2D mesh elements based on nodes of free faces of boundary volumes
6871 \return TRUE if operation has been completed successfully, FALSE otherwise
6873 //================================================================================
6875 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6876 throw (SALOME::SALOME_Exception)
6881 bool aResult = getEditor().Make2DMeshFrom3D();
6883 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6885 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6888 SMESH_CATCH( SMESH::throwCorbaException );
6892 //================================================================================
6894 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6895 * The list of groups must contain at least two groups. The groups have to be disjoint:
6896 * no common element into two different groups.
6897 * The nodes of the internal faces at the boundaries of the groups are doubled.
6898 * Optionally, the internal faces are replaced by flat elements.
6899 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6900 * The flat elements are stored in groups of volumes.
6901 * These groups are named according to the position of the group in the list:
6902 * 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.
6903 * 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.
6904 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6905 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6906 * \param theDomains - list of groups of volumes
6907 * \param createJointElems - if TRUE, create the elements
6908 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6909 * the boundary between \a theDomains and the rest mesh
6910 * \return TRUE if operation has been completed successfully, FALSE otherwise
6912 //================================================================================
6915 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6916 CORBA::Boolean createJointElems,
6917 CORBA::Boolean onAllBoundaries )
6918 throw (SALOME::SALOME_Exception)
6925 SMESHDS_Mesh* aMeshDS = getMeshDS();
6927 // MESSAGE("theDomains.length = "<<theDomains.length());
6928 if ( theDomains.length() <= 1 && !onAllBoundaries )
6929 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6931 vector<TIDSortedElemSet> domains;
6932 domains.resize( theDomains.length() );
6934 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6936 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6937 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6939 // if ( aGrp->GetType() != SMESH::VOLUME )
6940 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6941 SMESH::long_array_var anIDs = aGrp->GetIDs();
6942 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6946 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6947 // TODO publish the groups of flat elements in study
6949 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6951 // Update Python script
6952 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6953 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6955 SMESH_CATCH( SMESH::throwCorbaException );
6957 myMesh_i->CreateGroupServants(); // publish created groups if any
6962 //================================================================================
6964 * \brief Double nodes on some external faces and create flat elements.
6965 * Flat elements are mainly used by some types of mechanic calculations.
6967 * Each group of the list must be constituted of faces.
6968 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6969 * @param theGroupsOfFaces - list of groups of faces
6970 * @return TRUE if operation has been completed successfully, FALSE otherwise
6972 //================================================================================
6975 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6976 throw (SALOME::SALOME_Exception)
6981 SMESHDS_Mesh* aMeshDS = getMeshDS();
6983 vector<TIDSortedElemSet> faceGroups;
6986 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6988 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6989 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6991 TIDSortedElemSet faceGroup;
6993 faceGroups.push_back(faceGroup);
6994 SMESH::long_array_var anIDs = aGrp->GetIDs();
6995 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6999 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7000 // TODO publish the groups of flat elements in study
7002 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7004 // Update Python script
7005 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7008 SMESH_CATCH( SMESH::throwCorbaException );
7012 //================================================================================
7014 * \brief Identify all the elements around a geom shape, get the faces delimiting
7017 * Build groups of volume to remove, groups of faces to replace on the skin of the
7018 * object, groups of faces to remove inside the object, (idem edges).
7019 * Build ordered list of nodes at the border of each group of faces to replace
7020 * (to be used to build a geom subshape).
7022 //================================================================================
7024 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7025 GEOM::GEOM_Object_ptr theShape,
7026 const char* groupName,
7027 const SMESH::double_array& theNodesCoords,
7028 SMESH::array_of_long_array_out GroupsOfNodes)
7029 throw (SALOME::SALOME_Exception)
7034 std::vector<std::vector<int> > aListOfListOfNodes;
7035 ::SMESH_MeshEditor aMeshEditor( myMesh );
7037 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7038 if ( !theNodeSearcher )
7039 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7041 vector<double> nodesCoords;
7042 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7044 nodesCoords.push_back( theNodesCoords[i] );
7047 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7048 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7049 nodesCoords, aListOfListOfNodes);
7051 GroupsOfNodes = new SMESH::array_of_long_array;
7052 GroupsOfNodes->length( aListOfListOfNodes.size() );
7053 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7054 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7056 vector<int>& aListOfNodes = *llIt;
7057 vector<int>::iterator lIt = aListOfNodes.begin();;
7058 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7059 aGroup.length( aListOfNodes.size() );
7060 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7061 aGroup[ j ] = (*lIt);
7063 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7066 << ", '" << groupName << "', "
7067 << theNodesCoords << " )";
7069 SMESH_CATCH( SMESH::throwCorbaException );
7072 // issue 20749 ===================================================================
7074 * \brief Creates missing boundary elements
7075 * \param elements - elements whose boundary is to be checked
7076 * \param dimension - defines type of boundary elements to create
7077 * \param groupName - a name of group to store created boundary elements in,
7078 * "" means not to create the group
7079 * \param meshName - a name of new mesh to store created boundary elements in,
7080 * "" means not to create the new mesh
7081 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7082 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7083 * boundary elements will be copied into the new mesh
7084 * \param group - returns the create group, if any
7085 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7087 // ================================================================================
7089 SMESH::SMESH_Mesh_ptr
7090 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7091 SMESH::Bnd_Dimension dim,
7092 const char* groupName,
7093 const char* meshName,
7094 CORBA::Boolean toCopyElements,
7095 CORBA::Boolean toCopyExistingBondary,
7096 SMESH::SMESH_Group_out group)
7097 throw (SALOME::SALOME_Exception)
7102 if ( dim > SMESH::BND_1DFROM2D )
7103 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7105 SMESHDS_Mesh* aMeshDS = getMeshDS();
7107 SMESH::SMESH_Mesh_var mesh_var;
7108 SMESH::SMESH_Group_var group_var;
7112 TIDSortedElemSet elements;
7113 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7114 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7118 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7119 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7121 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7123 // group of new boundary elements
7124 SMESH_Group* smesh_group = 0;
7125 if ( strlen(groupName) )
7127 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7128 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7129 smesh_group = group_i->GetSmeshGroup();
7133 getEditor().MakeBoundaryMesh( elements,
7134 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7138 toCopyExistingBondary);
7141 smesh_mesh->GetMeshDS()->Modified();
7144 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7146 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7147 if ( mesh_var->_is_nil() )
7148 pyDump << myMesh_i->_this() << ", ";
7150 pyDump << mesh_var << ", ";
7151 if ( group_var->_is_nil() )
7152 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7154 pyDump << group_var << " = ";
7155 pyDump << this << ".MakeBoundaryMesh( "
7157 << "SMESH." << dimName[int(dim)] << ", "
7158 << "'" << groupName << "', "
7159 << "'" << meshName<< "', "
7160 << toCopyElements << ", "
7161 << toCopyExistingBondary << ")";
7163 group = group_var._retn();
7164 return mesh_var._retn();
7166 SMESH_CATCH( SMESH::throwCorbaException );
7167 return SMESH::SMESH_Mesh::_nil();
7170 //================================================================================
7172 * \brief Creates missing boundary elements
7173 * \param dimension - defines type of boundary elements to create
7174 * \param groupName - a name of group to store all boundary elements in,
7175 * "" means not to create the group
7176 * \param meshName - a name of a new mesh, which is a copy of the initial
7177 * mesh + created boundary elements; "" means not to create the new mesh
7178 * \param toCopyAll - if true, the whole initial mesh will be copied into
7179 * the new mesh else only boundary elements will be copied into the new mesh
7180 * \param groups - optional groups of elements to make boundary around
7181 * \param mesh - returns the mesh where elements were added to
7182 * \param group - returns the created group, if any
7183 * \retval long - number of added boundary elements
7185 //================================================================================
7187 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7188 const char* groupName,
7189 const char* meshName,
7190 CORBA::Boolean toCopyAll,
7191 const SMESH::ListOfIDSources& groups,
7192 SMESH::SMESH_Mesh_out mesh,
7193 SMESH::SMESH_Group_out group)
7194 throw (SALOME::SALOME_Exception)
7199 if ( dim > SMESH::BND_1DFROM2D )
7200 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7202 // separate groups belonging to this and other mesh
7203 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7204 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7205 groupsOfThisMesh ->length( groups.length() );
7206 groupsOfOtherMesh->length( groups.length() );
7207 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7208 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7210 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7211 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7212 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7214 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7215 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7216 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7218 groupsOfThisMesh->length( nbGroups );
7219 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7224 if ( nbGroupsOfOtherMesh > 0 )
7226 // process groups belonging to another mesh
7227 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7228 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7229 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7230 groupsOfOtherMesh, mesh, group );
7233 SMESH::SMESH_Mesh_var mesh_var;
7234 SMESH::SMESH_Group_var group_var;
7237 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7238 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7242 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7244 /*toCopyGroups=*/false,
7245 /*toKeepIDs=*/true);
7247 mesh_var = makeMesh(meshName);
7249 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7250 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7253 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7254 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7256 // group of boundary elements
7257 SMESH_Group* smesh_group = 0;
7258 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7259 if ( strlen( groupName ))
7261 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7262 group_var = mesh_i->CreateGroup( groupType, groupName );
7263 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7264 smesh_group = group_i->GetSmeshGroup();
7267 TIDSortedElemSet elements;
7269 if ( groups.length() > 0 )
7271 for ( int i = 0; i < nbGroups; ++i )
7274 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7276 SMESH::Bnd_Dimension bdim =
7277 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7278 nbAdded += getEditor().MakeBoundaryMesh( elements,
7279 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7282 /*toCopyElements=*/false,
7283 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7284 /*toAddExistingBondary=*/true,
7285 /*aroundElements=*/true);
7291 nbAdded += getEditor().MakeBoundaryMesh( elements,
7292 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7295 /*toCopyElements=*/false,
7296 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7297 /*toAddExistingBondary=*/true);
7299 tgtMesh->GetMeshDS()->Modified();
7301 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7303 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7304 pyDump << "nbAdded, ";
7305 if ( mesh_var->_is_nil() )
7306 pyDump << myMesh_i->_this() << ", ";
7308 pyDump << mesh_var << ", ";
7309 if ( group_var->_is_nil() )
7310 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7312 pyDump << group_var << " = ";
7313 pyDump << this << ".MakeBoundaryElements( "
7314 << "SMESH." << dimName[int(dim)] << ", "
7315 << "'" << groupName << "', "
7316 << "'" << meshName<< "', "
7317 << toCopyAll << ", "
7320 mesh = mesh_var._retn();
7321 group = group_var._retn();
7324 SMESH_CATCH( SMESH::throwCorbaException );
7328 //================================================================================
7330 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7331 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7332 * plane passing through pairs of points specified by each PolySegment structure.
7333 * If there are several paths connecting a pair of points, the shortest path is
7334 * selected by the module. Position of the cutting plane is defined by the two
7335 * points and an optional vector lying on the plane specified by a PolySegment.
7336 * By default the vector is defined by Mesh module as following. A middle point
7337 * of the two given points is computed. The middle point is projected to the mesh.
7338 * The vector goes from the middle point to the projection point. In case of planar
7339 * mesh, the vector is normal to the mesh.
7340 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7341 * Return the used vector and position of the middle point.
7342 * \param [in] groupName - optional name of a group where created mesh segments will
7345 //================================================================================
7347 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7348 const char* theGroupName)
7349 throw (SALOME::SALOME_Exception)
7351 if ( theSegments.length() == 0 )
7352 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7353 if ( myMesh->NbFaces() == 0 )
7354 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7357 initData(/*deleteSearchers=*/false);
7359 SMESHDS_Group* groupDS = 0;
7360 SMESHDS_Mesh* meshDS = getMeshDS();
7361 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7363 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7364 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7365 while ( faceIt->more() )
7366 tmpMesh->Copy( faceIt->next() );
7367 meshDS = tmpMesh->GetMeshDS();
7369 else if ( theGroupName[0] ) // find/create a group of segments
7371 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7372 while ( !groupDS && grpIt->more() )
7374 SMESH_Group* group = grpIt->next();
7375 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7376 strcmp( group->GetName(), theGroupName ) == 0 )
7378 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7383 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7385 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7386 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7390 // convert input polySegments
7391 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7392 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7394 SMESH::PolySegment& segIn = theSegments[ i ];
7395 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7396 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7397 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7398 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7399 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7400 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7403 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7406 segOut.myVector.SetCoord( segIn.vector.PS.x,
7408 segIn.vector.PS.z );
7411 // get a static ElementSearcher
7412 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7413 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7414 if ( !theElementSearcher )
7415 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7418 std::vector<const SMDS_MeshElement*> newEdges;
7419 std::vector<const SMDS_MeshNode*> newNodes;
7420 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7421 groupDS ? &groupDS->SMDSGroup() : 0,
7422 theElementSearcher );
7424 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7426 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7427 assign( newNodes.begin(), newNodes.end() );
7430 if ( myIsPreviewMode )
7432 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7434 SMESH::PolySegment& segOut = theSegments[ i ];
7435 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7436 segOut.vector.PS.x = segIn.myVector.X();
7437 segOut.vector.PS.y = segIn.myVector.Y();
7438 segOut.vector.PS.z = segIn.myVector.Z();
7443 TPythonDump() << "_segments = []";
7444 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7446 SMESH::PolySegment& segIn = theSegments[ i ];
7447 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7448 << segIn.node1ID1 << ", "
7449 << segIn.node1ID2 << ", "
7450 << segIn.node2ID1 << ", "
7451 << segIn.node2ID2 << ", "
7452 << "smeshBuilder.MakeDirStruct( "
7453 << segIn.vector.PS.x << ", "
7454 << segIn.vector.PS.y << ", "
7455 << segIn.vector.PS.z << ")))";
7457 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7460 SMESH_CATCH( SMESH::throwCorbaException );
7464 //================================================================================
7466 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7467 * The slot is consrtucted by cutting faces by cylindrical surfaces made
7468 * around each segment. Segments are expected to be created by MakePolyLine().
7469 * \return Edges located at the slot boundary
7471 //================================================================================
7473 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7474 CORBA::Double theWidth)
7475 throw (SALOME::SALOME_Exception)
7477 if ( CORBA::is_nil( theSegments ) ||
7478 theSegments->GetType() != SMESH::EDGE )
7479 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7480 if ( myMesh->NbFaces() == 0 )
7481 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7483 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7486 initData(/*deleteSearchers=*/false);
7488 SMESHDS_Mesh* meshDS = getMeshDS();
7490 std::vector< SMESH_MeshAlgos::Edge > edges =
7491 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7494 resultEdges->length( edges.size() );
7495 for ( size_t i = 0; i < edges.size(); ++i )
7497 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7498 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7499 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7503 SMESH_CATCH( SMESH::throwCorbaException );
7505 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7507 return resultEdges._retn();