1 // Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _myMeshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< int > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( int i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
197 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::long_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::long_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
526 throw (SALOME::SALOME_Exception)
529 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
531 if ( myIsPreviewMode || hasBadElems )
533 list<int> aNodesConnectivity;
534 typedef map<int, int> TNodesMap;
537 SMESHDS_Mesh* aMeshDS;
538 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
540 const list<const SMDS_MeshElement*>& badElems =
541 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
542 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
543 aMeshDS = aMeshPartDS.get();
546 aMeshDS = getEditor().GetMeshDS();
548 myPreviewData = new SMESH::MeshPreviewStruct();
549 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
552 SMDSAbs_ElementType previewType = SMDSAbs_All;
554 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
555 previewType = aPreviewMesh->myPreviewType;
556 switch ( previewType ) {
557 case SMDSAbs_Edge : break;
558 case SMDSAbs_Face : break;
559 case SMDSAbs_Volume: break;
561 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
565 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
567 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
569 while ( itMeshElems->more() ) {
570 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
571 SMDS_NodeIteratorPtr itElemNodes =
572 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
573 aMeshElem->interlacedNodesIterator() :
574 aMeshElem->nodeIterator() );
575 while ( itElemNodes->more() ) {
576 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
577 int aNodeID = aMeshNode->GetID();
578 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
579 if ( anIter == nodesMap.end() ) {
580 // filling the nodes coordinates
581 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
582 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
583 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
584 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
587 aNodesConnectivity.push_back(anIter->second);
590 // filling the elements types
591 SMDSAbs_ElementType aType = aMeshElem->GetType();
592 bool isPoly = aMeshElem->IsPoly();
593 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
594 myPreviewData->elementTypes[i].isPoly = isPoly;
595 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
598 myPreviewData->nodesXYZ.length( j );
600 // filling the elements connectivities
601 list<int>::iterator aConnIter = aNodesConnectivity.begin();
602 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
603 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
604 myPreviewData->elementConnectivities[i] = *aConnIter;
606 return myPreviewData._retn();
608 SMESH_CATCH( SMESH::throwCorbaException );
612 //================================================================================
614 * \brief Returns list of it's IDs of created nodes
615 * \retval SMESH::long_array* - list of node ID
617 //================================================================================
619 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
620 throw (SALOME::SALOME_Exception)
623 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
625 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
626 myLastCreatedNodes->length( aSeq.size() );
627 for ( size_t i = 0; i < aSeq.size(); i++)
628 myLastCreatedNodes[i] = aSeq[i]->GetID();
630 return myLastCreatedNodes._retn();
631 SMESH_CATCH( SMESH::throwCorbaException );
635 //================================================================================
637 * \brief Returns list of it's IDs of created elements
638 * \retval SMESH::long_array* - list of elements' ID
640 //================================================================================
642 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 throw (SALOME::SALOME_Exception)
646 SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
648 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
649 myLastCreatedElems->length( aSeq.size() );
650 for ( size_t i = 0; i < aSeq.size(); i++ )
651 myLastCreatedElems[i] = aSeq[i]->GetID();
653 return myLastCreatedElems._retn();
654 SMESH_CATCH( SMESH::throwCorbaException );
658 //=======================================================================
659 //function : ClearLastCreated
660 //purpose : Clears sequences of last created elements and nodes
661 //=======================================================================
663 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
666 getEditor().ClearLastCreated();
667 SMESH_CATCH( SMESH::throwCorbaException );
670 //=======================================================================
672 * Returns description of an error/warning occurred during the last operation
673 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
675 //=======================================================================
677 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
678 throw (SALOME::SALOME_Exception)
681 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
682 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
683 if ( errIn && !errIn->IsOK() )
685 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
686 errOut->comment = errIn->myComment.c_str();
687 errOut->subShapeID = -1;
688 errOut->hasBadMesh = errIn->HasBadElems();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = false;
697 return errOut._retn();
698 SMESH_CATCH( SMESH::throwCorbaException );
702 //=======================================================================
703 //function : MakeIDSource
704 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
705 // Call UnRegister() as you fininsh using it!!
706 //=======================================================================
708 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
709 public virtual SALOME::GenericObj_i
711 SMESH::long_array _ids;
712 SMESH::ElementType _type;
713 SMESH::SMESH_Mesh_ptr _mesh;
714 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
715 SMESH::long_array* GetMeshInfo() { return 0; }
716 SMESH::long_array* GetNbElementsByType()
718 SMESH::long_array_var aRes = new SMESH::long_array();
719 aRes->length(SMESH::NB_ELEMENT_TYPES);
720 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
721 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
724 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
725 bool IsMeshInfoCorrect() { return true; }
726 SMESH::array_of_ElementType* GetTypes()
728 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
729 if ( _ids.length() > 0 ) {
733 return types._retn();
735 SALOMEDS::TMPFile* GetVtkUgStream()
737 SALOMEDS::TMPFile_var SeqFile;
738 return SeqFile._retn();
742 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
743 SMESH::ElementType type)
745 _IDSource* idSrc = new _IDSource;
746 idSrc->_mesh = myMesh_i->_this();
749 if ( type == SMESH::ALL && ids.length() > 0 )
750 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
752 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
754 return anIDSourceVar._retn();
757 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
759 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
762 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
765 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
767 nbIds = (int) tmpIdSource->_ids.length();
768 return & tmpIdSource->_ids[0];
774 // void SMESH_MeshEditor_i::deleteAuxIDSources()
776 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
777 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
779 // myAuxIDSources.clear();
782 //=============================================================================
786 //=============================================================================
789 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
790 throw (SALOME::SALOME_Exception)
797 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
862 list< int > IdList( seq.begin(), seq.end() );
864 int nbNodesBefore = myMesh->NbNodes();
865 getEditor().Remove( IdList, true );
866 int nbNodesAfter = myMesh->NbNodes();
868 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
869 return nbNodesBefore - nbNodesAfter;
871 SMESH_CATCH( SMESH::throwCorbaException );
875 //=============================================================================
879 //=============================================================================
881 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
882 throw (SALOME::SALOME_Exception)
887 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
889 // Update Python script
890 TPythonDump() << "nodeID = " << this << ".AddNode( "
891 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
893 declareMeshModified( /*isReComputeSafe=*/false );
896 SMESH_CATCH( SMESH::throwCorbaException );
900 //=============================================================================
902 * Create 0D element on the given node.
904 //=============================================================================
906 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
907 CORBA::Boolean DuplicateElements)
908 throw (SALOME::SALOME_Exception)
913 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
914 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
916 SMDS_MeshElement* elem = 0;
917 if ( DuplicateElements || !it0D->more() )
918 elem = getMeshDS()->Add0DElement(aNode);
920 // Update Python script
921 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
923 declareMeshModified( /*isReComputeSafe=*/false );
925 return elem ? elem->GetID() : 0;
927 SMESH_CATCH( SMESH::throwCorbaException );
931 //=============================================================================
933 * Create a ball element on the given node.
935 //=============================================================================
937 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
938 throw (SALOME::SALOME_Exception)
943 if ( diameter < std::numeric_limits<double>::min() )
944 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
946 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
947 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
949 // Update Python script
950 TPythonDump() << "ballElem = "
951 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
953 declareMeshModified( /*isReComputeSafe=*/false );
954 return elem ? elem->GetID() : 0;
956 SMESH_CATCH( SMESH::throwCorbaException );
960 //=============================================================================
962 * Create an edge, either linear and quadratic (this is determed
963 * by number of given nodes, two or three)
965 //=============================================================================
967 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
968 throw (SALOME::SALOME_Exception)
973 int NbNodes = IDsOfNodes.length();
974 SMDS_MeshElement* elem = 0;
977 CORBA::Long index1 = IDsOfNodes[0];
978 CORBA::Long index2 = IDsOfNodes[1];
979 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
980 getMeshDS()->FindNode(index2));
982 // Update Python script
983 TPythonDump() << "edge = " << this << ".AddEdge([ "
984 << index1 << ", " << index2 <<" ])";
987 CORBA::Long n1 = IDsOfNodes[0];
988 CORBA::Long n2 = IDsOfNodes[1];
989 CORBA::Long n12 = IDsOfNodes[2];
990 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
991 getMeshDS()->FindNode(n2),
992 getMeshDS()->FindNode(n12));
993 // Update Python script
994 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
995 <<n1<<", "<<n2<<", "<<n12<<" ])";
998 declareMeshModified( /*isReComputeSafe=*/false );
999 return elem ? elem->GetID() : 0;
1001 SMESH_CATCH( SMESH::throwCorbaException );
1005 //=============================================================================
1009 //=============================================================================
1011 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1012 throw (SALOME::SALOME_Exception)
1017 int NbNodes = IDsOfNodes.length();
1023 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1024 for (int i = 0; i < NbNodes; i++)
1025 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1027 SMDS_MeshElement* elem = 0;
1029 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1030 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1031 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5]); break;
1033 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6]); break;
1035 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1036 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1037 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1038 nodes[4], nodes[5], nodes[6], nodes[7],
1040 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1043 // Update Python script
1044 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1046 declareMeshModified( /*isReComputeSafe=*/false );
1048 return elem ? elem->GetID() : 0;
1050 SMESH_CATCH( SMESH::throwCorbaException );
1054 //=============================================================================
1058 //=============================================================================
1060 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1061 throw (SALOME::SALOME_Exception)
1066 int NbNodes = IDsOfNodes.length();
1067 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1068 for (int i = 0; i < NbNodes; i++)
1069 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1074 INFOS("Polygon without nodes is forbidden");
1078 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1080 // Update Python script
1081 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1083 declareMeshModified( /*isReComputeSafe=*/false );
1084 return elem ? elem->GetID() : 0;
1086 SMESH_CATCH( SMESH::throwCorbaException );
1090 //=============================================================================
1092 * AddQuadPolygonalFace
1094 //=============================================================================
1096 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1097 throw (SALOME::SALOME_Exception)
1102 int NbNodes = IDsOfNodes.length();
1103 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1104 for (int i = 0; i < NbNodes; i++)
1105 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1109 INFOS("Polygon without nodes is forbidden");
1113 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1115 // Update Python script
1116 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1118 declareMeshModified( /*isReComputeSafe=*/false );
1119 return elem ? elem->GetID() : 0;
1121 SMESH_CATCH( SMESH::throwCorbaException );
1125 //=============================================================================
1127 * Create volume, either linear and quadratic (this is determed
1128 * by number of given nodes)
1130 //=============================================================================
1132 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1133 throw (SALOME::SALOME_Exception)
1138 int NbNodes = IDsOfNodes.length();
1139 vector< const SMDS_MeshNode*> n(NbNodes);
1140 for(int i=0;i<NbNodes;i++)
1141 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1143 SMDS_MeshElement* elem = 0;
1146 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1147 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1148 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1149 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1150 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1151 n[6],n[7],n[8],n[9]);
1153 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1154 n[6],n[7],n[8],n[9],n[10],n[11]);
1156 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1157 n[7],n[8],n[9],n[10],n[11],n[12]);
1159 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1160 n[9],n[10],n[11],n[12],n[13],n[14]);
1162 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1163 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1164 n[15],n[16],n[17],n[18],n[19]);
1166 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1167 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1170 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1171 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1172 n[15],n[16],n[17],n[18],n[19],
1173 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1177 // Update Python script
1178 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1180 declareMeshModified( /*isReComputeSafe=*/false );
1181 return elem ? elem->GetID() : 0;
1183 SMESH_CATCH( SMESH::throwCorbaException );
1187 //=============================================================================
1189 * AddPolyhedralVolume
1191 //=============================================================================
1192 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1193 const SMESH::long_array & Quantities)
1194 throw (SALOME::SALOME_Exception)
1199 int NbNodes = IDsOfNodes.length();
1200 std::vector<const SMDS_MeshNode*> n (NbNodes);
1201 for (int i = 0; i < NbNodes; i++)
1203 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1204 if (!aNode) return 0;
1208 int NbFaces = Quantities.length();
1209 std::vector<int> q (NbFaces);
1210 for (int j = 0; j < NbFaces; j++)
1211 q[j] = Quantities[j];
1213 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1215 // Update Python script
1216 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1217 << IDsOfNodes << ", " << Quantities << " )";
1219 declareMeshModified( /*isReComputeSafe=*/false );
1220 return elem ? elem->GetID() : 0;
1222 SMESH_CATCH( SMESH::throwCorbaException );
1226 //=============================================================================
1228 * AddPolyhedralVolumeByFaces
1230 //=============================================================================
1232 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1233 throw (SALOME::SALOME_Exception)
1238 int NbFaces = IdsOfFaces.length();
1239 std::vector<const SMDS_MeshNode*> poly_nodes;
1240 std::vector<int> quantities (NbFaces);
1242 for (int i = 0; i < NbFaces; i++) {
1243 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1244 quantities[i] = aFace->NbNodes();
1246 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1247 while (It->more()) {
1248 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1252 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1254 // Update Python script
1255 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1256 << IdsOfFaces << " )";
1258 declareMeshModified( /*isReComputeSafe=*/false );
1259 return elem ? elem->GetID() : 0;
1261 SMESH_CATCH( SMESH::throwCorbaException );
1265 //=============================================================================
1267 // \brief Create 0D elements on all nodes of the given object.
1268 // \param theObject object on whose nodes 0D elements will be created.
1269 // \param theGroupName optional name of a group to add 0D elements created
1270 // and/or found on nodes of \a theObject.
1271 // \param DuplicateElements to add one more 0D element to a node or not.
1272 // \return an object (a new group or a temporary SMESH_IDSource) holding
1273 // ids of new and/or found 0D elements.
1275 //=============================================================================
1277 SMESH::SMESH_IDSource_ptr
1278 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1279 const char* theGroupName,
1280 CORBA::Boolean theDuplicateElements)
1281 throw (SALOME::SALOME_Exception)
1286 SMESH::SMESH_IDSource_var result;
1289 TIDSortedElemSet elements, elems0D;
1290 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1291 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1293 SMESH::long_array_var newElems = new SMESH::long_array;
1294 newElems->length( elems0D.size() );
1295 TIDSortedElemSet::iterator eIt = elems0D.begin();
1296 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1297 newElems[ i ] = (*eIt)->GetID();
1299 SMESH::SMESH_GroupBase_var groupToFill;
1300 if ( theGroupName && strlen( theGroupName ))
1302 // Get existing group named theGroupName
1303 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1304 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1305 SMESH::SMESH_GroupBase_var group = groups[i];
1306 if ( !group->_is_nil() ) {
1307 CORBA::String_var name = group->GetName();
1308 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1309 groupToFill = group;
1314 if ( groupToFill->_is_nil() )
1315 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1316 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1317 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1320 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1322 group_i->Add( newElems );
1323 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1324 pyDump << groupToFill;
1328 result = MakeIDSource( newElems, SMESH::ELEM0D );
1329 pyDump << "elem0DIDs";
1332 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1333 << theObject << ", '" << theGroupName << "' )";
1335 return result._retn();
1337 SMESH_CATCH( SMESH::throwCorbaException );
1341 //=============================================================================
1343 * \brief Bind a node to a vertex
1344 * \param NodeID - node ID
1345 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1346 * \retval boolean - false if NodeID or VertexID is invalid
1348 //=============================================================================
1350 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1351 throw (SALOME::SALOME_Exception)
1355 SMESHDS_Mesh * mesh = getMeshDS();
1356 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1358 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1360 if ( mesh->MaxShapeIndex() < VertexID )
1361 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1363 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1364 if ( shape.ShapeType() != TopAbs_VERTEX )
1365 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1367 mesh->SetNodeOnVertex( node, VertexID );
1369 myMesh->SetIsModified( true );
1371 SMESH_CATCH( SMESH::throwCorbaException );
1374 //=============================================================================
1376 * \brief Store node position on an edge
1377 * \param NodeID - node ID
1378 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1379 * \param paramOnEdge - parameter on edge where the node is located
1380 * \retval boolean - false if any parameter is invalid
1382 //=============================================================================
1384 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1385 CORBA::Double paramOnEdge)
1386 throw (SALOME::SALOME_Exception)
1390 SMESHDS_Mesh * mesh = getMeshDS();
1391 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1395 if ( mesh->MaxShapeIndex() < EdgeID )
1396 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1398 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1399 if ( shape.ShapeType() != TopAbs_EDGE )
1400 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1403 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1404 if ( paramOnEdge < f || paramOnEdge > l )
1406 SMESH_Comment txt("Invalid paramOnEdge. It must vary in range [ ");
1407 txt << f << ", " << l << " ]";
1408 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1410 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1412 myMesh->SetIsModified( true );
1414 SMESH_CATCH( SMESH::throwCorbaException );
1417 //=============================================================================
1419 * \brief Store node position on a face
1420 * \param NodeID - node ID
1421 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1422 * \param u - U parameter on face where the node is located
1423 * \param v - V parameter on face where the node is located
1424 * \retval boolean - false if any parameter is invalid
1426 //=============================================================================
1428 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1429 CORBA::Double u, CORBA::Double v)
1430 throw (SALOME::SALOME_Exception)
1433 SMESHDS_Mesh * mesh = getMeshDS();
1434 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1436 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1438 if ( mesh->MaxShapeIndex() < FaceID )
1439 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1441 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1442 if ( shape.ShapeType() != TopAbs_FACE )
1443 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1445 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1446 bool isOut = ( u < surf.FirstUParameter() ||
1447 u > surf.LastUParameter() ||
1448 v < surf.FirstVParameter() ||
1449 v > surf.LastVParameter() );
1452 SMESH_Comment txt("Invalid UV. U must vary in range [ ");
1453 txt << surf.FirstUParameter() << ", " << surf.LastUParameter() << " ], ";
1454 txt << "V must vary in range [ ";
1455 txt << surf.FirstVParameter() << ", " << surf.LastVParameter() << " ]";
1456 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1459 mesh->SetNodeOnFace( node, FaceID, u, v );
1460 myMesh->SetIsModified( true );
1462 SMESH_CATCH( SMESH::throwCorbaException );
1465 //=============================================================================
1467 * \brief Bind a node to a solid
1468 * \param NodeID - node ID
1469 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1470 * \retval boolean - false if NodeID or SolidID is invalid
1472 //=============================================================================
1474 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1475 throw (SALOME::SALOME_Exception)
1478 SMESHDS_Mesh * mesh = getMeshDS();
1479 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1481 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1483 if ( mesh->MaxShapeIndex() < SolidID )
1484 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1486 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1487 if ( shape.ShapeType() != TopAbs_SOLID &&
1488 shape.ShapeType() != TopAbs_SHELL)
1489 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1491 mesh->SetNodeInVolume( node, SolidID );
1493 SMESH_CATCH( SMESH::throwCorbaException );
1496 //=============================================================================
1498 * \brief Bind an element to a shape
1499 * \param ElementID - element ID
1500 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1502 //=============================================================================
1504 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1505 CORBA::Long ShapeID)
1506 throw (SALOME::SALOME_Exception)
1509 SMESHDS_Mesh * mesh = getMeshDS();
1510 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1512 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1514 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1515 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1517 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1518 if ( shape.ShapeType() != TopAbs_EDGE &&
1519 shape.ShapeType() != TopAbs_FACE &&
1520 shape.ShapeType() != TopAbs_SOLID &&
1521 shape.ShapeType() != TopAbs_SHELL )
1522 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1524 mesh->SetMeshElementOnShape( elem, ShapeID );
1526 myMesh->SetIsModified( true );
1528 SMESH_CATCH( SMESH::throwCorbaException );
1531 //=============================================================================
1535 //=============================================================================
1537 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1538 CORBA::Long NodeID2)
1539 throw (SALOME::SALOME_Exception)
1544 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1545 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1549 // Update Python script
1550 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1551 << NodeID1 << ", " << NodeID2 << " )";
1553 int ret = getEditor().InverseDiag ( n1, n2 );
1555 declareMeshModified( /*isReComputeSafe=*/false );
1558 SMESH_CATCH( SMESH::throwCorbaException );
1562 //=============================================================================
1566 //=============================================================================
1568 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1569 CORBA::Long NodeID2)
1570 throw (SALOME::SALOME_Exception)
1575 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1576 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1580 // Update Python script
1581 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1582 << NodeID1 << ", " << NodeID2 << " )";
1585 bool stat = getEditor().DeleteDiag ( n1, n2 );
1587 declareMeshModified( /*isReComputeSafe=*/!stat );
1591 SMESH_CATCH( SMESH::throwCorbaException );
1595 //=============================================================================
1599 //=============================================================================
1601 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1602 throw (SALOME::SALOME_Exception)
1607 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1609 CORBA::Long index = IDsOfElements[i];
1610 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1612 getEditor().Reorient( elem );
1614 // Update Python script
1615 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1617 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1620 SMESH_CATCH( SMESH::throwCorbaException );
1624 //=============================================================================
1628 //=============================================================================
1630 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1631 throw (SALOME::SALOME_Exception)
1636 TPythonDump aTPythonDump; // suppress dump in Reorient()
1638 prepareIdSource( theObject );
1640 SMESH::long_array_var anElementsId = theObject->GetIDs();
1641 CORBA::Boolean isDone = Reorient(anElementsId);
1643 // Update Python script
1644 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1646 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1649 SMESH_CATCH( SMESH::throwCorbaException );
1653 //=======================================================================
1654 //function : Reorient2D
1655 //purpose : Reorient faces contained in \a the2Dgroup.
1656 // the2Dgroup - the mesh or its part to reorient
1657 // theDirection - desired direction of normal of \a theFace
1658 // theFace - ID of face whose orientation is checked.
1659 // It can be < 1 then \a thePoint is used to find a face.
1660 // thePoint - is used to find a face if \a theFace < 1.
1661 // return number of reoriented elements.
1662 //=======================================================================
1664 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1665 const SMESH::DirStruct& theDirection,
1666 CORBA::Long theFace,
1667 const SMESH::PointStruct& thePoint)
1668 throw (SALOME::SALOME_Exception)
1671 initData(/*deleteSearchers=*/false);
1673 TIDSortedElemSet elements;
1674 IDSource_Error error;
1675 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1676 if ( error == IDSource_EMPTY )
1678 if ( error == IDSource_INVALID )
1679 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1682 const SMDS_MeshElement* face = 0;
1685 face = getMeshDS()->FindElement( theFace );
1687 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1688 if ( face->GetType() != SMDSAbs_Face )
1689 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1693 // create theElementSearcher if needed
1694 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1695 if ( !theElementSearcher )
1697 if ( elements.empty() ) // search in the whole mesh
1699 if ( myMesh->NbFaces() == 0 )
1700 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1702 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1706 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1707 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1709 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1713 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1714 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1717 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1718 if ( !elements.empty() && !elements.count( face ))
1719 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1722 const SMESH::PointStruct * P = &theDirection.PS;
1723 gp_Vec dirVec( P->x, P->y, P->z );
1724 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1725 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1727 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1730 declareMeshModified( /*isReComputeSafe=*/false );
1732 TPythonDump() << this << ".Reorient2D( "
1733 << the2Dgroup << ", "
1734 << theDirection << ", "
1736 << thePoint << " )";
1740 SMESH_CATCH( SMESH::throwCorbaException );
1744 //=======================================================================
1745 //function : Reorient2DBy3D
1746 //purpose : Reorient faces basing on orientation of adjacent volumes.
1747 //=======================================================================
1749 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1750 SMESH::SMESH_IDSource_ptr volumeGroup,
1751 CORBA::Boolean outsideNormal)
1752 throw (SALOME::SALOME_Exception)
1757 TIDSortedElemSet volumes;
1758 IDSource_Error volsError;
1759 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1762 for ( size_t i = 0; i < faceGroups.length(); ++i )
1764 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1766 TIDSortedElemSet faces;
1767 IDSource_Error error;
1768 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1769 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1770 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1771 if ( error == IDSource_OK && volsError != IDSource_OK )
1772 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1774 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1776 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1781 declareMeshModified( /*isReComputeSafe=*/false );
1783 TPythonDump() << this << ".Reorient2DBy3D( "
1784 << faceGroups << ", "
1785 << volumeGroup << ", "
1786 << outsideNormal << " )";
1790 SMESH_CATCH( SMESH::throwCorbaException );
1794 //=============================================================================
1796 * \brief Fuse neighbour triangles into quadrangles.
1798 //=============================================================================
1800 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1801 SMESH::NumericalFunctor_ptr Criterion,
1802 CORBA::Double MaxAngle)
1803 throw (SALOME::SALOME_Exception)
1808 SMESHDS_Mesh* aMesh = getMeshDS();
1809 TIDSortedElemSet faces,copyFaces;
1810 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1811 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1812 TIDSortedElemSet* workElements = & faces;
1814 if ( myIsPreviewMode ) {
1815 SMDSAbs_ElementType select = SMDSAbs_Face;
1816 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1817 workElements = & copyFaces;
1820 SMESH::NumericalFunctor_i* aNumericalFunctor =
1821 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1822 SMESH::Controls::NumericalFunctorPtr aCrit;
1823 if ( !aNumericalFunctor )
1824 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1826 aCrit = aNumericalFunctor->GetNumericalFunctor();
1828 if ( !myIsPreviewMode ) {
1829 // Update Python script
1830 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1831 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1834 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1836 declareMeshModified( /*isReComputeSafe=*/!stat );
1839 SMESH_CATCH( SMESH::throwCorbaException );
1843 //=============================================================================
1845 * \brief Fuse neighbour triangles into quadrangles.
1847 //=============================================================================
1849 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1850 SMESH::NumericalFunctor_ptr Criterion,
1851 CORBA::Double MaxAngle)
1852 throw (SALOME::SALOME_Exception)
1857 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1859 prepareIdSource( theObject );
1860 SMESH::long_array_var anElementsId = theObject->GetIDs();
1861 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1863 if ( !myIsPreviewMode ) {
1864 SMESH::NumericalFunctor_i* aNumericalFunctor =
1865 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1867 // Update Python script
1868 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1869 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1874 SMESH_CATCH( SMESH::throwCorbaException );
1878 //=============================================================================
1880 * \brief Split quadrangles into triangles.
1882 //=============================================================================
1884 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1885 SMESH::NumericalFunctor_ptr Criterion)
1886 throw (SALOME::SALOME_Exception)
1891 SMESHDS_Mesh* aMesh = getMeshDS();
1892 TIDSortedElemSet faces;
1893 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1895 SMESH::NumericalFunctor_i* aNumericalFunctor =
1896 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1897 SMESH::Controls::NumericalFunctorPtr aCrit;
1898 if ( !aNumericalFunctor )
1899 aCrit.reset( new SMESH::Controls::AspectRatio() );
1901 aCrit = aNumericalFunctor->GetNumericalFunctor();
1904 // Update Python script
1905 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1907 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1909 declareMeshModified( /*isReComputeSafe=*/false );
1912 SMESH_CATCH( SMESH::throwCorbaException );
1916 //=============================================================================
1918 * \brief Split quadrangles into triangles.
1920 //=============================================================================
1922 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1923 SMESH::NumericalFunctor_ptr Criterion)
1924 throw (SALOME::SALOME_Exception)
1929 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1931 prepareIdSource( theObject );
1932 SMESH::long_array_var anElementsId = theObject->GetIDs();
1933 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1935 SMESH::NumericalFunctor_i* aNumericalFunctor =
1936 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1938 // Update Python script
1939 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1941 declareMeshModified( /*isReComputeSafe=*/false );
1944 SMESH_CATCH( SMESH::throwCorbaException );
1948 //================================================================================
1950 * \brief Split each of quadrangles into 4 triangles.
1951 * \param [in] theObject - theQuads Container of quadrangles to split.
1953 //================================================================================
1955 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1956 throw (SALOME::SALOME_Exception)
1961 TIDSortedElemSet faces;
1962 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1964 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1966 getEditor().QuadTo4Tri( faces );
1967 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1969 declareMeshModified( /*isReComputeSafe=*/false );
1971 SMESH_CATCH( SMESH::throwCorbaException );
1974 //=============================================================================
1976 * \brief Split quadrangles into triangles.
1978 //=============================================================================
1980 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1981 CORBA::Boolean Diag13)
1982 throw (SALOME::SALOME_Exception)
1987 SMESHDS_Mesh* aMesh = getMeshDS();
1988 TIDSortedElemSet faces;
1989 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1991 // Update Python script
1992 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1993 << IDsOfElements << ", " << Diag13 << " )";
1995 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1997 declareMeshModified( /*isReComputeSafe=*/ !stat );
2000 SMESH_CATCH( SMESH::throwCorbaException );
2004 //=============================================================================
2006 * \brief Split quadrangles into triangles.
2008 //=============================================================================
2010 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
2011 CORBA::Boolean Diag13)
2012 throw (SALOME::SALOME_Exception)
2017 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2019 prepareIdSource( theObject );
2020 SMESH::long_array_var anElementsId = theObject->GetIDs();
2021 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2023 // Update Python script
2024 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2025 << theObject << ", " << Diag13 << " )";
2027 declareMeshModified( /*isReComputeSafe=*/!isDone );
2030 SMESH_CATCH( SMESH::throwCorbaException );
2035 //=============================================================================
2037 * Find better splitting of the given quadrangle.
2038 * \param IDOfQuad ID of the quadrangle to be split.
2039 * \param Criterion A criterion to choose a diagonal for splitting.
2040 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2041 * diagonal is better, 0 if error occurs.
2043 //=============================================================================
2045 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2046 SMESH::NumericalFunctor_ptr Criterion)
2047 throw (SALOME::SALOME_Exception)
2052 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2053 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2055 SMESH::NumericalFunctor_i* aNumericalFunctor =
2056 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2057 SMESH::Controls::NumericalFunctorPtr aCrit;
2058 if (aNumericalFunctor)
2059 aCrit = aNumericalFunctor->GetNumericalFunctor();
2061 aCrit.reset(new SMESH::Controls::AspectRatio());
2063 int id = getEditor().BestSplit(quad, aCrit);
2064 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2068 SMESH_CATCH( SMESH::throwCorbaException );
2072 //================================================================================
2074 * \brief Split volumic elements into tetrahedrons
2076 //================================================================================
2078 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2079 CORBA::Short methodFlags)
2080 throw (SALOME::SALOME_Exception)
2085 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2086 const int noneFacet = -1;
2087 prepareIdSource( elems );
2088 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2089 while ( volIt->more() )
2090 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2092 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2093 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2095 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2096 << elems << ", " << methodFlags << " )";
2098 SMESH_CATCH( SMESH::throwCorbaException );
2101 //================================================================================
2103 * \brief Split hexahedra into triangular prisms
2104 * \param elems - elements to split
2105 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2106 * to split into triangles
2107 * \param methodFlags - flags passing splitting method:
2108 * 1 - split the hexahedron into 2 prisms
2109 * 2 - split the hexahedron into 4 prisms
2111 //================================================================================
2113 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2114 const SMESH::PointStruct & startHexPoint,
2115 const SMESH::DirStruct& facetToSplitNormal,
2116 CORBA::Short methodFlags,
2117 CORBA::Boolean allDomains)
2118 throw (SALOME::SALOME_Exception)
2122 prepareIdSource( elems );
2124 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2127 gp_Dir( facetToSplitNormal.PS.x,
2128 facetToSplitNormal.PS.y,
2129 facetToSplitNormal.PS.z ));
2130 TIDSortedElemSet elemSet;
2131 prepareIdSource( elems );
2132 SMESH::long_array_var anElementsId = elems->GetIDs();
2133 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2134 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2136 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2137 while ( !elemSet.empty() )
2139 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2143 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2144 for ( ; ef != elemFacets.end(); ++ef )
2145 elemSet.erase( ef->first );
2148 if ( methodFlags == 2 )
2149 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2151 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2153 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2154 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2156 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2158 << startHexPoint << ", "
2159 << facetToSplitNormal<< ", "
2160 << methodFlags<< ", "
2161 << allDomains << " )";
2163 SMESH_CATCH( SMESH::throwCorbaException );
2166 //================================================================================
2168 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2169 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2170 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2171 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2172 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2173 * will be split in order to keep the mesh conformal.
2174 * \param elems - elements to split
2176 //================================================================================
2178 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2179 throw (SALOME::SALOME_Exception)
2184 TIDSortedElemSet elemSet;
2185 for ( size_t i = 0; i < theElems.length(); ++i )
2187 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2188 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2189 if ( mesh->GetId() != myMesh_i->GetId() )
2190 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2192 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2194 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2196 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2198 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2199 << theElems << " )";
2201 SMESH_CATCH( SMESH::throwCorbaException );
2204 //=======================================================================
2207 //=======================================================================
2210 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2211 const SMESH::long_array & IDsOfFixedNodes,
2212 CORBA::Long MaxNbOfIterations,
2213 CORBA::Double MaxAspectRatio,
2214 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2215 throw (SALOME::SALOME_Exception)
2217 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2218 MaxAspectRatio, Method, false );
2222 //=======================================================================
2223 //function : SmoothParametric
2225 //=======================================================================
2228 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2229 const SMESH::long_array & IDsOfFixedNodes,
2230 CORBA::Long MaxNbOfIterations,
2231 CORBA::Double MaxAspectRatio,
2232 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2233 throw (SALOME::SALOME_Exception)
2235 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2236 MaxAspectRatio, Method, true );
2240 //=======================================================================
2241 //function : SmoothObject
2243 //=======================================================================
2246 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2247 const SMESH::long_array & IDsOfFixedNodes,
2248 CORBA::Long MaxNbOfIterations,
2249 CORBA::Double MaxAspectRatio,
2250 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2251 throw (SALOME::SALOME_Exception)
2253 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2254 MaxAspectRatio, Method, false);
2258 //=======================================================================
2259 //function : SmoothParametricObject
2261 //=======================================================================
2264 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2265 const SMESH::long_array & IDsOfFixedNodes,
2266 CORBA::Long MaxNbOfIterations,
2267 CORBA::Double MaxAspectRatio,
2268 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2269 throw (SALOME::SALOME_Exception)
2271 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2272 MaxAspectRatio, Method, true);
2276 //=============================================================================
2280 //=============================================================================
2283 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2284 const SMESH::long_array & IDsOfFixedNodes,
2285 CORBA::Long MaxNbOfIterations,
2286 CORBA::Double MaxAspectRatio,
2287 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2289 throw (SALOME::SALOME_Exception)
2294 SMESHDS_Mesh* aMesh = getMeshDS();
2296 TIDSortedElemSet elements;
2297 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2299 set<const SMDS_MeshNode*> fixedNodes;
2300 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2301 CORBA::Long index = IDsOfFixedNodes[i];
2302 const SMDS_MeshNode * node = aMesh->FindNode(index);
2304 fixedNodes.insert( node );
2306 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2307 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2308 method = ::SMESH_MeshEditor::CENTROIDAL;
2310 getEditor().Smooth(elements, fixedNodes, method,
2311 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2313 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2315 // Update Python script
2316 TPythonDump() << "isDone = " << this << "."
2317 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2318 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2319 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2320 << "SMESH.SMESH_MeshEditor."
2321 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2322 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2326 SMESH_CATCH( SMESH::throwCorbaException );
2330 //=============================================================================
2334 //=============================================================================
2337 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2338 const SMESH::long_array & IDsOfFixedNodes,
2339 CORBA::Long MaxNbOfIterations,
2340 CORBA::Double MaxAspectRatio,
2341 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2343 throw (SALOME::SALOME_Exception)
2348 TPythonDump aTPythonDump; // suppress dump in smooth()
2350 prepareIdSource( theObject );
2351 SMESH::long_array_var anElementsId = theObject->GetIDs();
2352 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2353 MaxAspectRatio, Method, IsParametric);
2355 // Update Python script
2356 aTPythonDump << "isDone = " << this << "."
2357 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2358 << theObject << ", " << IDsOfFixedNodes << ", "
2359 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2360 << "SMESH.SMESH_MeshEditor."
2361 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2362 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2366 SMESH_CATCH( SMESH::throwCorbaException );
2370 //=============================================================================
2374 //=============================================================================
2376 void SMESH_MeshEditor_i::RenumberNodes()
2377 throw (SALOME::SALOME_Exception)
2380 // Update Python script
2381 TPythonDump() << this << ".RenumberNodes()";
2383 getMeshDS()->Renumber( true );
2385 SMESH_CATCH( SMESH::throwCorbaException );
2388 //=============================================================================
2392 //=============================================================================
2394 void SMESH_MeshEditor_i::RenumberElements()
2395 throw (SALOME::SALOME_Exception)
2398 // Update Python script
2399 TPythonDump() << this << ".RenumberElements()";
2401 getMeshDS()->Renumber( false );
2403 SMESH_CATCH( SMESH::throwCorbaException );
2406 //=======================================================================
2408 * \brief Return groups by their IDs
2410 //=======================================================================
2412 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2413 throw (SALOME::SALOME_Exception)
2418 myMesh_i->CreateGroupServants();
2419 return myMesh_i->GetGroups( *groupIDs );
2421 SMESH_CATCH( SMESH::throwCorbaException );
2425 //=======================================================================
2426 //function : RotationSweepObjects
2428 //=======================================================================
2430 SMESH::ListOfGroups*
2431 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2432 const SMESH::ListOfIDSources & theEdges,
2433 const SMESH::ListOfIDSources & theFaces,
2434 const SMESH::AxisStruct & theAxis,
2435 CORBA::Double theAngleInRadians,
2436 CORBA::Long theNbOfSteps,
2437 CORBA::Double theTolerance,
2438 const bool theMakeGroups)
2439 throw (SALOME::SALOME_Exception)
2444 TIDSortedElemSet elemsNodes[2];
2445 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2446 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2447 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2449 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2450 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2451 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2452 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2454 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2455 bool makeWalls=true;
2456 if ( myIsPreviewMode )
2458 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2459 TPreviewMesh * tmpMesh = getPreviewMesh();
2460 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2461 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2462 workElements = & copyElements[0];
2463 //makeWalls = false; -- faces are needed for preview
2466 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2468 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2469 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2471 ::SMESH_MeshEditor::PGroupIDs groupIds =
2472 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2473 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2475 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2477 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2479 if ( !myIsPreviewMode )
2481 dumpGroupsList( aPythonDump, aGroups );
2482 aPythonDump << this<< ".RotationSweepObjects( "
2487 << TVar( theAngleInRadians ) << ", "
2488 << TVar( theNbOfSteps ) << ", "
2489 << TVar( theTolerance ) << ", "
2490 << theMakeGroups << " )";
2494 getPreviewMesh()->Remove( SMDSAbs_Volume );
2497 return aGroups ? aGroups : new SMESH::ListOfGroups;
2499 SMESH_CATCH( SMESH::throwCorbaException );
2503 namespace MeshEditor_I
2506 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2508 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2510 bool myIsExtrusionByNormal;
2512 static int makeFlags( CORBA::Boolean MakeGroups,
2513 CORBA::Boolean ScaleVariation = false,
2514 CORBA::Boolean AngleVariation = false,
2515 CORBA::Boolean ByAverageNormal = false,
2516 CORBA::Boolean UseInputElemsOnly = false,
2517 CORBA::Long Flags = 0,
2518 CORBA::Boolean MakeBoundary = true )
2520 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2521 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2522 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2523 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2524 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2525 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2529 ExtrusionParams(const SMESH::DirStruct & theDir,
2530 CORBA::Long theNbOfSteps,
2531 const SMESH::double_array & theScaleFactors,
2532 CORBA::Boolean theScaleVariation,
2533 const SMESH::double_array & theAngles,
2534 CORBA::Boolean theAngleVariation,
2535 const SMESH::double_array & theBasePoint,
2536 CORBA::Boolean theMakeGroups):
2537 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2541 toList( theScaleFactors ),
2542 toList( theAngles ),
2543 TBasePoint( theBasePoint ),
2544 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2545 myIsExtrusionByNormal( false )
2549 ExtrusionParams(const SMESH::DirStruct & theDir,
2550 CORBA::Long theNbOfSteps,
2551 CORBA::Boolean theMakeGroups,
2552 CORBA::Long theExtrFlags,
2553 CORBA::Double theSewTolerance):
2554 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2558 std::list<double>(),
2559 std::list<double>(),
2561 makeFlags( theMakeGroups, false, false, false, false,
2562 theExtrFlags, false ),
2564 myIsExtrusionByNormal( false )
2567 // params for extrusion by normal
2568 ExtrusionParams(CORBA::Double theStepSize,
2569 CORBA::Long theNbOfSteps,
2570 CORBA::Short theDim,
2571 CORBA::Boolean theByAverageNormal,
2572 CORBA::Boolean theUseInputElemsOnly,
2573 CORBA::Boolean theMakeGroups ):
2574 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2576 makeFlags( theMakeGroups, false, false,
2577 theByAverageNormal, theUseInputElemsOnly ),
2579 myIsExtrusionByNormal( true )
2585 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2588 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2590 std::list<double> scales;
2591 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2592 scales.push_back( theScaleFactors[i] );
2598 // structure used to convert SMESH::double_array to gp_XYZ*
2602 TBasePoint( const SMESH::double_array & theBasePoint )
2605 if ( theBasePoint.length() == 3 )
2607 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2611 operator const gp_XYZ*() const { return pp; }
2616 //=======================================================================
2618 * \brief Generate dim+1 elements by extrusion of elements along vector
2619 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2620 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2621 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2622 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2623 * \param [in] nbOfSteps - number of elements to generate from one element
2624 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2625 * corresponding to groups the input elements included in.
2626 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2628 //=======================================================================
2630 SMESH::ListOfGroups*
2631 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2632 const SMESH::ListOfIDSources & theEdges,
2633 const SMESH::ListOfIDSources & theFaces,
2634 const SMESH::DirStruct & theStepVector,
2635 CORBA::Long theNbOfSteps,
2636 CORBA::Boolean theToMakeGroups,
2637 const SMESH::double_array & theScaleFactors,
2638 CORBA::Boolean theScalesVariation,
2639 const SMESH::double_array & theBasePoint,
2640 const SMESH::double_array & theAngles,
2641 CORBA::Boolean theAnglesVariation)
2642 throw (SALOME::SALOME_Exception)
2647 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2648 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2650 TIDSortedElemSet elemsNodes[2];
2651 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2652 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2653 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2655 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2656 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2657 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2658 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2660 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2661 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2662 if ( myIsPreviewMode )
2664 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2665 // previewType = SMDSAbs_Edge;
2667 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2668 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2669 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2670 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2671 workElements = & copyElements[0];
2673 params.SetNoGroups();
2675 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2677 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2678 ::SMESH_MeshEditor::PGroupIDs groupIds =
2679 getEditor().ExtrusionSweep( workElements, params, aHistory );
2681 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2683 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2685 if ( !myIsPreviewMode )
2687 dumpGroupsList( aPythonDump, aGroups );
2688 aPythonDump << this<< ".ExtrusionSweepObjects( "
2692 << theStepVector << ", "
2693 << TVar( theNbOfSteps ) << ", "
2694 << theToMakeGroups << ", "
2695 << TVar( theScaleFactors ) << ", "
2696 << theScalesVariation << ", "
2697 << TVar( theBasePoint ) << ", "
2698 << TVar( theAngles ) << ", "
2699 << theAnglesVariation << " )";
2703 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2706 return aGroups ? aGroups : new SMESH::ListOfGroups;
2708 SMESH_CATCH( SMESH::throwCorbaException );
2712 //=======================================================================
2713 //function : ExtrusionByNormal
2715 //=======================================================================
2717 SMESH::ListOfGroups*
2718 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2719 CORBA::Double stepSize,
2720 CORBA::Long nbOfSteps,
2721 CORBA::Boolean byAverageNormal,
2722 CORBA::Boolean useInputElemsOnly,
2723 CORBA::Boolean makeGroups,
2725 throw (SALOME::SALOME_Exception)
2730 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2732 ExtrusionParams params( stepSize, nbOfSteps, dim,
2733 byAverageNormal, useInputElemsOnly, makeGroups );
2735 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2736 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2738 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2739 if (( elemTypes->length() == 1 ) &&
2740 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2741 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2744 TIDSortedElemSet elemsNodes[2];
2745 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2746 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2748 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2749 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2750 if ( myIsPreviewMode )
2752 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2753 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2754 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2755 workElements = & copyElements[0];
2757 params.SetNoGroups();
2760 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2761 ::SMESH_MeshEditor::PGroupIDs groupIds =
2762 getEditor().ExtrusionSweep( workElements, params, aHistory );
2764 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2766 if (!myIsPreviewMode) {
2767 dumpGroupsList(aPythonDump, aGroups);
2768 aPythonDump << this << ".ExtrusionByNormal( " << objects
2769 << ", " << TVar( stepSize )
2770 << ", " << TVar( nbOfSteps )
2771 << ", " << byAverageNormal
2772 << ", " << useInputElemsOnly
2773 << ", " << makeGroups
2779 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2782 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2784 return aGroups ? aGroups : new SMESH::ListOfGroups;
2786 SMESH_CATCH( SMESH::throwCorbaException );
2790 //=======================================================================
2791 //function : AdvancedExtrusion
2793 //=======================================================================
2795 SMESH::ListOfGroups*
2796 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2797 const SMESH::DirStruct & theStepVector,
2798 CORBA::Long theNbOfSteps,
2799 CORBA::Long theExtrFlags,
2800 CORBA::Double theSewTolerance,
2801 CORBA::Boolean theMakeGroups)
2802 throw (SALOME::SALOME_Exception)
2807 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2809 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2810 theExtrFlags, theSewTolerance );
2812 TIDSortedElemSet elemsNodes[2];
2813 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2815 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2816 ::SMESH_MeshEditor::PGroupIDs groupIds =
2817 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2819 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2821 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2823 if ( !myIsPreviewMode ) {
2824 dumpGroupsList(aPythonDump, aGroups);
2825 aPythonDump << this << ".AdvancedExtrusion( "
2826 << theIDsOfElements << ", "
2827 << theStepVector << ", "
2828 << theNbOfSteps << ", "
2829 << theExtrFlags << ", "
2830 << theSewTolerance << ", "
2831 << theMakeGroups << " )";
2835 getPreviewMesh()->Remove( SMDSAbs_Volume );
2838 return aGroups ? aGroups : new SMESH::ListOfGroups;
2840 SMESH_CATCH( SMESH::throwCorbaException );
2844 //================================================================================
2846 * \brief Convert extrusion error to IDL enum
2848 //================================================================================
2852 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2854 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2858 RETCASE( EXTR_NO_ELEMENTS );
2859 RETCASE( EXTR_PATH_NOT_EDGE );
2860 RETCASE( EXTR_BAD_PATH_SHAPE );
2861 RETCASE( EXTR_BAD_STARTING_NODE );
2862 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2863 RETCASE( EXTR_CANT_GET_TANGENT );
2865 return SMESH::SMESH_MeshEditor::EXTR_OK;
2869 //=======================================================================
2870 //function : extrusionAlongPath
2872 //=======================================================================
2873 SMESH::ListOfGroups*
2874 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2875 const SMESH::ListOfIDSources & theEdges,
2876 const SMESH::ListOfIDSources & theFaces,
2877 SMESH::SMESH_IDSource_ptr thePathObject,
2878 GEOM::GEOM_Object_ptr thePathShape,
2879 CORBA::Long theNodeStart,
2880 CORBA::Boolean theHasAngles,
2881 const SMESH::double_array & theAngles,
2882 CORBA::Boolean theAnglesVariation,
2883 CORBA::Boolean theHasRefPoint,
2884 const SMESH::PointStruct & theRefPoint,
2886 const SMESH::double_array & theScaleFactors,
2887 CORBA::Boolean theScalesVariation,
2888 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2889 throw (SALOME::SALOME_Exception)
2894 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2896 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2897 if ( thePathObject->_is_nil() )
2898 return aGroups._retn();
2901 SMDS_ElemIteratorPtr pathEdgesIterator;
2903 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2904 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2906 // get a sub-mesh of thePathShape
2907 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2908 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2910 return aGroups._retn();
2912 if ( !aSubMesh->GetSubMeshDS() )
2914 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2915 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2916 if ( !aSubMesh->GetSubMeshDS() )
2917 return aGroups._retn();
2919 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2920 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2921 if ( !pathEdgesIterator->more() ||
2922 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2923 return aGroups._retn();
2925 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2929 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2930 prepareIdSource( thePathObject );
2931 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2932 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2933 return aGroups._retn();
2938 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2939 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2943 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2944 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2946 return aGroups._retn();
2949 TIDSortedElemSet elemsNodes[2];
2950 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2951 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2952 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2954 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2955 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2956 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2957 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2959 list<double> angles = ExtrusionParams::toList( theAngles );
2960 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2962 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2963 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2965 int nbOldGroups = myMesh->NbGroup();
2967 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2968 if ( myIsPreviewMode )
2970 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2971 TPreviewMesh * tmpMesh = getPreviewMesh();
2972 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2973 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2974 workElements = & copyElements[0];
2975 theMakeGroups = false;
2978 ::SMESH_MeshEditor::Extrusion_Error error =
2979 getEditor().ExtrusionAlongTrack( workElements,
2980 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2981 angles, theAnglesVariation,
2982 scales, theScalesVariation,
2983 refPntPtr, theMakeGroups );
2985 declareMeshModified( /*isReComputeSafe=*/true );
2986 theError = convExtrError( error );
2988 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2989 if ( theMakeGroups ) {
2990 list<int> groupIDs = myMesh->GetGroupIds();
2991 list<int>::iterator newBegin = groupIDs.begin();
2992 std::advance( newBegin, nbOldGroups ); // skip old groups
2993 groupIDs.erase( groupIDs.begin(), newBegin );
2994 aGroups = getGroups( & groupIDs );
2995 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2998 if ( !myIsPreviewMode ) {
2999 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
3000 else aPythonDump << "(_noGroups, error) = ";
3001 aPythonDump << this << ".ExtrusionAlongPathObjects( "
3005 << thePathObject << ", "
3006 << thePathShape << ", "
3007 << theNodeStart << ", "
3008 << theHasAngles << ", "
3009 << TVar( theAngles ) << ", "
3010 << theAnglesVariation << ", "
3011 << theHasRefPoint << ", "
3012 << "SMESH.PointStruct( "
3013 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3014 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3015 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
3016 << theMakeGroups << ", "
3017 << TVar( theScaleFactors ) << ", "
3018 << theScalesVariation << " )";
3022 getPreviewMesh()->Remove( SMDSAbs_Volume );
3025 return aGroups._retn();
3027 SMESH_CATCH( SMESH::throwCorbaException );
3031 //================================================================================
3033 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3034 * of given angles along path steps
3035 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3036 * which proceeds the extrusion
3037 * \param PathShape is shape(edge); as the mesh can be complex, the edge
3038 * is used to define the sub-mesh for the path
3040 //================================================================================
3042 SMESH::double_array*
3043 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3044 GEOM::GEOM_Object_ptr thePathShape,
3045 const SMESH::double_array & theAngles)
3047 SMESH::double_array_var aResult = new SMESH::double_array();
3048 int nbAngles = theAngles.length();
3049 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3051 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3052 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3053 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3054 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3055 return aResult._retn();
3056 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3057 if ( nbSteps == nbAngles )
3059 aResult.inout() = theAngles;
3063 aResult->length( nbSteps );
3064 double rAn2St = double( nbAngles ) / double( nbSteps );
3065 double angPrev = 0, angle;
3066 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3068 double angCur = rAn2St * ( iSt+1 );
3069 double angCurFloor = floor( angCur );
3070 double angPrevFloor = floor( angPrev );
3071 if ( angPrevFloor == angCurFloor )
3072 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3075 int iP = int( angPrevFloor );
3076 double angPrevCeil = ceil(angPrev);
3077 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3079 int iC = int( angCurFloor );
3080 if ( iC < nbAngles )
3081 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3083 iP = int( angPrevCeil );
3085 angle += theAngles[ iC ];
3087 aResult[ iSt ] = angle;
3092 // Update Python script
3093 TPythonDump() << "rotAngles = " << theAngles;
3094 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3095 << thePathMesh << ", "
3096 << thePathShape << ", "
3099 return aResult._retn();
3102 //=======================================================================
3105 //=======================================================================
3107 SMESH::ListOfGroups*
3108 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3109 const SMESH::AxisStruct & theAxis,
3110 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3111 CORBA::Boolean theCopy,
3113 ::SMESH_Mesh* theTargetMesh)
3114 throw (SALOME::SALOME_Exception)
3119 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3120 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3122 if ( theTargetMesh )
3126 switch ( theMirrorType ) {
3127 case SMESH::SMESH_MeshEditor::POINT:
3128 aTrsf.SetMirror( P );
3130 case SMESH::SMESH_MeshEditor::AXIS:
3131 aTrsf.SetMirror( gp_Ax1( P, V ));
3134 aTrsf.SetMirror( gp_Ax2( P, V ));
3137 TIDSortedElemSet copyElements;
3138 TIDSortedElemSet* workElements = & theElements;
3140 if ( myIsPreviewMode )
3142 TPreviewMesh * tmpMesh = getPreviewMesh();
3143 tmpMesh->Copy( theElements, copyElements);
3144 if ( !theCopy && !theTargetMesh )
3146 TIDSortedElemSet elemsAround, elemsAroundCopy;
3147 getElementsAround( theElements, getMeshDS(), elemsAround );
3148 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3150 workElements = & copyElements;
3151 theMakeGroups = false;
3154 ::SMESH_MeshEditor::PGroupIDs groupIds =
3155 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3157 if ( !myIsPreviewMode )
3159 if ( theTargetMesh )
3160 theTargetMesh->GetMeshDS()->Modified();
3162 declareMeshModified( /*isReComputeSafe=*/false );
3165 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3167 SMESH_CATCH( SMESH::throwCorbaException );
3171 //=======================================================================
3174 //=======================================================================
3176 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3177 const SMESH::AxisStruct & theAxis,
3178 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3179 CORBA::Boolean theCopy)
3180 throw (SALOME::SALOME_Exception)
3182 if ( !myIsPreviewMode ) {
3183 TPythonDump() << this << ".Mirror( "
3184 << theIDsOfElements << ", "
3186 << mirrorTypeName(theMirrorType) << ", "
3189 if ( theIDsOfElements.length() > 0 )
3191 TIDSortedElemSet elements;
3192 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3193 mirror(elements, theAxis, theMirrorType, theCopy, false);
3198 //=======================================================================
3199 //function : MirrorObject
3201 //=======================================================================
3203 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3204 const SMESH::AxisStruct & theAxis,
3205 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3206 CORBA::Boolean theCopy)
3207 throw (SALOME::SALOME_Exception)
3209 if ( !myIsPreviewMode ) {
3210 TPythonDump() << this << ".MirrorObject( "
3211 << theObject << ", "
3213 << mirrorTypeName(theMirrorType) << ", "
3216 TIDSortedElemSet elements;
3218 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3220 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3221 mirror(elements, theAxis, theMirrorType, theCopy, false);
3224 //=======================================================================
3225 //function : MirrorMakeGroups
3227 //=======================================================================
3229 SMESH::ListOfGroups*
3230 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3231 const SMESH::AxisStruct& theMirror,
3232 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3233 throw (SALOME::SALOME_Exception)
3235 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3237 SMESH::ListOfGroups * aGroups = 0;
3238 if ( theIDsOfElements.length() > 0 )
3240 TIDSortedElemSet elements;
3241 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3242 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3244 if (!myIsPreviewMode) {
3245 dumpGroupsList(aPythonDump, aGroups);
3246 aPythonDump << this << ".MirrorMakeGroups( "
3247 << theIDsOfElements << ", "
3248 << theMirror << ", "
3249 << mirrorTypeName(theMirrorType) << " )";
3254 //=======================================================================
3255 //function : MirrorObjectMakeGroups
3257 //=======================================================================
3259 SMESH::ListOfGroups*
3260 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3261 const SMESH::AxisStruct& theMirror,
3262 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3263 throw (SALOME::SALOME_Exception)
3265 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3267 SMESH::ListOfGroups * aGroups = 0;
3268 TIDSortedElemSet elements;
3269 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3270 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3272 if (!myIsPreviewMode)
3274 dumpGroupsList(aPythonDump,aGroups);
3275 aPythonDump << this << ".MirrorObjectMakeGroups( "
3276 << theObject << ", "
3277 << theMirror << ", "
3278 << mirrorTypeName(theMirrorType) << " )";
3283 //=======================================================================
3284 //function : MirrorMakeMesh
3286 //=======================================================================
3288 SMESH::SMESH_Mesh_ptr
3289 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3290 const SMESH::AxisStruct& theMirror,
3291 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3292 CORBA::Boolean theCopyGroups,
3293 const char* theMeshName)
3294 throw (SALOME::SALOME_Exception)
3296 SMESH_Mesh_i* mesh_i;
3297 SMESH::SMESH_Mesh_var mesh;
3298 { // open new scope to dump "MakeMesh" command
3299 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3301 TPythonDump pydump; // to prevent dump at mesh creation
3303 mesh = makeMesh( theMeshName );
3304 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3305 if (mesh_i && theIDsOfElements.length() > 0 )
3307 TIDSortedElemSet elements;
3308 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3309 mirror(elements, theMirror, theMirrorType,
3310 false, theCopyGroups, & mesh_i->GetImpl());
3311 mesh_i->CreateGroupServants();
3314 if (!myIsPreviewMode) {
3315 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3316 << theIDsOfElements << ", "
3317 << theMirror << ", "
3318 << mirrorTypeName(theMirrorType) << ", "
3319 << theCopyGroups << ", '"
3320 << theMeshName << "' )";
3325 if (!myIsPreviewMode && mesh_i)
3326 mesh_i->GetGroups();
3328 return mesh._retn();
3331 //=======================================================================
3332 //function : MirrorObjectMakeMesh
3334 //=======================================================================
3336 SMESH::SMESH_Mesh_ptr
3337 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3338 const SMESH::AxisStruct& theMirror,
3339 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3340 CORBA::Boolean theCopyGroups,
3341 const char* theMeshName)
3342 throw (SALOME::SALOME_Exception)
3344 SMESH_Mesh_i* mesh_i;
3345 SMESH::SMESH_Mesh_var mesh;
3346 { // open new scope to dump "MakeMesh" command
3347 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3349 TPythonDump pydump; // to prevent dump at mesh creation
3351 mesh = makeMesh( theMeshName );
3352 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3353 TIDSortedElemSet elements;
3355 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3357 mirror(elements, theMirror, theMirrorType,
3358 false, theCopyGroups, & mesh_i->GetImpl());
3359 mesh_i->CreateGroupServants();
3361 if (!myIsPreviewMode) {
3362 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3363 << theObject << ", "
3364 << theMirror << ", "
3365 << mirrorTypeName(theMirrorType) << ", "
3366 << theCopyGroups << ", '"
3367 << theMeshName << "' )";
3372 if (!myIsPreviewMode && mesh_i)
3373 mesh_i->GetGroups();
3375 return mesh._retn();
3378 //=======================================================================
3379 //function : translate
3381 //=======================================================================
3383 SMESH::ListOfGroups*
3384 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3385 const SMESH::DirStruct & theVector,
3386 CORBA::Boolean theCopy,
3388 ::SMESH_Mesh* theTargetMesh)
3389 throw (SALOME::SALOME_Exception)
3394 if ( theTargetMesh )
3398 const SMESH::PointStruct * P = &theVector.PS;
3399 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3401 TIDSortedElemSet copyElements;
3402 TIDSortedElemSet* workElements = &theElements;
3404 if ( myIsPreviewMode )
3406 TPreviewMesh * tmpMesh = getPreviewMesh();
3407 tmpMesh->Copy( theElements, copyElements);
3408 if ( !theCopy && !theTargetMesh )
3410 TIDSortedElemSet elemsAround, elemsAroundCopy;
3411 getElementsAround( theElements, getMeshDS(), elemsAround );
3412 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3414 workElements = & copyElements;
3415 theMakeGroups = false;
3418 ::SMESH_MeshEditor::PGroupIDs groupIds =
3419 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3421 if ( !myIsPreviewMode )
3423 if ( theTargetMesh )
3424 theTargetMesh->GetMeshDS()->Modified();
3426 declareMeshModified( /*isReComputeSafe=*/false );
3429 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3431 SMESH_CATCH( SMESH::throwCorbaException );
3435 //=======================================================================
3436 //function : Translate
3438 //=======================================================================
3440 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3441 const SMESH::DirStruct & theVector,
3442 CORBA::Boolean theCopy)
3443 throw (SALOME::SALOME_Exception)
3445 if (!myIsPreviewMode) {
3446 TPythonDump() << this << ".Translate( "
3447 << theIDsOfElements << ", "
3448 << theVector << ", "
3451 if (theIDsOfElements.length()) {
3452 TIDSortedElemSet elements;
3453 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3454 translate(elements, theVector, theCopy, false);
3458 //=======================================================================
3459 //function : TranslateObject
3461 //=======================================================================
3463 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3464 const SMESH::DirStruct & theVector,
3465 CORBA::Boolean theCopy)
3466 throw (SALOME::SALOME_Exception)
3468 if (!myIsPreviewMode) {
3469 TPythonDump() << this << ".TranslateObject( "
3470 << theObject << ", "
3471 << theVector << ", "
3474 TIDSortedElemSet elements;
3476 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3478 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3479 translate(elements, theVector, theCopy, false);
3482 //=======================================================================
3483 //function : TranslateMakeGroups
3485 //=======================================================================
3487 SMESH::ListOfGroups*
3488 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3489 const SMESH::DirStruct& theVector)
3490 throw (SALOME::SALOME_Exception)
3492 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3494 SMESH::ListOfGroups * aGroups = 0;
3495 if (theIDsOfElements.length()) {
3496 TIDSortedElemSet elements;
3497 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3498 aGroups = translate(elements,theVector,true,true);
3500 if (!myIsPreviewMode) {
3501 dumpGroupsList(aPythonDump, aGroups);
3502 aPythonDump << this << ".TranslateMakeGroups( "
3503 << theIDsOfElements << ", "
3504 << theVector << " )";
3509 //=======================================================================
3510 //function : TranslateObjectMakeGroups
3512 //=======================================================================
3514 SMESH::ListOfGroups*
3515 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3516 const SMESH::DirStruct& theVector)
3517 throw (SALOME::SALOME_Exception)
3519 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3521 SMESH::ListOfGroups * aGroups = 0;
3522 TIDSortedElemSet elements;
3523 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3524 aGroups = translate(elements, theVector, true, true);
3526 if (!myIsPreviewMode) {
3527 dumpGroupsList(aPythonDump, aGroups);
3528 aPythonDump << this << ".TranslateObjectMakeGroups( "
3529 << theObject << ", "
3530 << theVector << " )";
3535 //=======================================================================
3536 //function : TranslateMakeMesh
3538 //=======================================================================
3540 SMESH::SMESH_Mesh_ptr
3541 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3542 const SMESH::DirStruct& theVector,
3543 CORBA::Boolean theCopyGroups,
3544 const char* theMeshName)
3545 throw (SALOME::SALOME_Exception)
3547 SMESH_Mesh_i* mesh_i;
3548 SMESH::SMESH_Mesh_var mesh;
3550 { // open new scope to dump "MakeMesh" command
3551 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3553 TPythonDump pydump; // to prevent dump at mesh creation
3555 mesh = makeMesh( theMeshName );
3556 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3558 if ( mesh_i && theIDsOfElements.length() )
3560 TIDSortedElemSet elements;
3561 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3562 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3563 mesh_i->CreateGroupServants();
3566 if ( !myIsPreviewMode ) {
3567 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3568 << theIDsOfElements << ", "
3569 << theVector << ", "
3570 << theCopyGroups << ", '"
3571 << theMeshName << "' )";
3576 if (!myIsPreviewMode && mesh_i)
3577 mesh_i->GetGroups();
3579 return mesh._retn();
3582 //=======================================================================
3583 //function : TranslateObjectMakeMesh
3585 //=======================================================================
3587 SMESH::SMESH_Mesh_ptr
3588 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3589 const SMESH::DirStruct& theVector,
3590 CORBA::Boolean theCopyGroups,
3591 const char* theMeshName)
3592 throw (SALOME::SALOME_Exception)
3595 SMESH_Mesh_i* mesh_i;
3596 SMESH::SMESH_Mesh_var mesh;
3597 { // open new scope to dump "MakeMesh" command
3598 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3600 TPythonDump pydump; // to prevent dump at mesh creation
3601 mesh = makeMesh( theMeshName );
3602 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3604 TIDSortedElemSet elements;
3606 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3608 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3609 mesh_i->CreateGroupServants();
3611 if ( !myIsPreviewMode ) {
3612 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3613 << theObject << ", "
3614 << theVector << ", "
3615 << theCopyGroups << ", '"
3616 << theMeshName << "' )";
3621 if (!myIsPreviewMode && mesh_i)
3622 mesh_i->GetGroups();
3624 return mesh._retn();
3626 SMESH_CATCH( SMESH::throwCorbaException );
3630 //=======================================================================
3633 //=======================================================================
3635 SMESH::ListOfGroups*
3636 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3637 const SMESH::AxisStruct & theAxis,
3638 CORBA::Double theAngle,
3639 CORBA::Boolean theCopy,
3641 ::SMESH_Mesh* theTargetMesh)
3642 throw (SALOME::SALOME_Exception)
3647 if ( theTargetMesh )
3650 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3651 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3654 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3656 TIDSortedElemSet copyElements;
3657 TIDSortedElemSet* workElements = &theElements;
3658 if ( myIsPreviewMode ) {
3659 TPreviewMesh * tmpMesh = getPreviewMesh();
3660 tmpMesh->Copy( theElements, copyElements );
3661 if ( !theCopy && !theTargetMesh )
3663 TIDSortedElemSet elemsAround, elemsAroundCopy;
3664 getElementsAround( theElements, getMeshDS(), elemsAround );
3665 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3667 workElements = ©Elements;
3668 theMakeGroups = false;
3671 ::SMESH_MeshEditor::PGroupIDs groupIds =
3672 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3674 if ( !myIsPreviewMode)
3676 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3677 else declareMeshModified( /*isReComputeSafe=*/false );
3680 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3682 SMESH_CATCH( SMESH::throwCorbaException );
3686 //=======================================================================
3689 //=======================================================================
3691 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3692 const SMESH::AxisStruct & theAxis,
3693 CORBA::Double theAngle,
3694 CORBA::Boolean theCopy)
3695 throw (SALOME::SALOME_Exception)
3697 if (!myIsPreviewMode) {
3698 TPythonDump() << this << ".Rotate( "
3699 << theIDsOfElements << ", "
3701 << TVar( theAngle ) << ", "
3704 if (theIDsOfElements.length() > 0)
3706 TIDSortedElemSet elements;
3707 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3708 rotate(elements,theAxis,theAngle,theCopy,false);
3712 //=======================================================================
3713 //function : RotateObject
3715 //=======================================================================
3717 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3718 const SMESH::AxisStruct & theAxis,
3719 CORBA::Double theAngle,
3720 CORBA::Boolean theCopy)
3721 throw (SALOME::SALOME_Exception)
3723 if ( !myIsPreviewMode ) {
3724 TPythonDump() << this << ".RotateObject( "
3725 << theObject << ", "
3727 << TVar( theAngle ) << ", "
3730 TIDSortedElemSet elements;
3731 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3732 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3733 rotate(elements,theAxis,theAngle,theCopy,false);
3736 //=======================================================================
3737 //function : RotateMakeGroups
3739 //=======================================================================
3741 SMESH::ListOfGroups*
3742 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3743 const SMESH::AxisStruct& theAxis,
3744 CORBA::Double theAngle)
3745 throw (SALOME::SALOME_Exception)
3747 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3749 SMESH::ListOfGroups * aGroups = 0;
3750 if (theIDsOfElements.length() > 0)
3752 TIDSortedElemSet elements;
3753 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3754 aGroups = rotate(elements,theAxis,theAngle,true,true);
3756 if (!myIsPreviewMode) {
3757 dumpGroupsList(aPythonDump, aGroups);
3758 aPythonDump << this << ".RotateMakeGroups( "
3759 << theIDsOfElements << ", "
3761 << TVar( theAngle ) << " )";
3766 //=======================================================================
3767 //function : RotateObjectMakeGroups
3769 //=======================================================================
3771 SMESH::ListOfGroups*
3772 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3773 const SMESH::AxisStruct& theAxis,
3774 CORBA::Double theAngle)
3775 throw (SALOME::SALOME_Exception)
3777 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3779 SMESH::ListOfGroups * aGroups = 0;
3780 TIDSortedElemSet elements;
3781 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3782 aGroups = rotate(elements, theAxis, theAngle, true, true);
3784 if (!myIsPreviewMode) {
3785 dumpGroupsList(aPythonDump, aGroups);
3786 aPythonDump << this << ".RotateObjectMakeGroups( "
3787 << theObject << ", "
3789 << TVar( theAngle ) << " )";
3794 //=======================================================================
3795 //function : RotateMakeMesh
3797 //=======================================================================
3799 SMESH::SMESH_Mesh_ptr
3800 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3801 const SMESH::AxisStruct& theAxis,
3802 CORBA::Double theAngleInRadians,
3803 CORBA::Boolean theCopyGroups,
3804 const char* theMeshName)
3805 throw (SALOME::SALOME_Exception)
3808 SMESH::SMESH_Mesh_var mesh;
3809 SMESH_Mesh_i* mesh_i;
3811 { // open new scope to dump "MakeMesh" command
3812 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3814 TPythonDump pydump; // to prevent dump at mesh creation
3816 mesh = makeMesh( theMeshName );
3817 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3819 if ( mesh_i && theIDsOfElements.length() > 0 )
3821 TIDSortedElemSet elements;
3822 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3823 rotate(elements, theAxis, theAngleInRadians,
3824 false, theCopyGroups, & mesh_i->GetImpl());
3825 mesh_i->CreateGroupServants();
3827 if ( !myIsPreviewMode ) {
3828 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3829 << theIDsOfElements << ", "
3831 << TVar( theAngleInRadians ) << ", "
3832 << theCopyGroups << ", '"
3833 << theMeshName << "' )";
3838 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3839 mesh_i->GetGroups();
3841 return mesh._retn();
3843 SMESH_CATCH( SMESH::throwCorbaException );
3847 //=======================================================================
3848 //function : RotateObjectMakeMesh
3850 //=======================================================================
3852 SMESH::SMESH_Mesh_ptr
3853 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3854 const SMESH::AxisStruct& theAxis,
3855 CORBA::Double theAngleInRadians,
3856 CORBA::Boolean theCopyGroups,
3857 const char* theMeshName)
3858 throw (SALOME::SALOME_Exception)
3861 SMESH::SMESH_Mesh_var mesh;
3862 SMESH_Mesh_i* mesh_i;
3864 {// open new scope to dump "MakeMesh" command
3865 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3867 TPythonDump pydump; // to prevent dump at mesh creation
3868 mesh = makeMesh( theMeshName );
3869 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3871 TIDSortedElemSet elements;
3873 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3875 rotate(elements, theAxis, theAngleInRadians,
3876 false, theCopyGroups, & mesh_i->GetImpl());
3877 mesh_i->CreateGroupServants();
3879 if ( !myIsPreviewMode ) {
3880 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3881 << theObject << ", "
3883 << TVar( theAngleInRadians ) << ", "
3884 << theCopyGroups << ", '"
3885 << theMeshName << "' )";
3890 if (!myIsPreviewMode && mesh_i)
3891 mesh_i->GetGroups();
3893 return mesh._retn();
3895 SMESH_CATCH( SMESH::throwCorbaException );
3899 //=======================================================================
3902 //=======================================================================
3904 SMESH::ListOfGroups*
3905 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3906 const SMESH::PointStruct& thePoint,
3907 const SMESH::double_array& theScaleFact,
3908 CORBA::Boolean theCopy,
3910 ::SMESH_Mesh* theTargetMesh)
3911 throw (SALOME::SALOME_Exception)
3915 if ( theScaleFact.length() < 1 )
3916 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3917 if ( theScaleFact.length() == 2 )
3918 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3920 if ( theTargetMesh )
3923 TIDSortedElemSet elements;
3924 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3925 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3930 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3931 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3935 // fight against orthogonalization
3936 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3937 // 0, S[1], 0, thePoint.y * (1-S[1]),
3938 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3939 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3940 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3941 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3942 loc.SetCoord( thePoint.x * (1-S[0]),
3943 thePoint.y * (1-S[1]),
3944 thePoint.z * (1-S[2]));
3945 M.SetDiagonal( S[0], S[1], S[2] );
3947 TIDSortedElemSet copyElements;
3948 TIDSortedElemSet* workElements = &elements;
3949 if ( myIsPreviewMode )
3951 TPreviewMesh * tmpMesh = getPreviewMesh();
3952 tmpMesh->Copy( elements, copyElements);
3953 if ( !theCopy && !theTargetMesh )
3955 TIDSortedElemSet elemsAround, elemsAroundCopy;
3956 getElementsAround( elements, getMeshDS(), elemsAround );
3957 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3959 workElements = & copyElements;
3960 theMakeGroups = false;
3963 ::SMESH_MeshEditor::PGroupIDs groupIds =
3964 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3966 if ( !myIsPreviewMode )
3968 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3969 else declareMeshModified( /*isReComputeSafe=*/false );
3971 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3973 SMESH_CATCH( SMESH::throwCorbaException );
3977 //=======================================================================
3980 //=======================================================================
3982 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3983 const SMESH::PointStruct& thePoint,
3984 const SMESH::double_array& theScaleFact,
3985 CORBA::Boolean theCopy)
3986 throw (SALOME::SALOME_Exception)
3988 if ( !myIsPreviewMode ) {
3989 TPythonDump() << this << ".Scale( "
3990 << theObject << ", "
3992 << TVar( theScaleFact ) << ", "
3995 scale(theObject, thePoint, theScaleFact, theCopy, false);
3999 //=======================================================================
4000 //function : ScaleMakeGroups
4002 //=======================================================================
4004 SMESH::ListOfGroups*
4005 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4006 const SMESH::PointStruct& thePoint,
4007 const SMESH::double_array& theScaleFact)
4008 throw (SALOME::SALOME_Exception)
4010 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4012 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
4013 if (!myIsPreviewMode) {
4014 dumpGroupsList(aPythonDump, aGroups);
4015 aPythonDump << this << ".Scale("
4018 << TVar( theScaleFact ) << ",True,True)";
4024 //=======================================================================
4025 //function : ScaleMakeMesh
4027 //=======================================================================
4029 SMESH::SMESH_Mesh_ptr
4030 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4031 const SMESH::PointStruct& thePoint,
4032 const SMESH::double_array& theScaleFact,
4033 CORBA::Boolean theCopyGroups,
4034 const char* theMeshName)
4035 throw (SALOME::SALOME_Exception)
4037 SMESH_Mesh_i* mesh_i;
4038 SMESH::SMESH_Mesh_var mesh;
4039 { // open new scope to dump "MakeMesh" command
4040 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4042 TPythonDump pydump; // to prevent dump at mesh creation
4043 mesh = makeMesh( theMeshName );
4044 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4048 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4049 mesh_i->CreateGroupServants();
4051 if ( !myIsPreviewMode )
4052 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4053 << theObject << ", "
4055 << TVar( theScaleFact ) << ", "
4056 << theCopyGroups << ", '"
4057 << theMeshName << "' )";
4061 if (!myIsPreviewMode && mesh_i)
4062 mesh_i->GetGroups();
4064 return mesh._retn();
4067 //================================================================================
4069 * \brief Make an offset mesh from a source 2D mesh
4070 * \param [inout] theObject - source mesh. New elements are added to this mesh
4071 * if \a theMeshName is empty.
4072 * \param [in] theValue - offset value
4073 * \param [in] theCopyGroups - to generate groups
4074 * \param [in] theMeshName - optional name of a new mesh
4075 * \param [out] theGroups - new groups
4076 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4078 //================================================================================
4080 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4081 CORBA::Double theValue,
4082 CORBA::Boolean theCopyGroups,
4083 CORBA::Boolean theCopyElements,
4084 const char* theMeshName,
4085 SMESH::ListOfGroups_out theGroups)
4086 throw (SALOME::SALOME_Exception)
4091 SMESHDS_Mesh* aMeshDS = getMeshDS();
4093 SMESH::SMESH_Mesh_var mesh_var;
4094 ::SMESH_MeshEditor::PGroupIDs groupIds;
4098 TIDSortedElemSet elements, copyElements;
4099 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4100 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4103 SMESH_Mesh* tgtMesh = 0;
4104 if ( myIsPreviewMode )
4106 TPreviewMesh * tmpMesh = getPreviewMesh();
4108 tmpMesh->Copy( elements, copyElements );
4109 elements.swap( copyElements );
4110 theCopyGroups = false;
4111 theCopyElements = false;
4116 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4117 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4118 tgtMesh = & mesh_i->GetImpl();
4120 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4121 theCopyGroups, theCopyElements, !myIsPreviewMode );
4123 tgtMesh->GetMeshDS()->Modified();
4126 if ( myIsPreviewMode )
4128 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4132 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4134 // new mesh empty, remove it
4135 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4136 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4137 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4138 builder->RemoveObjectWithChildren( meshSO );
4139 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4141 if ( !groupIds ) // nothing changed in the current mesh
4142 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4144 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4146 // result of Offset() is a tuple (mesh, groups)
4147 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4148 else pyDump << mesh_var << ", ";
4149 pyDump << theGroups << " = " << this << ".Offset( "
4150 << theObject << ", "
4152 << theCopyGroups << ", "
4153 << theCopyElements << ", "
4154 << "'" << theMeshName<< "')";
4157 return mesh_var._retn();
4159 SMESH_CATCH( SMESH::throwCorbaException );
4160 return SMESH::SMESH_Mesh::_nil();
4163 //=======================================================================
4164 //function : findCoincidentNodes
4166 //=======================================================================
4168 void SMESH_MeshEditor_i::
4169 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4170 CORBA::Double Tolerance,
4171 SMESH::array_of_long_array_out GroupsOfNodes,
4172 CORBA::Boolean SeparateCornersAndMedium)
4174 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4175 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4177 GroupsOfNodes = new SMESH::array_of_long_array;
4178 GroupsOfNodes->length( aListOfListOfNodes.size() );
4179 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4180 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4182 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4183 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4184 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4185 aGroup.length( aListOfNodes.size() );
4186 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4187 aGroup[ j ] = (*lIt)->GetID();
4191 //=======================================================================
4192 //function : FindCoincidentNodes
4194 //=======================================================================
4196 void SMESH_MeshEditor_i::
4197 FindCoincidentNodes (CORBA::Double Tolerance,
4198 SMESH::array_of_long_array_out GroupsOfNodes,
4199 CORBA::Boolean SeparateCornersAndMedium)
4200 throw (SALOME::SALOME_Exception)
4205 TIDSortedNodeSet nodes; // no input nodes
4206 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4208 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4209 << Tolerance << ", "
4210 << SeparateCornersAndMedium << " )";
4212 SMESH_CATCH( SMESH::throwCorbaException );
4215 //=======================================================================
4216 //function : FindCoincidentNodesOnPart
4218 //=======================================================================
4220 void SMESH_MeshEditor_i::
4221 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4222 CORBA::Double Tolerance,
4223 SMESH::array_of_long_array_out GroupsOfNodes,
4224 CORBA::Boolean SeparateCornersAndMedium)
4225 throw (SALOME::SALOME_Exception)
4230 TIDSortedNodeSet nodes;
4231 prepareIdSource( theObject );
4232 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4234 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4236 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4238 << Tolerance << ", "
4239 << SeparateCornersAndMedium << " )";
4241 SMESH_CATCH( SMESH::throwCorbaException );
4244 //================================================================================
4246 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4247 * ExceptSubMeshOrGroups
4249 //================================================================================
4251 void SMESH_MeshEditor_i::
4252 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4253 CORBA::Double theTolerance,
4254 SMESH::array_of_long_array_out theGroupsOfNodes,
4255 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4256 CORBA::Boolean theSeparateCornersAndMedium)
4257 throw (SALOME::SALOME_Exception)
4262 TIDSortedNodeSet nodes;
4263 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4265 prepareIdSource( theObjects[i] );
4266 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4268 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4270 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4272 while ( nodeIt->more() )
4273 nodes.erase( cast2Node( nodeIt->next() ));
4275 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4277 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4278 << theObjects <<", "
4279 << theTolerance << ", "
4280 << theExceptSubMeshOrGroups << ", "
4281 << theSeparateCornersAndMedium << " )";
4283 SMESH_CATCH( SMESH::throwCorbaException );
4286 //=======================================================================
4287 //function : MergeNodes
4289 //=======================================================================
4291 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4292 const SMESH::ListOfIDSources& NodesToKeep,
4293 CORBA::Boolean AvoidMakingHoles)
4294 throw (SALOME::SALOME_Exception)
4299 SMESHDS_Mesh* aMesh = getMeshDS();
4301 TPythonDump aTPythonDump;
4302 aTPythonDump << this << ".MergeNodes([";
4304 TIDSortedNodeSet setOfNodesToKeep;
4305 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4307 prepareIdSource( NodesToKeep[i] );
4308 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4309 while ( nodeIt->more() )
4310 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4313 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4314 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4316 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4317 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4318 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4319 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4321 CORBA::Long index = aNodeGroup[ j ];
4322 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4324 if ( setOfNodesToKeep.count( node ))
4325 aListOfNodes.push_front( node );
4327 aListOfNodes.push_back( node );
4330 if ( aListOfNodes.size() < 2 )
4331 aListOfListOfNodes.pop_back();
4333 if ( i > 0 ) aTPythonDump << ", ";
4334 aTPythonDump << aNodeGroup;
4337 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4339 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4341 declareMeshModified( /*isReComputeSafe=*/false );
4343 SMESH_CATCH( SMESH::throwCorbaException );
4346 //=======================================================================
4347 //function : FindEqualElements
4349 //=======================================================================
4351 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4352 const SMESH::ListOfIDSources& theExceptObjects,
4353 SMESH::array_of_long_array_out theGroupsOfElementsID)
4354 throw (SALOME::SALOME_Exception)
4359 theGroupsOfElementsID = new SMESH::array_of_long_array;
4361 TIDSortedElemSet elems;
4362 bool hasOkObject = false;
4363 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4365 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4367 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4368 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4369 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4375 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4377 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4378 while ( elemIt->more() )
4379 elems.erase( elemIt->next() );
4382 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4383 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4385 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4387 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4388 aListOfListOfElementsID.begin();
4389 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4391 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4392 list<int>& listOfIDs = *arraysIt;
4393 aGroup.length( listOfIDs.size() );
4394 list<int>::iterator idIt = listOfIDs.begin();
4395 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4396 aGroup[ k ] = *idIt;
4399 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4400 << theObjects << ", "
4401 << theExceptObjects << " )";
4404 SMESH_CATCH( SMESH::throwCorbaException );
4407 //=======================================================================
4408 //function : MergeElements
4410 //=======================================================================
4412 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4413 const SMESH::ListOfIDSources& theElementsToKeep)
4414 throw (SALOME::SALOME_Exception)
4419 TPythonDump aTPythonDump;
4420 aTPythonDump << this << ".MergeElements( [";
4422 NCollection_Map< int > idsToKeep;
4423 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4425 if ( CORBA::is_nil( theElementsToKeep[i] ))
4427 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4428 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4430 SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs();
4431 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4432 idsToKeep.Add( elementsId[ j ]);
4435 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4437 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4439 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4440 aListOfListOfElementsID.push_back( list< int >() );
4441 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4442 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4444 CORBA::Long id = anElemsIDGroup[ j ];
4445 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4446 else aListOfElemsID.push_back( id );
4448 if ( aListOfElemsID.size() < 2 )
4449 aListOfListOfElementsID.pop_back();
4450 if ( i > 0 ) aTPythonDump << ", ";
4451 aTPythonDump << anElemsIDGroup;
4454 getEditor().MergeElements(aListOfListOfElementsID);
4456 declareMeshModified( /*isReComputeSafe=*/true );
4458 aTPythonDump << "], " << theElementsToKeep << " )";
4460 SMESH_CATCH( SMESH::throwCorbaException );
4463 //=======================================================================
4464 //function : MergeEqualElements
4466 //=======================================================================
4468 void SMESH_MeshEditor_i::MergeEqualElements()
4469 throw (SALOME::SALOME_Exception)
4474 getEditor().MergeEqualElements();
4476 declareMeshModified( /*isReComputeSafe=*/true );
4478 TPythonDump() << this << ".MergeEqualElements()";
4480 SMESH_CATCH( SMESH::throwCorbaException );
4483 //=============================================================================
4485 * Move the node to a given point
4487 //=============================================================================
4489 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4493 throw (SALOME::SALOME_Exception)
4496 initData(/*deleteSearchers=*/false);
4498 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4502 if ( theNodeSearcher )
4503 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4505 if ( myIsPreviewMode ) // make preview data
4507 // in a preview mesh, make edges linked to a node
4508 TPreviewMesh& tmpMesh = *getPreviewMesh();
4509 TIDSortedElemSet linkedNodes;
4510 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4511 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4512 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4513 for ( ; nIt != linkedNodes.end(); ++nIt )
4515 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4516 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4520 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4521 // fill preview data
4523 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4524 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4526 getMeshDS()->MoveNode(node, x, y, z);
4528 if ( !myIsPreviewMode )
4530 // Update Python script
4531 TPythonDump() << "isDone = " << this << ".MoveNode( "
4532 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4533 declareMeshModified( /*isReComputeSafe=*/false );
4536 SMESH_CATCH( SMESH::throwCorbaException );
4541 //================================================================================
4543 * \brief Return ID of node closest to a given point
4545 //================================================================================
4547 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4550 throw (SALOME::SALOME_Exception)
4553 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4555 if ( !theNodeSearcher ) {
4556 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4559 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4560 return node->GetID();
4562 SMESH_CATCH( SMESH::throwCorbaException );
4566 //================================================================================
4568 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4569 * move the node closest to the point to point's location and return ID of the node
4571 //================================================================================
4573 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4576 CORBA::Long theNodeID)
4577 throw (SALOME::SALOME_Exception)
4580 // We keep theNodeSearcher until any mesh modification:
4581 // 1) initData() deletes theNodeSearcher at any edition,
4582 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4584 initData(/*deleteSearchers=*/false);
4586 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4588 int nodeID = theNodeID;
4589 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4590 if ( !node ) // preview moving node
4592 if ( !theNodeSearcher ) {
4593 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4596 node = theNodeSearcher->FindClosestTo( p );
4599 nodeID = node->GetID();
4600 if ( myIsPreviewMode ) // make preview data
4602 // in a preview mesh, make edges linked to a node
4603 TPreviewMesh tmpMesh = *getPreviewMesh();
4604 TIDSortedElemSet linkedNodes;
4605 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4606 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4607 for ( ; nIt != linkedNodes.end(); ++nIt )
4609 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4610 tmpMesh.Copy( &edge );
4613 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4615 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4616 // fill preview data
4618 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4620 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4624 getMeshDS()->MoveNode(node, x, y, z);
4628 if ( !myIsPreviewMode )
4630 TPythonDump() << "nodeID = " << this
4631 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4632 << ", " << nodeID << " )";
4634 declareMeshModified( /*isReComputeSafe=*/false );
4639 SMESH_CATCH( SMESH::throwCorbaException );
4643 //=======================================================================
4645 * Return elements of given type where the given point is IN or ON.
4647 * 'ALL' type means elements of any type excluding nodes
4649 //=======================================================================
4651 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4654 SMESH::ElementType type)
4655 throw (SALOME::SALOME_Exception)
4658 SMESH::long_array_var res = new SMESH::long_array;
4659 vector< const SMDS_MeshElement* > foundElems;
4661 theSearchersDeleter.Set( myMesh );
4662 if ( !theElementSearcher ) {
4663 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4665 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4666 SMDSAbs_ElementType( type ),
4668 res->length( foundElems.size() );
4669 for ( size_t i = 0; i < foundElems.size(); ++i )
4670 res[i] = foundElems[i]->GetID();
4674 SMESH_CATCH( SMESH::throwCorbaException );
4678 //=======================================================================
4679 //function : FindAmongElementsByPoint
4680 //purpose : Searching among the given elements, return elements of given type
4681 // where the given point is IN or ON.
4682 // 'ALL' type means elements of any type excluding nodes
4683 //=======================================================================
4686 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4690 SMESH::ElementType type)
4691 throw (SALOME::SALOME_Exception)
4694 SMESH::long_array_var res = new SMESH::long_array;
4696 prepareIdSource( elementIDs );
4697 if ( type != SMESH::NODE )
4699 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4700 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4701 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4702 type != types[0] ) // but search of elements of dim > 0
4706 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4707 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4708 if ( mesh_i != myMesh_i )
4710 SMESH::SMESH_MeshEditor_var editor=
4711 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4712 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4715 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4716 return FindElementsByPoint( x,y,z, type );
4718 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4720 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4721 if ( !theElementSearcher )
4723 // create a searcher from elementIDs
4724 SMDS_ElemIteratorPtr elemIt;
4725 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4727 //prepareIdSource( elementIDs );
4728 elemIt = myMesh_i->GetElements( elementIDs, type );
4732 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4735 vector< const SMDS_MeshElement* > foundElems;
4737 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4738 SMDSAbs_ElementType( type ),
4740 res->length( foundElems.size() );
4741 for ( size_t i = 0; i < foundElems.size(); ++i )
4742 res[i] = foundElems[i]->GetID();
4746 SMESH_CATCH( SMESH::throwCorbaException );
4750 //=======================================================================
4751 //function : ProjectPoint
4752 //purpose : Project a point to a mesh object.
4753 // Return ID of an element of given type where the given point is projected
4754 // and coordinates of the projection point.
4755 // In the case if nothing found, return -1 and []
4756 //=======================================================================
4758 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4761 SMESH::ElementType type,
4762 SMESH::SMESH_IDSource_ptr meshObject,
4763 SMESH::double_array_out projecton)
4764 throw (SALOME::SALOME_Exception)
4766 if ( CORBA::is_nil( meshObject ))
4767 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4771 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4772 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4773 if ( mesh_i != myMesh_i )
4775 SMESH::SMESH_MeshEditor_var editor=
4776 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4777 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4781 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4782 if ( !theElementSearcher )
4784 // create a searcher from meshObject
4786 SMDS_ElemIteratorPtr elemIt;
4787 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4789 prepareIdSource( meshObject );
4790 elemIt = myMesh_i->GetElements( meshObject, type );
4794 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4797 const SMDS_MeshElement* elem = 0;
4798 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4799 SMDSAbs_ElementType( type ),
4802 projecton = new SMESH::double_array();
4803 if ( elem && !elem->IsNull() )
4805 projecton->length( 3 );
4806 projecton[0] = pProj.X();
4807 projecton[1] = pProj.Y();
4808 projecton[2] = pProj.Z();
4809 return elem->GetID();
4812 SMESH_CATCH( SMESH::throwCorbaException );
4816 //=======================================================================
4817 //function : GetPointState
4818 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4819 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4820 //=======================================================================
4822 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4825 throw (SALOME::SALOME_Exception)
4828 theSearchersDeleter.Set( myMesh );
4829 if ( !theElementSearcher ) {
4830 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4832 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4834 SMESH_CATCH( SMESH::throwCorbaException );
4838 //=======================================================================
4839 //function : IsManifold
4840 //purpose : Check if a 2D mesh is manifold
4841 //=======================================================================
4843 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4844 throw (SALOME::SALOME_Exception)
4846 bool isManifold = true;
4849 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4850 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4852 /*closedOnly=*/true,
4854 SMESH_CATCH( SMESH::throwCorbaException );
4859 //=======================================================================
4860 //function : IsCoherentOrientation2D
4861 //purpose : Check if orientation of 2D elements is coherent
4862 //=======================================================================
4864 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4865 throw (SALOME::SALOME_Exception)
4867 bool isGoodOri = true;
4870 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4871 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4873 /*closedOnly=*/true,
4876 SMESH_CATCH( SMESH::throwCorbaException );
4881 //=======================================================================
4882 //function : Get1DBranches
4883 //purpose : Partition given 1D elements into groups of contiguous edges.
4884 // A node where number of meeting edges != 2 is a group end.
4885 // An optional startNode is used to orient groups it belongs to.
4886 //return : a list of edge groups and a list of corresponding node groups.
4887 // If a group is closed, the first and last nodes of the group are same.
4888 //=======================================================================
4890 SMESH::array_of_long_array*
4891 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4892 CORBA::Long theStartNode,
4893 SMESH::array_of_long_array_out theNodeGroups )
4894 throw (SALOME::SALOME_Exception)
4896 if ( CORBA::is_nil( theEdges ))
4897 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4899 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4900 theNodeGroups = new SMESH::array_of_long_array;
4904 prepareIdSource( theEdges );
4906 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4907 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4908 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4911 getMeshDS()->FindNode( theStartNode ));
4913 edgeGroupArray->length( edgeBranches.size() );
4914 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4916 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4917 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4918 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4921 theNodeGroups->length( nodeBranches.size() );
4922 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4924 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4925 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4926 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4929 SMESH_CATCH( SMESH::throwCorbaException );
4931 return edgeGroupArray._retn();
4934 //=======================================================================
4935 //function : FindSharpEdges
4936 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4937 //=======================================================================
4939 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4940 CORBA::Boolean theAddExisting)
4941 throw (SALOME::SALOME_Exception)
4943 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4948 std::vector< SMESH_MeshAlgos::Edge > edges =
4949 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4951 if ( myIsPreviewMode ) // fill a preview mesh with edges
4953 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4954 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4955 for ( size_t i = 0; i < edges.size(); ++i )
4957 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4958 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4959 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4960 if ( edges[i]._medium )
4962 xyz1.Set( edges[i]._medium );
4963 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4964 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4968 mesh->GetMeshDS()->AddEdge( n1, n2 );
4974 resultEdges->length( edges.size() );
4975 for ( size_t i = 0; i < edges.size(); ++i )
4977 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4978 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4979 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4982 SMESH_CATCH( SMESH::throwCorbaException );
4983 return resultEdges._retn();
4986 //=======================================================================
4987 //function : FindFreeBorders
4988 //purpose : Returns all or only closed FreeBorder's.
4989 //=======================================================================
4991 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4992 throw (SALOME::SALOME_Exception)
4994 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4997 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4998 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
5000 resBorders->length( foundFreeBordes.size() );
5001 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
5003 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
5004 SMESH::FreeBorder& bordOut = resBorders[i];
5005 bordOut.nodeIDs.length( bordNodes.size() );
5006 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
5007 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
5010 SMESH_CATCH( SMESH::throwCorbaException );
5012 return resBorders._retn();
5015 //=======================================================================
5016 //function : FillHole
5017 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
5018 //=======================================================================
5020 SMESH::SMESH_Group_ptr
5021 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
5022 const char* theGroupName)
5023 throw (SALOME::SALOME_Exception)
5027 if ( theHole.nodeIDs.length() < 4 )
5028 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
5029 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
5030 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
5031 "First and last nodes must be same", SALOME::BAD_PARAM);
5033 SMESH_MeshAlgos::TFreeBorder bordNodes;
5034 bordNodes.resize( theHole.nodeIDs.length() );
5035 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
5037 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
5038 if ( !bordNodes[ iN ] )
5039 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
5040 << " does not exist", SALOME::BAD_PARAM);
5045 // prepare a preview mesh
5046 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5047 SMDS_Mesh* meshDS = getMeshDS();
5048 if ( myIsPreviewMode )
5050 // copy faces sharing nodes of theHole
5051 TIDSortedElemSet holeFaces;
5052 previewMesh = getPreviewMesh( SMDSAbs_Face );
5053 for ( size_t i = 0; i < bordNodes.size(); ++i )
5055 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5056 while ( fIt->more() )
5058 const SMDS_MeshElement* face = fIt->next();
5059 if ( holeFaces.insert( face ).second )
5060 previewMesh->Copy( face );
5062 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5063 ASSERT( bordNodes[i] );
5065 meshDS = previewMesh->GetMeshDS();
5069 std::vector<const SMDS_MeshElement*> newFaces;
5070 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5072 if ( myIsPreviewMode )
5075 previewMesh->Clear();
5076 for ( size_t i = 0; i < newFaces.size(); ++i )
5077 previewMesh->Copy( newFaces[i] );
5081 // return new faces via a group
5082 SMESH::SMESH_Group_var group;
5083 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5085 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5086 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5088 SMESH::SMESH_GroupBase_var g = groups[ i ];
5089 if ( g->GetType() != SMESH::FACE ) continue;
5090 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5091 if ( standalone->_is_nil() ) continue;
5092 CORBA::String_var name = g->GetName();
5093 if ( strcmp( theGroupName, name.in() ) == 0 )
5099 if ( group->_is_nil() )
5100 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5102 if ( !group->_is_nil() )
5104 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5105 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5106 for ( size_t i = 0; i < newFaces.size(); ++i )
5107 grpDS->Add( newFaces[ i ]);
5112 getEditor().ClearLastCreated();
5113 SMESH_SequenceOfElemPtr& aSeq =
5114 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5115 aSeq.swap( newFaces );
5118 if ( group->_is_nil() ) pyDump << "_group = ";
5119 else pyDump << group << " = ";
5120 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5122 return group._retn();
5125 SMESH_CATCH( SMESH::throwCorbaException );
5127 return SMESH::SMESH_Group::_nil();
5130 //=======================================================================
5131 //function : convError
5133 //=======================================================================
5135 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5137 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5141 RETCASE( SEW_BORDER1_NOT_FOUND );
5142 RETCASE( SEW_BORDER2_NOT_FOUND );
5143 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5144 RETCASE( SEW_BAD_SIDE_NODES );
5145 RETCASE( SEW_VOLUMES_TO_SPLIT );
5146 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5147 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5148 RETCASE( SEW_BAD_SIDE1_NODES );
5149 RETCASE( SEW_BAD_SIDE2_NODES );
5150 RETCASE( SEW_INTERNAL_ERROR );
5152 return SMESH::SMESH_MeshEditor::SEW_OK;
5155 //=======================================================================
5157 * Returns groups of FreeBorder's coincident within the given tolerance.
5158 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5159 * to free borders being compared is used.
5161 //=======================================================================
5163 SMESH::CoincidentFreeBorders*
5164 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5166 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5170 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5171 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5173 // copy free borders
5174 aCFB->borders.length( cfb._borders.size() );
5175 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5177 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5178 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5179 aBRD.nodeIDs.length( nodes.size() );
5180 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5181 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5184 // copy coincident parts
5185 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5186 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5188 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5189 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5190 aGRP.length( grp.size() );
5191 for ( size_t iP = 0; iP < grp.size(); ++iP )
5193 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5194 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5195 aPART.border = part._border;
5196 aPART.node1 = part._node1;
5197 aPART.node2 = part._node2;
5198 aPART.nodeLast = part._nodeLast;
5201 SMESH_CATCH( SMESH::doNothing );
5203 TPythonDump() << "CoincidentFreeBorders = "
5204 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5206 return aCFB._retn();
5209 //=======================================================================
5211 * Sew FreeBorder's of each group
5213 //=======================================================================
5215 CORBA::Short SMESH_MeshEditor_i::
5216 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5217 CORBA::Boolean createPolygons,
5218 CORBA::Boolean createPolyhedra)
5219 throw (SALOME::SALOME_Exception)
5221 CORBA::Short nbSewed = 0;
5223 SMESH_MeshAlgos::TFreeBorderVec groups;
5224 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5226 // check the input and collect nodes
5227 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5229 borderNodes.clear();
5230 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5231 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5233 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5234 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5235 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5237 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5239 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5240 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5241 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5242 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5243 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5244 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5246 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5247 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5248 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5249 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5251 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5253 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5255 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5257 borderNodes.push_back( n1 );
5258 borderNodes.push_back( n2 );
5259 borderNodes.push_back( n3 );
5261 groups.push_back( borderNodes );
5264 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5265 // to get nodes that replace other nodes during merge we create 0D elements
5266 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5269 vector< const SMDS_MeshElement* > tmp0Delems;
5270 for ( size_t i = 0; i < groups.size(); ++i )
5272 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5273 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5275 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5277 tmp0Delems.push_back( it0D->next() );
5279 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5283 // cout << endl << "INIT" << endl;
5284 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5286 // cout << i << " ";
5287 // if ( i % 3 == 0 ) cout << "^ ";
5288 // tmp0Delems[i]->GetNode(0)->Print( cout );
5293 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5295 for ( size_t i = 0; i < groups.size(); ++i )
5297 bool isBordToBord = true;
5298 bool groupSewed = false;
5299 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5300 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5302 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5303 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5304 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5306 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5307 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5308 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5310 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5313 // TIDSortedElemSet emptySet, avoidSet;
5314 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5316 // cout << "WRONG 2nd 1" << endl;
5317 // n0->Print( cout );
5318 // n1->Print( cout );
5320 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5322 // cout << "WRONG 2nd 2" << endl;
5323 // n3->Print( cout );
5324 // n4->Print( cout );
5327 if ( !isBordToBord )
5329 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5330 n2 = 0; // and n2 is not used
5332 // 1st border moves to 2nd
5333 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5335 /*2ndIsFreeBorder=*/ isBordToBord,
5336 createPolygons, createPolyhedra);
5337 groupSewed = ( res == ok );
5339 isBordToBord = false;
5340 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5341 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5343 // cout << t << " ";
5344 // if ( t % 3 == 0 ) cout << "^ ";
5345 // tmp0Delems[t]->GetNode(0)->Print( cout );
5348 i0D += nodes.size();
5349 nbSewed += groupSewed;
5352 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5353 << freeBorders << ", "
5354 << createPolygons << ", "
5355 << createPolyhedra << " )";
5357 SMESH_CATCH( SMESH::doNothing );
5359 declareMeshModified( /*isReComputeSafe=*/false );
5361 // remove tmp 0D elements
5363 set< const SMDS_MeshElement* > removed0D;
5364 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5366 if ( removed0D.insert( tmp0Delems[i] ).second )
5367 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5369 SMESH_CATCH( SMESH::throwCorbaException );
5374 //=======================================================================
5375 //function : SewFreeBorders
5377 //=======================================================================
5379 SMESH::SMESH_MeshEditor::Sew_Error
5380 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5381 CORBA::Long SecondNodeID1,
5382 CORBA::Long LastNodeID1,
5383 CORBA::Long FirstNodeID2,
5384 CORBA::Long SecondNodeID2,
5385 CORBA::Long LastNodeID2,
5386 CORBA::Boolean CreatePolygons,
5387 CORBA::Boolean CreatePolyedrs)
5388 throw (SALOME::SALOME_Exception)
5393 SMESHDS_Mesh* aMesh = getMeshDS();
5395 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5396 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5397 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5398 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5399 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5400 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5402 if (!aBorderFirstNode ||
5403 !aBorderSecondNode||
5405 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5406 if (!aSide2FirstNode ||
5407 !aSide2SecondNode ||
5409 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5411 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5412 << FirstNodeID1 << ", "
5413 << SecondNodeID1 << ", "
5414 << LastNodeID1 << ", "
5415 << FirstNodeID2 << ", "
5416 << SecondNodeID2 << ", "
5417 << LastNodeID2 << ", "
5418 << CreatePolygons<< ", "
5419 << CreatePolyedrs<< " )";
5421 SMESH::SMESH_MeshEditor::Sew_Error error =
5422 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5433 declareMeshModified( /*isReComputeSafe=*/false );
5436 SMESH_CATCH( SMESH::throwCorbaException );
5437 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5441 //=======================================================================
5442 //function : SewConformFreeBorders
5444 //=======================================================================
5446 SMESH::SMESH_MeshEditor::Sew_Error
5447 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5448 CORBA::Long SecondNodeID1,
5449 CORBA::Long LastNodeID1,
5450 CORBA::Long FirstNodeID2,
5451 CORBA::Long SecondNodeID2)
5452 throw (SALOME::SALOME_Exception)
5457 SMESHDS_Mesh* aMesh = getMeshDS();
5459 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5460 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5461 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5462 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5463 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5464 const SMDS_MeshNode* aSide2ThirdNode = 0;
5466 if (!aBorderFirstNode ||
5467 !aBorderSecondNode||
5469 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5470 if (!aSide2FirstNode ||
5472 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5474 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5475 << FirstNodeID1 << ", "
5476 << SecondNodeID1 << ", "
5477 << LastNodeID1 << ", "
5478 << FirstNodeID2 << ", "
5479 << SecondNodeID2 << " )";
5481 SMESH::SMESH_MeshEditor::Sew_Error error =
5482 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5491 declareMeshModified( /*isReComputeSafe=*/false );
5494 SMESH_CATCH( SMESH::throwCorbaException );
5495 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5499 //=======================================================================
5500 //function : SewBorderToSide
5502 //=======================================================================
5504 SMESH::SMESH_MeshEditor::Sew_Error
5505 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5506 CORBA::Long SecondNodeIDOnFreeBorder,
5507 CORBA::Long LastNodeIDOnFreeBorder,
5508 CORBA::Long FirstNodeIDOnSide,
5509 CORBA::Long LastNodeIDOnSide,
5510 CORBA::Boolean CreatePolygons,
5511 CORBA::Boolean CreatePolyedrs)
5512 throw (SALOME::SALOME_Exception)
5517 SMESHDS_Mesh* aMesh = getMeshDS();
5519 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5520 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5521 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5522 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5523 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5524 const SMDS_MeshNode* aSide2ThirdNode = 0;
5526 if (!aBorderFirstNode ||
5527 !aBorderSecondNode||
5529 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5530 if (!aSide2FirstNode ||
5532 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5534 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5535 << FirstNodeIDOnFreeBorder << ", "
5536 << SecondNodeIDOnFreeBorder << ", "
5537 << LastNodeIDOnFreeBorder << ", "
5538 << FirstNodeIDOnSide << ", "
5539 << LastNodeIDOnSide << ", "
5540 << CreatePolygons << ", "
5541 << CreatePolyedrs << ") ";
5543 SMESH::SMESH_MeshEditor::Sew_Error error =
5544 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5554 declareMeshModified( /*isReComputeSafe=*/false );
5557 SMESH_CATCH( SMESH::throwCorbaException );
5558 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5562 //=======================================================================
5563 //function : SewSideElements
5565 //=======================================================================
5567 SMESH::SMESH_MeshEditor::Sew_Error
5568 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5569 const SMESH::long_array& IDsOfSide2Elements,
5570 CORBA::Long NodeID1OfSide1ToMerge,
5571 CORBA::Long NodeID1OfSide2ToMerge,
5572 CORBA::Long NodeID2OfSide1ToMerge,
5573 CORBA::Long NodeID2OfSide2ToMerge)
5574 throw (SALOME::SALOME_Exception)
5579 SMESHDS_Mesh* aMesh = getMeshDS();
5581 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5582 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5583 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5584 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5586 if (!aFirstNode1ToMerge ||
5587 !aFirstNode2ToMerge )
5588 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5589 if (!aSecondNode1ToMerge||
5590 !aSecondNode2ToMerge)
5591 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5593 TIDSortedElemSet aSide1Elems, aSide2Elems;
5594 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5595 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5597 TPythonDump() << "error = " << this << ".SewSideElements( "
5598 << IDsOfSide1Elements << ", "
5599 << IDsOfSide2Elements << ", "
5600 << NodeID1OfSide1ToMerge << ", "
5601 << NodeID1OfSide2ToMerge << ", "
5602 << NodeID2OfSide1ToMerge << ", "
5603 << NodeID2OfSide2ToMerge << ")";
5605 SMESH::SMESH_MeshEditor::Sew_Error error =
5606 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5609 aSecondNode1ToMerge,
5610 aSecondNode2ToMerge));
5612 declareMeshModified( /*isReComputeSafe=*/false );
5615 SMESH_CATCH( SMESH::throwCorbaException );
5616 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5619 //================================================================================
5621 * \brief Set new nodes for given element
5622 * \param ide - element id
5623 * \param newIDs - new node ids
5624 * \retval CORBA::Boolean - true if result is OK
5626 //================================================================================
5628 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5629 const SMESH::long_array& newIDs)
5630 throw (SALOME::SALOME_Exception)
5635 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5636 if ( !elem ) return false;
5638 int nbn = newIDs.length();
5639 vector<const SMDS_MeshNode*> aNodes(nbn);
5640 for ( int i = 0; i < nbn; i++ ) {
5641 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5644 aNodes[ i ] = aNode;
5646 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5647 << ide << ", " << newIDs << " )";
5649 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5651 declareMeshModified( /*isReComputeSafe=*/ !res );
5655 SMESH_CATCH( SMESH::throwCorbaException );
5659 //=======================================================================
5661 * \brief Makes a part of the mesh quadratic or bi-quadratic
5663 //=======================================================================
5665 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5666 CORBA::Boolean theToBiQuad,
5667 SMESH::SMESH_IDSource_ptr theObject)
5668 throw (SALOME::SALOME_Exception)
5673 TIDSortedElemSet elems;
5675 if ( !( elemsOK = CORBA::is_nil( theObject )))
5677 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5678 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5682 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5683 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5685 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5686 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5688 declareMeshModified( /*isReComputeSafe=*/false );
5691 SMESH_CATCH( SMESH::throwCorbaException );
5694 //=======================================================================
5695 //function : ConvertFromQuadratic
5697 //=======================================================================
5699 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5700 throw (SALOME::SALOME_Exception)
5705 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5706 TPythonDump() << this << ".ConvertFromQuadratic()";
5707 declareMeshModified( /*isReComputeSafe=*/!isDone );
5710 SMESH_CATCH( SMESH::throwCorbaException );
5714 //=======================================================================
5715 //function : ConvertToQuadratic
5717 //=======================================================================
5719 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5720 throw (SALOME::SALOME_Exception)
5722 convertToQuadratic( theForce3d, false );
5723 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5726 //================================================================================
5728 * \brief Makes a part of the mesh quadratic
5730 //================================================================================
5732 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5733 SMESH::SMESH_IDSource_ptr theObject)
5734 throw (SALOME::SALOME_Exception)
5736 convertToQuadratic( theForce3d, false, theObject );
5737 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5740 //================================================================================
5742 * \brief Makes a part of the mesh bi-quadratic
5744 //================================================================================
5746 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5747 SMESH::SMESH_IDSource_ptr theObject)
5748 throw (SALOME::SALOME_Exception)
5750 convertToQuadratic( theForce3d, true, theObject );
5751 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5754 //================================================================================
5756 * \brief Makes a part of the mesh linear
5758 //================================================================================
5760 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5761 throw (SALOME::SALOME_Exception)
5768 TIDSortedElemSet elems;
5769 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5771 if ( elems.empty() )
5773 ConvertFromQuadratic();
5775 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5777 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5781 getEditor().ConvertFromQuadratic(elems);
5784 declareMeshModified( /*isReComputeSafe=*/false );
5786 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5788 SMESH_CATCH( SMESH::throwCorbaException );
5791 //=======================================================================
5792 //function : makeMesh
5793 //purpose : create a named imported mesh
5794 //=======================================================================
5796 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5798 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5799 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5800 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5801 gen->SetName( meshSO, theMeshName, "Mesh" );
5802 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5804 return mesh._retn();
5807 //=======================================================================
5808 //function : dumpGroupsList
5810 //=======================================================================
5812 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5813 const SMESH::ListOfGroups * theGroupList)
5815 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5816 if ( isDumpGroupList )
5817 theDumpPython << theGroupList << " = ";
5820 //================================================================================
5822 \brief Generates the unique group name.
5823 \param thePrefix name prefix
5826 //================================================================================
5828 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5830 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5831 set<std::string> groupNames;
5833 // Get existing group names
5834 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5835 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5836 if (CORBA::is_nil(aGroup))
5839 CORBA::String_var name = aGroup->GetName();
5840 groupNames.insert( name.in() );
5844 std::string name = thePrefix;
5847 while (!groupNames.insert(name).second)
5848 name = SMESH_Comment( thePrefix ) << "_" << index++;
5853 //================================================================================
5855 * \brief Prepare SMESH_IDSource for work
5857 //================================================================================
5859 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5861 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5863 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5864 filter->SetMesh( mesh );
5867 //================================================================================
5869 * \brief Retrieve elements of given type from SMESH_IDSource
5871 //================================================================================
5873 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5874 const SMESHDS_Mesh* theMeshDS,
5875 TIDSortedElemSet& theElemSet,
5876 const SMDSAbs_ElementType theType,
5877 const bool emptyIfIsMesh,
5878 IDSource_Error* error)
5881 if ( error ) *error = IDSource_OK;
5883 if ( CORBA::is_nil( theIDSource ))
5885 if ( error ) *error = IDSource_INVALID;
5888 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5890 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5891 *error = IDSource_EMPTY;
5894 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5896 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5897 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5898 if ( mesh_i && mesh_i != myMesh_i )
5901 *error = IDSource_INVALID;
5905 prepareIdSource( theIDSource );
5906 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5907 if ( anIDs->length() == 0 )
5909 if ( error ) *error = IDSource_EMPTY;
5912 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5913 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5915 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5917 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5921 if ( error ) *error = IDSource_INVALID;
5927 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5928 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5930 if ( error ) *error = IDSource_INVALID;
5937 //================================================================================
5939 * \brief Duplicates given elements, i.e. creates new elements based on the
5940 * same nodes as the given ones.
5941 * \param theElements - container of elements to duplicate.
5942 * \param theGroupName - a name of group to contain the generated elements.
5943 * If a group with such a name already exists, the new elements
5944 * are added to the existing group, else a new group is created.
5945 * If \a theGroupName is empty, new elements are not added
5947 * \return a group where the new elements are added. NULL if theGroupName == "".
5950 //================================================================================
5952 SMESH::SMESH_Group_ptr
5953 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5954 const char* theGroupName)
5955 throw (SALOME::SALOME_Exception)
5957 SMESH::SMESH_Group_var newGroup;
5964 TIDSortedElemSet elems;
5965 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5967 getEditor().DoubleElements( elems );
5969 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5972 SMESH::ElementType type =
5973 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5974 // find existing group
5975 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5976 for ( size_t i = 0; i < groups->length(); ++i )
5977 if ( groups[i]->GetType() == type )
5979 CORBA::String_var name = groups[i]->GetName();
5980 if ( strcmp( name, theGroupName ) == 0 ) {
5981 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5985 // create a new group
5986 if ( newGroup->_is_nil() )
5987 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5989 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5991 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5992 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5993 for ( size_t i = 0; i < aSeq.size(); i++ )
5994 groupDS->SMDSGroup().Add( aSeq[i] );
5999 if ( !newGroup->_is_nil() )
6000 pyDump << newGroup << " = ";
6001 pyDump << this << ".DoubleElements( "
6002 << theElements << ", " << "'" << theGroupName <<"')";
6004 SMESH_CATCH( SMESH::throwCorbaException );
6006 return newGroup._retn();
6009 //================================================================================
6011 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6012 \param theNodes - identifiers of nodes to be doubled
6013 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
6014 nodes. If list of element identifiers is empty then nodes are doubled but
6015 they not assigned to elements
6016 \return TRUE if operation has been completed successfully, FALSE otherwise
6017 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6019 //================================================================================
6021 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
6022 const SMESH::long_array& theModifiedElems )
6023 throw (SALOME::SALOME_Exception)
6028 list< int > aListOfNodes;
6030 for ( i = 0, n = theNodes.length(); i < n; i++ )
6031 aListOfNodes.push_back( theNodes[ i ] );
6033 list< int > aListOfElems;
6034 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6035 aListOfElems.push_back( theModifiedElems[ i ] );
6037 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6039 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6041 // Update Python script
6042 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6046 SMESH_CATCH( SMESH::throwCorbaException );
6050 //================================================================================
6052 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6053 This method provided for convenience works as DoubleNodes() described above.
6054 \param theNodeId - identifier of node to be doubled.
6055 \param theModifiedElems - identifiers of elements to be updated.
6056 \return TRUE if operation has been completed successfully, FALSE otherwise
6057 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6059 //================================================================================
6061 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
6062 const SMESH::long_array& theModifiedElems )
6063 throw (SALOME::SALOME_Exception)
6066 SMESH::long_array_var aNodes = new SMESH::long_array;
6067 aNodes->length( 1 );
6068 aNodes[ 0 ] = theNodeId;
6070 TPythonDump pyDump; // suppress dump by the next line
6072 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6074 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6078 SMESH_CATCH( SMESH::throwCorbaException );
6082 //================================================================================
6084 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6085 This method provided for convenience works as DoubleNodes() described above.
6086 \param theNodes - group of nodes to be doubled.
6087 \param theModifiedElems - group of elements to be updated.
6088 \return TRUE if operation has been completed successfully, FALSE otherwise
6089 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6091 //================================================================================
6093 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6094 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6095 throw (SALOME::SALOME_Exception)
6098 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6101 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6102 SMESH::long_array_var aModifiedElems;
6103 if ( !CORBA::is_nil( theModifiedElems ) )
6104 aModifiedElems = theModifiedElems->GetListOfID();
6106 aModifiedElems = new SMESH::long_array;
6108 TPythonDump pyDump; // suppress dump by the next line
6110 bool done = DoubleNodes( aNodes, aModifiedElems );
6112 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6116 SMESH_CATCH( SMESH::throwCorbaException );
6120 //================================================================================
6122 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6123 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6124 * \param theNodes - group of nodes to be doubled.
6125 * \param theModifiedElems - group of elements to be updated.
6126 * \return a new group with newly created nodes
6127 * \sa DoubleNodeGroup()
6129 //================================================================================
6131 SMESH::SMESH_Group_ptr
6132 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6133 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6134 throw (SALOME::SALOME_Exception)
6137 SMESH::SMESH_Group_var aNewGroup;
6139 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6140 return aNewGroup._retn();
6143 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6144 SMESH::long_array_var aModifiedElems;
6145 if ( !CORBA::is_nil( theModifiedElems ) )
6146 aModifiedElems = theModifiedElems->GetListOfID();
6148 aModifiedElems = new SMESH::long_array;
6149 aModifiedElems->length( 0 );
6152 TPythonDump pyDump; // suppress dump by the next line
6154 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6157 // Create group with newly created nodes
6158 SMESH::long_array_var anIds = GetLastCreatedNodes();
6159 if (anIds->length() > 0) {
6160 std::string anUnindexedName (theNodes->GetName());
6161 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6162 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6163 aNewGroup->Add(anIds);
6164 pyDump << aNewGroup << " = ";
6168 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6169 << theModifiedElems << " )";
6171 return aNewGroup._retn();
6173 SMESH_CATCH( SMESH::throwCorbaException );
6177 //================================================================================
6179 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6180 This method provided for convenience works as DoubleNodes() described above.
6181 \param theNodes - list of groups of nodes to be doubled
6182 \param theModifiedElems - list of groups of elements to be updated.
6183 \return TRUE if operation has been completed successfully, FALSE otherwise
6184 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6186 //================================================================================
6188 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6189 const SMESH::ListOfGroups& theModifiedElems )
6190 throw (SALOME::SALOME_Exception)
6195 std::list< int > aNodes;
6197 for ( i = 0, n = theNodes.length(); i < n; i++ )
6199 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6200 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6202 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6203 for ( j = 0, m = aCurr->length(); j < m; j++ )
6204 aNodes.push_back( aCurr[ j ] );
6208 std::list< int > anElems;
6209 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6211 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6212 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6214 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6215 for ( j = 0, m = aCurr->length(); j < m; j++ )
6216 anElems.push_back( aCurr[ j ] );
6220 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6222 declareMeshModified( /*isReComputeSafe=*/false );
6224 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6228 SMESH_CATCH( SMESH::throwCorbaException );
6232 //================================================================================
6234 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6235 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6236 * \param theNodes - group of nodes to be doubled.
6237 * \param theModifiedElems - group of elements to be updated.
6238 * \return a new group with newly created nodes
6239 * \sa DoubleNodeGroups()
6241 //================================================================================
6243 SMESH::SMESH_Group_ptr
6244 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6245 const SMESH::ListOfGroups& theModifiedElems )
6246 throw (SALOME::SALOME_Exception)
6248 SMESH::SMESH_Group_var aNewGroup;
6250 TPythonDump pyDump; // suppress dump by the next line
6252 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6256 // Create group with newly created nodes
6257 SMESH::long_array_var anIds = GetLastCreatedNodes();
6258 if (anIds->length() > 0) {
6259 std::string anUnindexedName (theNodes[0]->GetName());
6260 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6261 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6262 aNewGroup->Add(anIds);
6263 pyDump << aNewGroup << " = ";
6267 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6268 << theModifiedElems << " )";
6270 return aNewGroup._retn();
6274 //================================================================================
6276 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6277 \param theElems - the list of elements (edges or faces) to be replicated
6278 The nodes for duplication could be found from these elements
6279 \param theNodesNot - list of nodes to NOT replicate
6280 \param theAffectedElems - the list of elements (cells and edges) to which the
6281 replicated nodes should be associated to.
6282 \return TRUE if operation has been completed successfully, FALSE otherwise
6283 \sa DoubleNodeGroup(), DoubleNodeGroups()
6285 //================================================================================
6287 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6288 const SMESH::long_array& theNodesNot,
6289 const SMESH::long_array& theAffectedElems )
6290 throw (SALOME::SALOME_Exception)
6295 SMESHDS_Mesh* aMeshDS = getMeshDS();
6296 TIDSortedElemSet anElems, aNodes, anAffected;
6297 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6298 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6299 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6301 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6303 // Update Python script
6304 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6305 << theNodesNot << ", " << theAffectedElems << " )";
6307 declareMeshModified( /*isReComputeSafe=*/false );
6310 SMESH_CATCH( SMESH::throwCorbaException );
6314 //================================================================================
6316 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6317 \param theElems - the list of elements (edges or faces) to be replicated
6318 The nodes for duplication could be found from these elements
6319 \param theNodesNot - list of nodes to NOT replicate
6320 \param theShape - shape to detect affected elements (element which geometric center
6321 located on or inside shape).
6322 The replicated nodes should be associated to affected elements.
6323 \return TRUE if operation has been completed successfully, FALSE otherwise
6324 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6326 //================================================================================
6328 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6329 const SMESH::long_array& theNodesNot,
6330 GEOM::GEOM_Object_ptr theShape )
6331 throw (SALOME::SALOME_Exception)
6337 SMESHDS_Mesh* aMeshDS = getMeshDS();
6338 TIDSortedElemSet anElems, aNodes;
6339 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6340 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6342 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6343 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6345 // Update Python script
6346 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6347 << theNodesNot << ", " << theShape << " )";
6349 declareMeshModified( /*isReComputeSafe=*/false );
6352 SMESH_CATCH( SMESH::throwCorbaException );
6356 //================================================================================
6358 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6359 \param theElems - group of of elements (edges or faces) to be replicated
6360 \param theNodesNot - group of nodes not to replicated
6361 \param theAffectedElems - group of elements to which the replicated nodes
6362 should be associated to.
6363 \return TRUE if operation has been completed successfully, FALSE otherwise
6364 \sa DoubleNodes(), DoubleNodeGroups()
6366 //================================================================================
6369 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6370 SMESH::SMESH_GroupBase_ptr theNodesNot,
6371 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6372 throw (SALOME::SALOME_Exception)
6375 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6381 SMESHDS_Mesh* aMeshDS = getMeshDS();
6382 TIDSortedElemSet anElems, aNodes, anAffected;
6383 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6384 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6385 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6387 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6389 // Update Python script
6390 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6391 << theNodesNot << ", " << theAffectedElems << " )";
6393 declareMeshModified( /*isReComputeSafe=*/false );
6396 SMESH_CATCH( SMESH::throwCorbaException );
6400 //================================================================================
6402 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6403 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6404 * \param theElems - group of of elements (edges or faces) to be replicated
6405 * \param theNodesNot - group of nodes not to replicated
6406 * \param theAffectedElems - group of elements to which the replicated nodes
6407 * should be associated to.
6408 * \return a new group with newly created elements
6409 * \sa DoubleNodeElemGroup()
6411 //================================================================================
6413 SMESH::SMESH_Group_ptr
6414 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6415 SMESH::SMESH_GroupBase_ptr theNodesNot,
6416 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6417 throw (SALOME::SALOME_Exception)
6420 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6424 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6425 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6427 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6429 << theNodesNot << ", "
6430 << theAffectedElems << " )";
6432 return elemGroup._retn();
6435 //================================================================================
6437 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6438 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6439 * \param theElems - group of of elements (edges or faces) to be replicated
6440 * \param theNodesNot - group of nodes not to replicated
6441 * \param theAffectedElems - group of elements to which the replicated nodes
6442 * should be associated to.
6443 * \return a new group with newly created elements
6444 * \sa DoubleNodeElemGroup()
6446 //================================================================================
6448 SMESH::ListOfGroups*
6449 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6450 SMESH::SMESH_GroupBase_ptr theNodesNot,
6451 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6452 CORBA::Boolean theElemGroupNeeded,
6453 CORBA::Boolean theNodeGroupNeeded)
6454 throw (SALOME::SALOME_Exception)
6457 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6458 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6459 aTwoGroups->length( 2 );
6461 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6462 return aTwoGroups._retn();
6467 SMESHDS_Mesh* aMeshDS = getMeshDS();
6468 TIDSortedElemSet anElems, aNodes, anAffected;
6469 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6470 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6471 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6474 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6476 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6482 // Create group with newly created elements
6483 CORBA::String_var elemGroupName = theElems->GetName();
6484 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6485 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6487 SMESH::long_array_var anIds = GetLastCreatedElems();
6488 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6489 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6490 aNewElemGroup->Add(anIds);
6492 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6494 SMESH::long_array_var anIds = GetLastCreatedNodes();
6495 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6496 aNewNodeGroup->Add(anIds);
6500 // Update Python script
6503 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6504 else pyDump << aNewElemGroup << ", ";
6505 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6506 else pyDump << aNewNodeGroup << " ] = ";
6508 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6509 << theNodesNot << ", "
6510 << theAffectedElems << ", "
6511 << theElemGroupNeeded << ", "
6512 << theNodeGroupNeeded <<" )";
6514 aTwoGroups[0] = aNewElemGroup._retn();
6515 aTwoGroups[1] = aNewNodeGroup._retn();
6516 return aTwoGroups._retn();
6518 SMESH_CATCH( SMESH::throwCorbaException );
6522 //================================================================================
6524 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6525 \param theElems - group of of elements (edges or faces) to be replicated
6526 \param theNodesNot - group of nodes not to replicated
6527 \param theShape - shape to detect affected elements (element which geometric center
6528 located on or inside shape).
6529 The replicated nodes should be associated to affected elements.
6530 \return TRUE if operation has been completed successfully, FALSE otherwise
6531 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6533 //================================================================================
6536 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6537 SMESH::SMESH_GroupBase_ptr theNodesNot,
6538 GEOM::GEOM_Object_ptr theShape )
6539 throw (SALOME::SALOME_Exception)
6542 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6548 SMESHDS_Mesh* aMeshDS = getMeshDS();
6549 TIDSortedElemSet anElems, aNodes, anAffected;
6550 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6551 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6553 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6554 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6557 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6559 // Update Python script
6560 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6561 << theNodesNot << ", " << theShape << " )";
6564 SMESH_CATCH( SMESH::throwCorbaException );
6568 //================================================================================
6570 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6571 * \param [in] theGrpList - groups
6572 * \param [in] theMeshDS - mesh
6573 * \param [out] theElemSet - set of elements
6574 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6576 //================================================================================
6578 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6579 SMESHDS_Mesh* theMeshDS,
6580 TIDSortedElemSet& theElemSet,
6581 const bool theIsNodeGrp)
6583 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6585 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6586 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6587 : aGrp->GetType() != SMESH::NODE ) )
6589 SMESH::long_array_var anIDs = aGrp->GetIDs();
6590 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6595 //================================================================================
6597 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6598 This method provided for convenience works as DoubleNodes() described above.
6599 \param theElems - list of groups of elements (edges or faces) to be replicated
6600 \param theNodesNot - list of groups of nodes not to replicated
6601 \param theAffectedElems - group of elements to which the replicated nodes
6602 should be associated to.
6603 \return TRUE if operation has been completed successfully, FALSE otherwise
6604 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6606 //================================================================================
6609 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6610 const SMESH::ListOfGroups& theNodesNot,
6611 const SMESH::ListOfGroups& theAffectedElems)
6612 throw (SALOME::SALOME_Exception)
6618 SMESHDS_Mesh* aMeshDS = getMeshDS();
6619 TIDSortedElemSet anElems, aNodes, anAffected;
6620 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6621 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6622 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6624 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6626 // Update Python script
6627 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6628 << &theNodesNot << ", " << &theAffectedElems << " )";
6630 declareMeshModified( /*isReComputeSafe=*/false );
6633 SMESH_CATCH( SMESH::throwCorbaException );
6637 //================================================================================
6639 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6640 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6641 \param theElems - list of groups of elements (edges or faces) to be replicated
6642 \param theNodesNot - list of groups of nodes not to replicated
6643 \param theAffectedElems - group of elements to which the replicated nodes
6644 should be associated to.
6645 * \return a new group with newly created elements
6646 * \sa DoubleNodeElemGroups()
6648 //================================================================================
6650 SMESH::SMESH_Group_ptr
6651 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6652 const SMESH::ListOfGroups& theNodesNot,
6653 const SMESH::ListOfGroups& theAffectedElems)
6654 throw (SALOME::SALOME_Exception)
6657 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6661 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6662 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6664 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6666 << theNodesNot << ", "
6667 << theAffectedElems << " )";
6669 return elemGroup._retn();
6672 //================================================================================
6674 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6675 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6676 \param theElems - list of groups of elements (edges or faces) to be replicated
6677 \param theNodesNot - list of groups of nodes not to replicated
6678 \param theAffectedElems - group of elements to which the replicated nodes
6679 should be associated to.
6680 * \return a new group with newly created elements
6681 * \sa DoubleNodeElemGroups()
6683 //================================================================================
6685 SMESH::ListOfGroups*
6686 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6687 const SMESH::ListOfGroups& theNodesNot,
6688 const SMESH::ListOfGroups& theAffectedElems,
6689 CORBA::Boolean theElemGroupNeeded,
6690 CORBA::Boolean theNodeGroupNeeded)
6691 throw (SALOME::SALOME_Exception)
6694 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6695 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6696 aTwoGroups->length( 2 );
6701 SMESHDS_Mesh* aMeshDS = getMeshDS();
6702 TIDSortedElemSet anElems, aNodes, anAffected;
6703 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6704 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6705 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6707 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6709 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6714 // Create group with newly created elements
6715 CORBA::String_var elemGroupName = theElems[0]->GetName();
6716 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6717 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6719 SMESH::long_array_var anIds = GetLastCreatedElems();
6720 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6721 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6722 aNewElemGroup->Add(anIds);
6724 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6726 SMESH::long_array_var anIds = GetLastCreatedNodes();
6727 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6728 aNewNodeGroup->Add(anIds);
6732 // Update Python script
6735 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6736 else pyDump << aNewElemGroup << ", ";
6737 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6738 else pyDump << aNewNodeGroup << " ] = ";
6740 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6741 << &theNodesNot << ", "
6742 << &theAffectedElems << ", "
6743 << theElemGroupNeeded << ", "
6744 << theNodeGroupNeeded << " )";
6746 aTwoGroups[0] = aNewElemGroup._retn();
6747 aTwoGroups[1] = aNewNodeGroup._retn();
6748 return aTwoGroups._retn();
6750 SMESH_CATCH( SMESH::throwCorbaException );
6754 //================================================================================
6756 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6757 This method provided for convenience works as DoubleNodes() described above.
6758 \param theElems - list of groups of elements (edges or faces) to be replicated
6759 \param theNodesNot - list of groups of nodes not to replicated
6760 \param theShape - shape to detect affected elements (element which geometric center
6761 located on or inside shape).
6762 The replicated nodes should be associated to affected elements.
6763 \return TRUE if operation has been completed successfully, FALSE otherwise
6764 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6766 //================================================================================
6769 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6770 const SMESH::ListOfGroups& theNodesNot,
6771 GEOM::GEOM_Object_ptr theShape )
6772 throw (SALOME::SALOME_Exception)
6778 SMESHDS_Mesh* aMeshDS = getMeshDS();
6779 TIDSortedElemSet anElems, aNodes;
6780 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6781 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6783 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6784 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6786 // Update Python script
6787 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6788 << &theNodesNot << ", " << theShape << " )";
6790 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6793 SMESH_CATCH( SMESH::throwCorbaException );
6797 //================================================================================
6799 \brief Identify the elements that will be affected by node duplication (actual
6800 duplication is not performed.
6801 This method is the first step of DoubleNodeElemGroupsInRegion.
6802 \param theElems - list of groups of elements (edges or faces) to be replicated
6803 \param theNodesNot - list of groups of nodes not to replicated
6804 \param theShape - shape to detect affected elements (element which geometric center
6805 located on or inside shape).
6806 The replicated nodes should be associated to affected elements.
6807 \return groups of affected elements
6808 \sa DoubleNodeElemGroupsInRegion()
6810 //================================================================================
6811 SMESH::ListOfGroups*
6812 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6813 const SMESH::ListOfGroups& theNodesNot,
6814 GEOM::GEOM_Object_ptr theShape )
6815 throw (SALOME::SALOME_Exception)
6818 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6819 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6820 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6821 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6825 ::SMESH_MeshEditor aMeshEditor(myMesh);
6827 SMESHDS_Mesh* aMeshDS = getMeshDS();
6828 TIDSortedElemSet anElems, aNodes;
6829 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6830 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6831 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6833 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6834 TIDSortedElemSet anAffected;
6835 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6837 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6840 if ( aResult && anAffected.size() > 0 )
6842 SMESH::long_array_var volumeIds = new SMESH::long_array;
6843 SMESH::long_array_var faceIds = new SMESH::long_array;
6844 SMESH::long_array_var edgeIds = new SMESH::long_array;
6845 volumeIds->length( anAffected.size() );
6846 faceIds ->length( anAffected.size() );
6847 edgeIds ->length( anAffected.size() );
6852 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6853 for (; eIt != anAffected.end(); ++eIt)
6855 const SMDS_MeshElement* anElem = *eIt;
6856 int elemId = anElem->GetID();
6857 switch ( anElem->GetType() ) {
6858 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6859 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6860 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6864 volumeIds->length(ivol);
6865 faceIds->length(iface);
6866 edgeIds->length(iedge);
6871 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6872 GenerateGroupName("affectedVolumes").c_str());
6873 aNewVolumeGroup->Add(volumeIds);
6874 aListOfGroups->length( nbGroups+1 );
6875 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6879 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6880 GenerateGroupName("affectedFaces").c_str());
6881 aNewFaceGroup->Add(faceIds);
6882 aListOfGroups->length( nbGroups+1 );
6883 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6887 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6888 GenerateGroupName("affectedEdges").c_str());
6889 aNewEdgeGroup->Add(edgeIds);
6890 aListOfGroups->length( nbGroups+1 );
6891 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6895 // Update Python script
6897 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6898 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6900 return aListOfGroups._retn();
6902 SMESH_CATCH( SMESH::throwCorbaException );
6906 //================================================================================
6908 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6909 The created 2D mesh elements based on nodes of free faces of boundary volumes
6910 \return TRUE if operation has been completed successfully, FALSE otherwise
6912 //================================================================================
6914 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6915 throw (SALOME::SALOME_Exception)
6920 bool aResult = getEditor().Make2DMeshFrom3D();
6922 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6924 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6927 SMESH_CATCH( SMESH::throwCorbaException );
6931 //================================================================================
6933 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6934 * The list of groups must contain at least two groups. The groups have to be disjoint:
6935 * no common element into two different groups.
6936 * The nodes of the internal faces at the boundaries of the groups are doubled.
6937 * Optionally, the internal faces are replaced by flat elements.
6938 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6939 * The flat elements are stored in groups of volumes.
6940 * These groups are named according to the position of the group in the list:
6941 * 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.
6942 * 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.
6943 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6944 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6945 * \param theDomains - list of groups of volumes
6946 * \param createJointElems - if TRUE, create the elements
6947 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6948 * the boundary between \a theDomains and the rest mesh
6949 * \return TRUE if operation has been completed successfully, FALSE otherwise
6951 //================================================================================
6954 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6955 CORBA::Boolean createJointElems,
6956 CORBA::Boolean onAllBoundaries )
6957 throw (SALOME::SALOME_Exception)
6964 SMESHDS_Mesh* aMeshDS = getMeshDS();
6966 // MESSAGE("theDomains.length = "<<theDomains.length());
6967 if ( theDomains.length() <= 1 && !onAllBoundaries )
6968 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6970 vector<TIDSortedElemSet> domains;
6971 domains.resize( theDomains.length() );
6973 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6975 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6976 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6978 // if ( aGrp->GetType() != SMESH::VOLUME )
6979 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6980 SMESH::long_array_var anIDs = aGrp->GetIDs();
6981 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6985 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6986 // TODO publish the groups of flat elements in study
6988 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6990 // Update Python script
6991 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6992 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6994 SMESH_CATCH( SMESH::throwCorbaException );
6996 myMesh_i->CreateGroupServants(); // publish created groups if any
7001 //================================================================================
7003 * \brief Double nodes on some external faces and create flat elements.
7004 * Flat elements are mainly used by some types of mechanic calculations.
7006 * Each group of the list must be constituted of faces.
7007 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
7008 * @param theGroupsOfFaces - list of groups of faces
7009 * @return TRUE if operation has been completed successfully, FALSE otherwise
7011 //================================================================================
7014 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
7015 throw (SALOME::SALOME_Exception)
7020 SMESHDS_Mesh* aMeshDS = getMeshDS();
7022 vector<TIDSortedElemSet> faceGroups;
7025 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7027 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7028 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7030 TIDSortedElemSet faceGroup;
7032 faceGroups.push_back(faceGroup);
7033 SMESH::long_array_var anIDs = aGrp->GetIDs();
7034 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7038 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7039 // TODO publish the groups of flat elements in study
7041 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7043 // Update Python script
7044 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7047 SMESH_CATCH( SMESH::throwCorbaException );
7051 //================================================================================
7053 * \brief Identify all the elements around a geom shape, get the faces delimiting
7056 * Build groups of volume to remove, groups of faces to replace on the skin of the
7057 * object, groups of faces to remove inside the object, (idem edges).
7058 * Build ordered list of nodes at the border of each group of faces to replace
7059 * (to be used to build a geom subshape).
7061 //================================================================================
7063 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7064 GEOM::GEOM_Object_ptr theShape,
7065 const char* groupName,
7066 const SMESH::double_array& theNodesCoords,
7067 SMESH::array_of_long_array_out GroupsOfNodes)
7068 throw (SALOME::SALOME_Exception)
7073 std::vector<std::vector<int> > aListOfListOfNodes;
7074 ::SMESH_MeshEditor aMeshEditor( myMesh );
7076 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7077 if ( !theNodeSearcher )
7078 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7080 vector<double> nodesCoords;
7081 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7083 nodesCoords.push_back( theNodesCoords[i] );
7086 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7087 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7088 nodesCoords, aListOfListOfNodes);
7090 GroupsOfNodes = new SMESH::array_of_long_array;
7091 GroupsOfNodes->length( aListOfListOfNodes.size() );
7092 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7093 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7095 vector<int>& aListOfNodes = *llIt;
7096 vector<int>::iterator lIt = aListOfNodes.begin();;
7097 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7098 aGroup.length( aListOfNodes.size() );
7099 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7100 aGroup[ j ] = (*lIt);
7102 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7105 << ", '" << groupName << "', "
7106 << theNodesCoords << " )";
7108 SMESH_CATCH( SMESH::throwCorbaException );
7111 // issue 20749 ===================================================================
7113 * \brief Creates missing boundary elements
7114 * \param elements - elements whose boundary is to be checked
7115 * \param dimension - defines type of boundary elements to create
7116 * \param groupName - a name of group to store created boundary elements in,
7117 * "" means not to create the group
7118 * \param meshName - a name of new mesh to store created boundary elements in,
7119 * "" means not to create the new mesh
7120 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7121 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7122 * boundary elements will be copied into the new mesh
7123 * \param group - returns the create group, if any
7124 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7126 // ================================================================================
7128 SMESH::SMESH_Mesh_ptr
7129 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7130 SMESH::Bnd_Dimension dim,
7131 const char* groupName,
7132 const char* meshName,
7133 CORBA::Boolean toCopyElements,
7134 CORBA::Boolean toCopyExistingBondary,
7135 SMESH::SMESH_Group_out group)
7136 throw (SALOME::SALOME_Exception)
7141 if ( dim > SMESH::BND_1DFROM2D )
7142 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7144 SMESHDS_Mesh* aMeshDS = getMeshDS();
7146 SMESH::SMESH_Mesh_var mesh_var;
7147 SMESH::SMESH_Group_var group_var;
7151 TIDSortedElemSet elements;
7152 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7153 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7157 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7158 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7160 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7162 // group of new boundary elements
7163 SMESH_Group* smesh_group = 0;
7164 if ( strlen(groupName) )
7166 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7167 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7168 smesh_group = group_i->GetSmeshGroup();
7172 getEditor().MakeBoundaryMesh( elements,
7173 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7177 toCopyExistingBondary);
7180 smesh_mesh->GetMeshDS()->Modified();
7183 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7185 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7186 if ( mesh_var->_is_nil() )
7187 pyDump << myMesh_i->_this() << ", ";
7189 pyDump << mesh_var << ", ";
7190 if ( group_var->_is_nil() )
7191 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7193 pyDump << group_var << " = ";
7194 pyDump << this << ".MakeBoundaryMesh( "
7196 << "SMESH." << dimName[int(dim)] << ", "
7197 << "'" << groupName << "', "
7198 << "'" << meshName<< "', "
7199 << toCopyElements << ", "
7200 << toCopyExistingBondary << ")";
7202 group = group_var._retn();
7203 return mesh_var._retn();
7205 SMESH_CATCH( SMESH::throwCorbaException );
7206 return SMESH::SMESH_Mesh::_nil();
7209 //================================================================================
7211 * \brief Creates missing boundary elements
7212 * \param dimension - defines type of boundary elements to create
7213 * \param groupName - a name of group to store all boundary elements in,
7214 * "" means not to create the group
7215 * \param meshName - a name of a new mesh, which is a copy of the initial
7216 * mesh + created boundary elements; "" means not to create the new mesh
7217 * \param toCopyAll - if true, the whole initial mesh will be copied into
7218 * the new mesh else only boundary elements will be copied into the new mesh
7219 * \param groups - optional groups of elements to make boundary around
7220 * \param mesh - returns the mesh where elements were added to
7221 * \param group - returns the created group, if any
7222 * \retval long - number of added boundary elements
7224 //================================================================================
7226 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7227 const char* groupName,
7228 const char* meshName,
7229 CORBA::Boolean toCopyAll,
7230 const SMESH::ListOfIDSources& groups,
7231 SMESH::SMESH_Mesh_out mesh,
7232 SMESH::SMESH_Group_out group)
7233 throw (SALOME::SALOME_Exception)
7238 if ( dim > SMESH::BND_1DFROM2D )
7239 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7241 // separate groups belonging to this and other mesh
7242 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7243 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7244 groupsOfThisMesh ->length( groups.length() );
7245 groupsOfOtherMesh->length( groups.length() );
7246 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7247 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7249 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7250 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7251 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7253 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7254 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7255 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7257 groupsOfThisMesh->length( nbGroups );
7258 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7263 if ( nbGroupsOfOtherMesh > 0 )
7265 // process groups belonging to another mesh
7266 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7267 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7268 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7269 groupsOfOtherMesh, mesh, group );
7272 SMESH::SMESH_Mesh_var mesh_var;
7273 SMESH::SMESH_Group_var group_var;
7276 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7277 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7281 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7283 /*toCopyGroups=*/false,
7284 /*toKeepIDs=*/true);
7286 mesh_var = makeMesh(meshName);
7288 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7289 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7292 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7293 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7295 // group of boundary elements
7296 SMESH_Group* smesh_group = 0;
7297 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7298 if ( strlen( groupName ))
7300 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7301 group_var = mesh_i->CreateGroup( groupType, groupName );
7302 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7303 smesh_group = group_i->GetSmeshGroup();
7306 TIDSortedElemSet elements;
7308 if ( groups.length() > 0 )
7310 for ( int i = 0; i < nbGroups; ++i )
7313 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7315 SMESH::Bnd_Dimension bdim =
7316 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7317 nbAdded += getEditor().MakeBoundaryMesh( elements,
7318 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7321 /*toCopyElements=*/false,
7322 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7323 /*toAddExistingBondary=*/true,
7324 /*aroundElements=*/true);
7330 nbAdded += getEditor().MakeBoundaryMesh( elements,
7331 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7334 /*toCopyElements=*/false,
7335 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7336 /*toAddExistingBondary=*/true);
7338 tgtMesh->GetMeshDS()->Modified();
7340 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7342 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7343 pyDump << "nbAdded, ";
7344 if ( mesh_var->_is_nil() )
7345 pyDump << myMesh_i->_this() << ", ";
7347 pyDump << mesh_var << ", ";
7348 if ( group_var->_is_nil() )
7349 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7351 pyDump << group_var << " = ";
7352 pyDump << this << ".MakeBoundaryElements( "
7353 << "SMESH." << dimName[int(dim)] << ", "
7354 << "'" << groupName << "', "
7355 << "'" << meshName<< "', "
7356 << toCopyAll << ", "
7359 mesh = mesh_var._retn();
7360 group = group_var._retn();
7363 SMESH_CATCH( SMESH::throwCorbaException );
7367 //================================================================================
7369 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7370 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7371 * plane passing through pairs of points specified by each PolySegment structure.
7372 * If there are several paths connecting a pair of points, the shortest path is
7373 * selected by the module. Position of the cutting plane is defined by the two
7374 * points and an optional vector lying on the plane specified by a PolySegment.
7375 * By default the vector is defined by Mesh module as following. A middle point
7376 * of the two given points is computed. The middle point is projected to the mesh.
7377 * The vector goes from the middle point to the projection point. In case of planar
7378 * mesh, the vector is normal to the mesh.
7379 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7380 * Return the used vector and position of the middle point.
7381 * \param [in] groupName - optional name of a group where created mesh segments will
7384 //================================================================================
7386 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7387 const char* theGroupName)
7388 throw (SALOME::SALOME_Exception)
7390 if ( theSegments.length() == 0 )
7391 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7392 if ( myMesh->NbFaces() == 0 )
7393 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7396 initData(/*deleteSearchers=*/false);
7398 SMESHDS_Group* groupDS = 0;
7399 SMESHDS_Mesh* meshDS = getMeshDS();
7400 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7402 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7403 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7404 while ( faceIt->more() )
7405 tmpMesh->Copy( faceIt->next() );
7406 meshDS = tmpMesh->GetMeshDS();
7408 else if ( theGroupName[0] ) // find/create a group of segments
7410 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7411 // while ( !groupDS && grpIt->more() )
7413 // SMESH_Group* group = grpIt->next();
7414 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7415 // strcmp( group->GetName(), theGroupName ) == 0 )
7417 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7422 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7424 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7425 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7429 // convert input polySegments
7430 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7431 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7433 SMESH::PolySegment& segIn = theSegments[ i ];
7434 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7435 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7436 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7437 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7438 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7439 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7442 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7445 segOut.myVector.SetCoord( segIn.vector.PS.x,
7447 segIn.vector.PS.z );
7450 // get a static ElementSearcher
7451 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7452 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7453 if ( !theElementSearcher )
7454 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7457 std::vector<const SMDS_MeshElement*> newEdges;
7458 std::vector<const SMDS_MeshNode*> newNodes;
7459 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7460 groupDS ? &groupDS->SMDSGroup() : 0,
7461 theElementSearcher );
7463 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7465 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7466 assign( newNodes.begin(), newNodes.end() );
7469 if ( myIsPreviewMode )
7471 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7473 SMESH::PolySegment& segOut = theSegments[ i ];
7474 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7475 segOut.vector.PS.x = segIn.myVector.X();
7476 segOut.vector.PS.y = segIn.myVector.Y();
7477 segOut.vector.PS.z = segIn.myVector.Z();
7482 TPythonDump() << "_segments = []";
7483 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7485 SMESH::PolySegment& segIn = theSegments[ i ];
7486 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7487 << segIn.node1ID1 << ", "
7488 << segIn.node1ID2 << ", "
7489 << segIn.node2ID1 << ", "
7490 << segIn.node2ID2 << ", "
7491 << "smeshBuilder.MakeDirStruct( "
7492 << segIn.vector.PS.x << ", "
7493 << segIn.vector.PS.y << ", "
7494 << segIn.vector.PS.z << ")))";
7496 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7499 SMESH_CATCH( SMESH::throwCorbaException );
7503 //================================================================================
7505 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7506 * The slot is constructed by cutting faces by cylindrical surfaces made
7507 * around each segment. Segments are expected to be created by MakePolyLine().
7508 * \return Edges located at the slot boundary
7510 //================================================================================
7512 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7513 CORBA::Double theWidth)
7514 throw (SALOME::SALOME_Exception)
7516 if ( CORBA::is_nil( theSegments ) ||
7517 theSegments->GetType() != SMESH::EDGE )
7518 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7519 if ( myMesh->NbFaces() == 0 )
7520 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7522 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7525 initData(/*deleteSearchers=*/false);
7527 SMESHDS_Mesh* meshDS = getMeshDS();
7529 // get standalone face groups to be updated
7530 std::vector< SMDS_MeshGroup* > faceGroups;
7531 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7532 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7533 for ( ; grIt != allGroups.end(); ++grIt )
7534 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7535 if ( gr->GetType() == SMDSAbs_Face )
7536 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7538 std::vector< SMESH_MeshAlgos::Edge > edges =
7539 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7540 theWidth, meshDS, faceGroups );
7542 resultEdges->length( edges.size() );
7543 for ( size_t i = 0; i < edges.size(); ++i )
7545 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7546 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7547 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7551 SMESH_CATCH( SMESH::throwCorbaException );
7553 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7555 return resultEdges._retn();