1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
83 #include <Standard_Failure.hxx>
86 #include <Standard_ErrorHandler.hxx>
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
97 using SMESH::TPythonDump;
100 namespace MeshEditor_I {
102 //=============================================================================
104 * \brief Mesh to apply modifications for preview purposes
106 //=============================================================================
108 struct TPreviewMesh: public SMESH_Mesh
110 SMDSAbs_ElementType myPreviewType; // type to show
112 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113 _isShapeToMesh = (_id =_studyId = 0);
114 _myMeshDS = new SMESHDS_Mesh( _id, true );
115 myPreviewType = previewElements;
117 //!< Copy a set of elements
118 void Copy(const TIDSortedElemSet & theElements,
119 TIDSortedElemSet& theCopyElements,
120 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
121 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
123 // loop on theIDsOfElements
124 TIDSortedElemSet::const_iterator eIt = theElements.begin();
125 for ( ; eIt != theElements.end(); ++eIt )
127 const SMDS_MeshElement* anElem = *eIt;
128 if ( !anElem ) continue;
129 SMDSAbs_ElementType type = anElem->GetType();
130 if ( type == theAvoidType ||
131 ( theSelectType != SMDSAbs_All && type != theSelectType ))
133 const SMDS_MeshElement* anElemCopy;
134 if ( type == SMDSAbs_Node)
135 anElemCopy = Copy( cast2Node(anElem) );
137 anElemCopy = Copy( anElem );
139 theCopyElements.insert( theCopyElements.end(), anElemCopy );
143 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
145 // copy element nodes
146 int anElemNbNodes = anElem->NbNodes();
147 vector< int > anElemNodesID( anElemNbNodes ) ;
148 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
149 for ( int i = 0; itElemNodes->more(); i++)
151 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
153 anElemNodesID[i] = anElemNode->GetID();
156 // creates a corresponding element on copied nodes
157 ::SMESH_MeshEditor::ElemFeatures elemType;
158 elemType.Init( anElem, /*basicOnly=*/false );
159 elemType.SetID( anElem->GetID() );
160 SMDS_MeshElement* anElemCopy =
161 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
165 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
167 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
168 anElemNode->GetID());
172 GetMeshDS()->ClearMesh();
174 void Remove( SMDSAbs_ElementType type )
176 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
177 while ( eIt->more() )
178 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
180 };// struct TPreviewMesh
182 static SMESH_NodeSearcher * theNodeSearcher = 0;
183 static SMESH_ElementSearcher * theElementSearcher = 0;
185 //=============================================================================
187 * \brief Deleter of theNodeSearcher at any compute event occurred
189 //=============================================================================
191 struct TSearchersDeleter : public SMESH_subMeshEventListener
194 string myMeshPartIOR;
196 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
197 "SMESH_MeshEditor_i::TSearchersDeleter"),
199 //!< Delete theNodeSearcher
202 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
203 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
205 typedef map < int, SMESH_subMesh * > TDependsOnMap;
206 //!< The meshod called by submesh: do my main job
207 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
208 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
210 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
212 Unset( sm->GetFather() );
215 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
216 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
218 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
225 myMeshPartIOR = meshPartIOR;
226 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
227 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
228 while ( smIt->more() )
231 sm->SetEventListener( this, 0, sm );
235 //!< delete self from all submeshes
236 void Unset(SMESH_Mesh* mesh)
238 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
239 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
240 while ( smIt->more() )
241 smIt->next()->DeleteEventListener( this );
246 } theSearchersDeleter;
248 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
250 TCollection_AsciiString typeStr;
251 switch ( theMirrorType ) {
252 case SMESH::SMESH_MeshEditor::POINT:
253 typeStr = "SMESH.SMESH_MeshEditor.POINT";
255 case SMESH::SMESH_MeshEditor::AXIS:
256 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
259 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
263 //================================================================================
265 * \brief function for conversion of long_array to TIDSortedElemSet
266 * \param IDs - array of IDs
267 * \param aMesh - mesh
268 * \param aMap - collection to fill
269 * \param aType - element type
271 //================================================================================
273 void arrayToSet(const SMESH::long_array & IDs,
274 const SMESHDS_Mesh* aMesh,
275 TIDSortedElemSet& aMap,
276 const SMDSAbs_ElementType aType = SMDSAbs_All,
277 SMDS_MeshElement::Filter* aFilter = NULL)
279 SMDS_MeshElement::NonNullFilter filter1;
280 SMDS_MeshElement::TypeFilter filter2( aType );
282 if ( aFilter == NULL )
283 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
285 SMDS_MeshElement::Filter & filter = *aFilter;
287 if ( aType == SMDSAbs_Node )
288 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
289 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
291 aMap.insert( aMap.end(), elem );
294 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
295 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
297 aMap.insert( aMap.end(), elem );
301 //================================================================================
303 * \brief Retrieve nodes from SMESH_IDSource
305 //================================================================================
307 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
308 const SMESHDS_Mesh* theMeshDS,
309 TIDSortedNodeSet& theNodeSet)
312 if ( CORBA::is_nil( theObject ) )
314 SMESH::array_of_ElementType_var types = theObject->GetTypes();
315 SMESH::long_array_var aElementsId = theObject->GetIDs();
316 if ( types->length() == 1 && types[0] == SMESH::NODE)
318 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
319 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
320 theNodeSet.insert( theNodeSet.end(), n);
322 else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
324 SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
325 while ( nIt->more( ))
326 if ( const SMDS_MeshElement * elem = nIt->next() )
327 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
331 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
332 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
333 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
337 //================================================================================
339 * \brief Returns elements connected to the given elements
341 //================================================================================
343 void getElementsAround(const TIDSortedElemSet& theElements,
344 const SMESHDS_Mesh* theMeshDS,
345 TIDSortedElemSet& theElementsAround)
347 if ( theElements.empty() ) return;
349 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
350 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
352 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
353 return; // all the elements are in theElements
356 elemType = SMDSAbs_All;
358 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
360 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
361 for ( ; elemIt != theElements.end(); ++elemIt )
363 const SMDS_MeshElement* e = *elemIt;
364 int i = e->NbCornerNodes();
367 const SMDS_MeshNode* n = e->GetNode( i );
368 if ( !isNodeChecked[ n->GetID() ])
370 isNodeChecked[ n->GetID() ] = true;
371 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
372 while ( invIt->more() )
374 const SMDS_MeshElement* elemAround = invIt->next();
375 if ( !theElements.count( elemAround ))
376 theElementsAround.insert( elemAround );
383 //================================================================================
385 * \brief Return a string used to detect change of mesh part on which theElementSearcher
386 * is going to be used
388 //================================================================================
390 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
392 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
393 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
394 // take into account passible group modification
395 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
396 partIOR += SMESH_Comment( type );
400 } // namespace MeshEditor_I
402 using namespace MeshEditor_I;
404 //=============================================================================
408 //=============================================================================
410 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
412 myMesh( &theMesh->GetImpl() ),
414 myIsPreviewMode ( isPreview ),
420 //================================================================================
424 //================================================================================
426 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
428 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
429 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
430 poa->deactivate_object(anObjectId.in());
432 //deleteAuxIDSources();
433 delete myPreviewMesh; myPreviewMesh = 0;
434 delete myPreviewEditor; myPreviewEditor = 0;
437 //================================================================================
439 * \brief Returns the mesh
441 //================================================================================
443 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
445 return myMesh_i->_this();
448 //================================================================================
450 * \brief Clear members
452 //================================================================================
454 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
456 if ( myIsPreviewMode ) {
457 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
460 if ( deleteSearchers )
461 TSearchersDeleter::Delete();
463 getEditor().GetError().reset();
464 getEditor().ClearLastCreated();
467 //================================================================================
469 * \brief Increment mesh modif time and optionally record that the performed
470 * modification may influence further mesh re-compute.
471 * \param [in] isReComputeSafe - true if the modification does not influence
472 * further mesh re-compute
474 //================================================================================
476 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
478 myMesh->GetMeshDS()->Modified();
479 if ( !isReComputeSafe )
480 myMesh->SetIsModified( true );
483 //================================================================================
485 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
486 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
488 //================================================================================
490 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
492 if ( myIsPreviewMode && !myPreviewEditor ) {
493 if ( !myPreviewMesh ) getPreviewMesh();
494 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
496 return myIsPreviewMode ? *myPreviewEditor : myEditor;
499 //================================================================================
501 * \brief Initialize and return myPreviewMesh
502 * \param previewElements - type of elements to show in preview
504 * WARNING: call it once per method!
506 //================================================================================
508 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
510 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
512 delete myPreviewEditor;
514 delete myPreviewMesh;
515 myPreviewMesh = new TPreviewMesh( previewElements );
517 myPreviewMesh->Clear();
518 return myPreviewMesh;
521 //================================================================================
523 * Return data of mesh edition preview
525 //================================================================================
527 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
528 throw (SALOME::SALOME_Exception)
531 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
533 if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
535 list<int> aNodesConnectivity;
536 typedef map<int, int> TNodesMap;
539 SMESHDS_Mesh* aMeshDS;
540 std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
542 aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
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.Length() );
627 for (int i = 1; i <= aSeq.Length(); i++)
628 myLastCreatedNodes[i-1] = aSeq.Value(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.Length() );
650 for ( int i = 1; i <= aSeq.Length(); i++ )
651 myLastCreatedElems[i-1] = aSeq.Value(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->myBadElements.empty();
693 errOut->subShapeID = -1;
694 errOut->hasBadMesh = false;
697 return errOut._retn();
698 SMESH_CATCH( SMESH::throwCorbaException );
702 //=======================================================================
703 //function : MakeIDSource
704 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
705 // Call UnRegister() as you fininsh using it!!
706 //=======================================================================
708 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
709 public virtual SALOME::GenericObj_i
711 SMESH::long_array _ids;
712 SMESH::ElementType _type;
713 SMESH::SMESH_Mesh_ptr _mesh;
714 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
715 SMESH::long_array* GetMeshInfo() { return 0; }
716 SMESH::long_array* GetNbElementsByType()
718 SMESH::long_array_var aRes = new SMESH::long_array();
719 aRes->length(SMESH::NB_ELEMENT_TYPES);
720 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
721 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
724 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
725 bool IsMeshInfoCorrect() { return true; }
726 SMESH::array_of_ElementType* GetTypes()
728 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
729 if ( _ids.length() > 0 ) {
733 return types._retn();
735 SALOMEDS::TMPFile* GetVtkUgStream()
737 SALOMEDS::TMPFile_var SeqFile;
738 return SeqFile._retn();
742 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
743 SMESH::ElementType type)
745 _IDSource* idSrc = new _IDSource;
746 idSrc->_mesh = myMesh_i->_this();
749 if ( type == SMESH::ALL && ids.length() > 0 )
750 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
752 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
754 return anIDSourceVar._retn();
757 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
759 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
762 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
765 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
767 nbIds = (int) tmpIdSource->_ids.length();
768 return & tmpIdSource->_ids[0];
774 // void SMESH_MeshEditor_i::deleteAuxIDSources()
776 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
777 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
779 // myAuxIDSources.clear();
782 //=============================================================================
786 //=============================================================================
789 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
790 throw (SALOME::SALOME_Exception)
797 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
798 IdList.push_back( IDsOfElements[i] );
800 // Update Python script
801 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
804 bool ret = getEditor().Remove( IdList, false );
806 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
809 SMESH_CATCH( SMESH::throwCorbaException );
813 //=============================================================================
817 //=============================================================================
819 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
820 throw (SALOME::SALOME_Exception)
826 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
827 IdList.push_back( IDsOfNodes[i] );
829 // Update Python script
830 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
832 bool ret = getEditor().Remove( IdList, true );
834 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
837 SMESH_CATCH( SMESH::throwCorbaException );
841 //=============================================================================
845 //=============================================================================
847 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
848 throw (SALOME::SALOME_Exception)
853 // Update Python script
854 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
856 // Create filter to find all orphan nodes
857 SMESH::Controls::Filter::TIdSequence seq;
858 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
859 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
861 // remove orphan nodes (if there are any)
862 list< int > IdList( seq.begin(), seq.end() );
864 int nbNodesBefore = myMesh->NbNodes();
865 getEditor().Remove( IdList, true );
866 int nbNodesAfter = myMesh->NbNodes();
868 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
869 return nbNodesBefore - nbNodesAfter;
871 SMESH_CATCH( SMESH::throwCorbaException );
875 //=============================================================================
879 //=============================================================================
881 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
882 throw (SALOME::SALOME_Exception)
887 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
889 // Update Python script
890 TPythonDump() << "nodeID = " << this << ".AddNode( "
891 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
893 declareMeshModified( /*isReComputeSafe=*/false );
896 SMESH_CATCH( SMESH::throwCorbaException );
900 //=============================================================================
902 * Create 0D element on the given node.
904 //=============================================================================
906 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
907 CORBA::Boolean DuplicateElements)
908 throw (SALOME::SALOME_Exception)
913 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
914 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
916 SMDS_MeshElement* elem = 0;
917 if ( DuplicateElements || !it0D->more() )
918 elem = getMeshDS()->Add0DElement(aNode);
920 // Update Python script
921 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
923 declareMeshModified( /*isReComputeSafe=*/false );
925 return elem ? elem->GetID() : 0;
927 SMESH_CATCH( SMESH::throwCorbaException );
931 //=============================================================================
933 * Create a ball element on the given node.
935 //=============================================================================
937 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
938 throw (SALOME::SALOME_Exception)
943 if ( diameter < std::numeric_limits<double>::min() )
944 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
946 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
947 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
949 // Update Python script
950 TPythonDump() << "ballElem = "
951 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
953 declareMeshModified( /*isReComputeSafe=*/false );
954 return elem ? elem->GetID() : 0;
956 SMESH_CATCH( SMESH::throwCorbaException );
960 //=============================================================================
962 * Create an edge, either linear and quadratic (this is determed
963 * by number of given nodes, two or three)
965 //=============================================================================
967 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
968 throw (SALOME::SALOME_Exception)
973 int NbNodes = IDsOfNodes.length();
974 SMDS_MeshElement* elem = 0;
977 CORBA::Long index1 = IDsOfNodes[0];
978 CORBA::Long index2 = IDsOfNodes[1];
979 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
980 getMeshDS()->FindNode(index2));
982 // Update Python script
983 TPythonDump() << "edge = " << this << ".AddEdge([ "
984 << index1 << ", " << index2 <<" ])";
987 CORBA::Long n1 = IDsOfNodes[0];
988 CORBA::Long n2 = IDsOfNodes[1];
989 CORBA::Long n12 = IDsOfNodes[2];
990 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
991 getMeshDS()->FindNode(n2),
992 getMeshDS()->FindNode(n12));
993 // Update Python script
994 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
995 <<n1<<", "<<n2<<", "<<n12<<" ])";
998 declareMeshModified( /*isReComputeSafe=*/false );
999 return elem ? elem->GetID() : 0;
1001 SMESH_CATCH( SMESH::throwCorbaException );
1005 //=============================================================================
1009 //=============================================================================
1011 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1012 throw (SALOME::SALOME_Exception)
1017 int NbNodes = IDsOfNodes.length();
1023 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1024 for (int i = 0; i < NbNodes; i++)
1025 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1027 SMDS_MeshElement* elem = 0;
1029 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1030 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1031 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1032 nodes[4], nodes[5]); break;
1033 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1034 nodes[4], nodes[5], nodes[6]); break;
1035 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1036 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1037 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1038 nodes[4], nodes[5], nodes[6], nodes[7],
1040 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1043 // Update Python script
1044 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1046 declareMeshModified( /*isReComputeSafe=*/false );
1048 return elem ? elem->GetID() : 0;
1050 SMESH_CATCH( SMESH::throwCorbaException );
1054 //=============================================================================
1058 //=============================================================================
1060 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1061 throw (SALOME::SALOME_Exception)
1066 int NbNodes = IDsOfNodes.length();
1067 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1068 for (int i = 0; i < NbNodes; i++)
1069 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1072 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1074 // Update Python script
1075 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1077 declareMeshModified( /*isReComputeSafe=*/false );
1078 return elem ? elem->GetID() : 0;
1080 SMESH_CATCH( SMESH::throwCorbaException );
1084 //=============================================================================
1086 * AddQuadPolygonalFace
1088 //=============================================================================
1090 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1091 throw (SALOME::SALOME_Exception)
1096 int NbNodes = IDsOfNodes.length();
1097 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1098 for (int i = 0; i < NbNodes; i++)
1099 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1101 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1103 // Update Python script
1104 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1106 declareMeshModified( /*isReComputeSafe=*/false );
1107 return elem ? elem->GetID() : 0;
1109 SMESH_CATCH( SMESH::throwCorbaException );
1113 //=============================================================================
1115 * Create volume, either linear and quadratic (this is determed
1116 * by number of given nodes)
1118 //=============================================================================
1120 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1121 throw (SALOME::SALOME_Exception)
1126 int NbNodes = IDsOfNodes.length();
1127 vector< const SMDS_MeshNode*> n(NbNodes);
1128 for(int i=0;i<NbNodes;i++)
1129 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1131 SMDS_MeshElement* elem = 0;
1134 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1135 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1136 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1137 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1138 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1139 n[6],n[7],n[8],n[9]);
1141 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1142 n[6],n[7],n[8],n[9],n[10],n[11]);
1144 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1145 n[7],n[8],n[9],n[10],n[11],n[12]);
1147 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1148 n[9],n[10],n[11],n[12],n[13],n[14]);
1150 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1151 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1152 n[15],n[16],n[17],n[18],n[19]);
1154 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1155 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1158 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1159 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1160 n[15],n[16],n[17],n[18],n[19],
1161 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1165 // Update Python script
1166 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1168 declareMeshModified( /*isReComputeSafe=*/false );
1169 return elem ? elem->GetID() : 0;
1171 SMESH_CATCH( SMESH::throwCorbaException );
1175 //=============================================================================
1177 * AddPolyhedralVolume
1179 //=============================================================================
1180 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1181 const SMESH::long_array & Quantities)
1182 throw (SALOME::SALOME_Exception)
1187 int NbNodes = IDsOfNodes.length();
1188 std::vector<const SMDS_MeshNode*> n (NbNodes);
1189 for (int i = 0; i < NbNodes; i++)
1191 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1192 if (!aNode) return 0;
1196 int NbFaces = Quantities.length();
1197 std::vector<int> q (NbFaces);
1198 for (int j = 0; j < NbFaces; j++)
1199 q[j] = Quantities[j];
1201 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1203 // Update Python script
1204 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1205 << IDsOfNodes << ", " << Quantities << " )";
1207 declareMeshModified( /*isReComputeSafe=*/false );
1208 return elem ? elem->GetID() : 0;
1210 SMESH_CATCH( SMESH::throwCorbaException );
1214 //=============================================================================
1216 * AddPolyhedralVolumeByFaces
1218 //=============================================================================
1220 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1221 throw (SALOME::SALOME_Exception)
1226 int NbFaces = IdsOfFaces.length();
1227 std::vector<const SMDS_MeshNode*> poly_nodes;
1228 std::vector<int> quantities (NbFaces);
1230 for (int i = 0; i < NbFaces; i++) {
1231 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1232 quantities[i] = aFace->NbNodes();
1234 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1235 while (It->more()) {
1236 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1240 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1242 // Update Python script
1243 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1244 << IdsOfFaces << " )";
1246 declareMeshModified( /*isReComputeSafe=*/false );
1247 return elem ? elem->GetID() : 0;
1249 SMESH_CATCH( SMESH::throwCorbaException );
1253 //=============================================================================
1255 // \brief Create 0D elements on all nodes of the given object.
1256 // \param theObject object on whose nodes 0D elements will be created.
1257 // \param theGroupName optional name of a group to add 0D elements created
1258 // and/or found on nodes of \a theObject.
1259 // \param DuplicateElements to add one more 0D element to a node or not.
1260 // \return an object (a new group or a temporary SMESH_IDSource) holding
1261 // ids of new and/or found 0D elements.
1263 //=============================================================================
1265 SMESH::SMESH_IDSource_ptr
1266 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1267 const char* theGroupName,
1268 CORBA::Boolean theDuplicateElements)
1269 throw (SALOME::SALOME_Exception)
1274 SMESH::SMESH_IDSource_var result;
1277 TIDSortedElemSet elements, elems0D;
1278 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1279 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1281 SMESH::long_array_var newElems = new SMESH::long_array;
1282 newElems->length( elems0D.size() );
1283 TIDSortedElemSet::iterator eIt = elems0D.begin();
1284 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1285 newElems[ i ] = (*eIt)->GetID();
1287 SMESH::SMESH_GroupBase_var groupToFill;
1288 if ( theGroupName && strlen( theGroupName ))
1290 // Get existing group named theGroupName
1291 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1292 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1293 SMESH::SMESH_GroupBase_var group = groups[i];
1294 if ( !group->_is_nil() ) {
1295 CORBA::String_var name = group->GetName();
1296 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1297 groupToFill = group;
1302 if ( groupToFill->_is_nil() )
1303 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1304 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1305 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1308 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1310 group_i->Add( newElems );
1311 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1312 pyDump << groupToFill;
1316 result = MakeIDSource( newElems, SMESH::ELEM0D );
1317 pyDump << "elem0DIDs";
1320 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1321 << theObject << ", '" << theGroupName << "' )";
1323 return result._retn();
1325 SMESH_CATCH( SMESH::throwCorbaException );
1329 //=============================================================================
1331 * \brief Bind a node to a vertex
1332 * \param NodeID - node ID
1333 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1334 * \retval boolean - false if NodeID or VertexID is invalid
1336 //=============================================================================
1338 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1339 throw (SALOME::SALOME_Exception)
1343 SMESHDS_Mesh * mesh = getMeshDS();
1344 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1346 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1348 if ( mesh->MaxShapeIndex() < VertexID )
1349 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1351 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1352 if ( shape.ShapeType() != TopAbs_VERTEX )
1353 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1355 mesh->SetNodeOnVertex( node, VertexID );
1357 myMesh->SetIsModified( true );
1359 SMESH_CATCH( SMESH::throwCorbaException );
1362 //=============================================================================
1364 * \brief Store node position on an edge
1365 * \param NodeID - node ID
1366 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1367 * \param paramOnEdge - parameter on edge where the node is located
1368 * \retval boolean - false if any parameter is invalid
1370 //=============================================================================
1372 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1373 CORBA::Double paramOnEdge)
1374 throw (SALOME::SALOME_Exception)
1378 SMESHDS_Mesh * mesh = getMeshDS();
1379 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1381 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1383 if ( mesh->MaxShapeIndex() < EdgeID )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1386 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1387 if ( shape.ShapeType() != TopAbs_EDGE )
1388 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1391 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1392 if ( paramOnEdge < f || paramOnEdge > l )
1393 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1395 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1397 myMesh->SetIsModified( true );
1399 SMESH_CATCH( SMESH::throwCorbaException );
1402 //=============================================================================
1404 * \brief Store node position on a face
1405 * \param NodeID - node ID
1406 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1407 * \param u - U parameter on face where the node is located
1408 * \param v - V parameter on face where the node is located
1409 * \retval boolean - false if any parameter is invalid
1411 //=============================================================================
1413 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1414 CORBA::Double u, CORBA::Double v)
1415 throw (SALOME::SALOME_Exception)
1418 SMESHDS_Mesh * mesh = getMeshDS();
1419 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1421 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1423 if ( mesh->MaxShapeIndex() < FaceID )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1426 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1427 if ( shape.ShapeType() != TopAbs_FACE )
1428 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1430 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1431 bool isOut = ( u < surf.FirstUParameter() ||
1432 u > surf.LastUParameter() ||
1433 v < surf.FirstVParameter() ||
1434 v > surf.LastVParameter() );
1438 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1439 << " u( " << surf.FirstUParameter()
1440 << "," << surf.LastUParameter()
1441 << ") v( " << surf.FirstVParameter()
1442 << "," << surf.LastVParameter() << ")" );
1444 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1447 mesh->SetNodeOnFace( node, FaceID, u, v );
1448 myMesh->SetIsModified( true );
1450 SMESH_CATCH( SMESH::throwCorbaException );
1453 //=============================================================================
1455 * \brief Bind a node to a solid
1456 * \param NodeID - node ID
1457 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1458 * \retval boolean - false if NodeID or SolidID is invalid
1460 //=============================================================================
1462 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1463 throw (SALOME::SALOME_Exception)
1466 SMESHDS_Mesh * mesh = getMeshDS();
1467 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1469 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1471 if ( mesh->MaxShapeIndex() < SolidID )
1472 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1474 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1475 if ( shape.ShapeType() != TopAbs_SOLID &&
1476 shape.ShapeType() != TopAbs_SHELL)
1477 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1479 mesh->SetNodeInVolume( node, SolidID );
1481 SMESH_CATCH( SMESH::throwCorbaException );
1484 //=============================================================================
1486 * \brief Bind an element to a shape
1487 * \param ElementID - element ID
1488 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1490 //=============================================================================
1492 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1493 CORBA::Long ShapeID)
1494 throw (SALOME::SALOME_Exception)
1497 SMESHDS_Mesh * mesh = getMeshDS();
1498 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1500 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1502 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1503 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1505 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1506 if ( shape.ShapeType() != TopAbs_EDGE &&
1507 shape.ShapeType() != TopAbs_FACE &&
1508 shape.ShapeType() != TopAbs_SOLID &&
1509 shape.ShapeType() != TopAbs_SHELL )
1510 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1512 mesh->SetMeshElementOnShape( elem, ShapeID );
1514 myMesh->SetIsModified( true );
1516 SMESH_CATCH( SMESH::throwCorbaException );
1519 //=============================================================================
1523 //=============================================================================
1525 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1526 CORBA::Long NodeID2)
1527 throw (SALOME::SALOME_Exception)
1532 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1533 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1537 // Update Python script
1538 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1539 << NodeID1 << ", " << NodeID2 << " )";
1541 int ret = getEditor().InverseDiag ( n1, n2 );
1543 declareMeshModified( /*isReComputeSafe=*/false );
1546 SMESH_CATCH( SMESH::throwCorbaException );
1550 //=============================================================================
1554 //=============================================================================
1556 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1557 CORBA::Long NodeID2)
1558 throw (SALOME::SALOME_Exception)
1563 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1564 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1568 // Update Python script
1569 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1570 << NodeID1 << ", " << NodeID2 << " )";
1573 bool stat = getEditor().DeleteDiag ( n1, n2 );
1575 declareMeshModified( /*isReComputeSafe=*/!stat );
1579 SMESH_CATCH( SMESH::throwCorbaException );
1583 //=============================================================================
1587 //=============================================================================
1589 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1590 throw (SALOME::SALOME_Exception)
1595 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1597 CORBA::Long index = IDsOfElements[i];
1598 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1600 getEditor().Reorient( elem );
1602 // Update Python script
1603 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1605 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1608 SMESH_CATCH( SMESH::throwCorbaException );
1612 //=============================================================================
1616 //=============================================================================
1618 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1619 throw (SALOME::SALOME_Exception)
1624 TPythonDump aTPythonDump; // suppress dump in Reorient()
1626 prepareIdSource( theObject );
1628 SMESH::long_array_var anElementsId = theObject->GetIDs();
1629 CORBA::Boolean isDone = Reorient(anElementsId);
1631 // Update Python script
1632 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1634 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1637 SMESH_CATCH( SMESH::throwCorbaException );
1641 //=======================================================================
1642 //function : Reorient2D
1643 //purpose : Reorient faces contained in \a the2Dgroup.
1644 // the2Dgroup - the mesh or its part to reorient
1645 // theDirection - desired direction of normal of \a theFace
1646 // theFace - ID of face whose orientation is checked.
1647 // It can be < 1 then \a thePoint is used to find a face.
1648 // thePoint - is used to find a face if \a theFace < 1.
1649 // return number of reoriented elements.
1650 //=======================================================================
1652 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1653 const SMESH::DirStruct& theDirection,
1654 CORBA::Long theFace,
1655 const SMESH::PointStruct& thePoint)
1656 throw (SALOME::SALOME_Exception)
1659 initData(/*deleteSearchers=*/false);
1661 TIDSortedElemSet elements;
1662 IDSource_Error error;
1663 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1664 if ( error == IDSource_EMPTY )
1666 if ( error == IDSource_INVALID )
1667 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1670 const SMDS_MeshElement* face = 0;
1673 face = getMeshDS()->FindElement( theFace );
1675 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1676 if ( face->GetType() != SMDSAbs_Face )
1677 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1681 // create theElementSearcher if needed
1682 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1683 if ( !theElementSearcher )
1685 if ( elements.empty() ) // search in the whole mesh
1687 if ( myMesh->NbFaces() == 0 )
1688 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1690 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1694 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1695 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1697 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1701 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1702 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1705 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1706 if ( !elements.empty() && !elements.count( face ))
1707 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1710 const SMESH::PointStruct * P = &theDirection.PS;
1711 gp_Vec dirVec( P->x, P->y, P->z );
1712 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1713 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1715 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1718 declareMeshModified( /*isReComputeSafe=*/false );
1720 TPythonDump() << this << ".Reorient2D( "
1721 << the2Dgroup << ", "
1722 << theDirection << ", "
1724 << thePoint << " )";
1728 SMESH_CATCH( SMESH::throwCorbaException );
1732 //=======================================================================
1733 //function : Reorient2DBy3D
1734 //purpose : Reorient faces basing on orientation of adjacent volumes.
1735 //=======================================================================
1737 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1738 SMESH::SMESH_IDSource_ptr volumeGroup,
1739 CORBA::Boolean outsideNormal)
1740 throw (SALOME::SALOME_Exception)
1745 TIDSortedElemSet volumes;
1746 IDSource_Error volsError;
1747 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1750 for ( size_t i = 0; i < faceGroups.length(); ++i )
1752 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1754 TIDSortedElemSet faces;
1755 IDSource_Error error;
1756 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1757 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1758 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1759 if ( error == IDSource_OK && volsError != IDSource_OK )
1760 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1762 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1764 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1769 declareMeshModified( /*isReComputeSafe=*/false );
1771 TPythonDump() << this << ".Reorient2DBy3D( "
1772 << faceGroups << ", "
1773 << volumeGroup << ", "
1774 << outsideNormal << " )";
1778 SMESH_CATCH( SMESH::throwCorbaException );
1782 //=============================================================================
1784 * \brief Fuse neighbour triangles into quadrangles.
1786 //=============================================================================
1788 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1789 SMESH::NumericalFunctor_ptr Criterion,
1790 CORBA::Double MaxAngle)
1791 throw (SALOME::SALOME_Exception)
1796 SMESHDS_Mesh* aMesh = getMeshDS();
1797 TIDSortedElemSet faces,copyFaces;
1798 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1799 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1800 TIDSortedElemSet* workElements = & faces;
1802 if ( myIsPreviewMode ) {
1803 SMDSAbs_ElementType select = SMDSAbs_Face;
1804 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1805 workElements = & copyFaces;
1808 SMESH::NumericalFunctor_i* aNumericalFunctor =
1809 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1810 SMESH::Controls::NumericalFunctorPtr aCrit;
1811 if ( !aNumericalFunctor )
1812 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1814 aCrit = aNumericalFunctor->GetNumericalFunctor();
1816 if ( !myIsPreviewMode ) {
1817 // Update Python script
1818 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1819 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1822 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1824 declareMeshModified( /*isReComputeSafe=*/!stat );
1827 SMESH_CATCH( SMESH::throwCorbaException );
1831 //=============================================================================
1833 * \brief Fuse neighbour triangles into quadrangles.
1835 //=============================================================================
1837 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1838 SMESH::NumericalFunctor_ptr Criterion,
1839 CORBA::Double MaxAngle)
1840 throw (SALOME::SALOME_Exception)
1845 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1847 prepareIdSource( theObject );
1848 SMESH::long_array_var anElementsId = theObject->GetIDs();
1849 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1851 if ( !myIsPreviewMode ) {
1852 SMESH::NumericalFunctor_i* aNumericalFunctor =
1853 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1855 // Update Python script
1856 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1857 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1862 SMESH_CATCH( SMESH::throwCorbaException );
1866 //=============================================================================
1868 * \brief Split quadrangles into triangles.
1870 //=============================================================================
1872 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1873 SMESH::NumericalFunctor_ptr Criterion)
1874 throw (SALOME::SALOME_Exception)
1879 SMESHDS_Mesh* aMesh = getMeshDS();
1880 TIDSortedElemSet faces;
1881 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1883 SMESH::NumericalFunctor_i* aNumericalFunctor =
1884 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1885 SMESH::Controls::NumericalFunctorPtr aCrit;
1886 if ( !aNumericalFunctor )
1887 aCrit.reset( new SMESH::Controls::AspectRatio() );
1889 aCrit = aNumericalFunctor->GetNumericalFunctor();
1892 // Update Python script
1893 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1895 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1897 declareMeshModified( /*isReComputeSafe=*/false );
1900 SMESH_CATCH( SMESH::throwCorbaException );
1904 //=============================================================================
1906 * \brief Split quadrangles into triangles.
1908 //=============================================================================
1910 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1911 SMESH::NumericalFunctor_ptr Criterion)
1912 throw (SALOME::SALOME_Exception)
1917 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1919 prepareIdSource( theObject );
1920 SMESH::long_array_var anElementsId = theObject->GetIDs();
1921 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1923 SMESH::NumericalFunctor_i* aNumericalFunctor =
1924 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1926 // Update Python script
1927 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1929 declareMeshModified( /*isReComputeSafe=*/false );
1932 SMESH_CATCH( SMESH::throwCorbaException );
1936 //================================================================================
1938 * \brief Split each of quadrangles into 4 triangles.
1939 * \param [in] theObject - theQuads Container of quadrangles to split.
1941 //================================================================================
1943 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1944 throw (SALOME::SALOME_Exception)
1949 TIDSortedElemSet faces;
1950 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1952 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1954 getEditor().QuadTo4Tri( faces );
1955 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1957 SMESH_CATCH( SMESH::throwCorbaException );
1960 //=============================================================================
1962 * \brief Split quadrangles into triangles.
1964 //=============================================================================
1966 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1967 CORBA::Boolean Diag13)
1968 throw (SALOME::SALOME_Exception)
1973 SMESHDS_Mesh* aMesh = getMeshDS();
1974 TIDSortedElemSet faces;
1975 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1977 // Update Python script
1978 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1979 << IDsOfElements << ", " << Diag13 << " )";
1981 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1983 declareMeshModified( /*isReComputeSafe=*/ !stat );
1986 SMESH_CATCH( SMESH::throwCorbaException );
1990 //=============================================================================
1992 * \brief Split quadrangles into triangles.
1994 //=============================================================================
1996 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1997 CORBA::Boolean Diag13)
1998 throw (SALOME::SALOME_Exception)
2003 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2005 prepareIdSource( theObject );
2006 SMESH::long_array_var anElementsId = theObject->GetIDs();
2007 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2009 // Update Python script
2010 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2011 << theObject << ", " << Diag13 << " )";
2013 declareMeshModified( /*isReComputeSafe=*/!isDone );
2016 SMESH_CATCH( SMESH::throwCorbaException );
2021 //=============================================================================
2023 * Find better splitting of the given quadrangle.
2024 * \param IDOfQuad ID of the quadrangle to be splitted.
2025 * \param Criterion A criterion to choose a diagonal for splitting.
2026 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2027 * diagonal is better, 0 if error occurs.
2029 //=============================================================================
2031 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2032 SMESH::NumericalFunctor_ptr Criterion)
2033 throw (SALOME::SALOME_Exception)
2038 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2039 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2041 SMESH::NumericalFunctor_i* aNumericalFunctor =
2042 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2043 SMESH::Controls::NumericalFunctorPtr aCrit;
2044 if (aNumericalFunctor)
2045 aCrit = aNumericalFunctor->GetNumericalFunctor();
2047 aCrit.reset(new SMESH::Controls::AspectRatio());
2049 int id = getEditor().BestSplit(quad, aCrit);
2050 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2054 SMESH_CATCH( SMESH::throwCorbaException );
2058 //================================================================================
2060 * \brief Split volumic elements into tetrahedrons
2062 //================================================================================
2064 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2065 CORBA::Short methodFlags)
2066 throw (SALOME::SALOME_Exception)
2071 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2072 const int noneFacet = -1;
2073 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2074 while( volIt->more() )
2075 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2077 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2078 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2080 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2081 << elems << ", " << methodFlags << " )";
2083 SMESH_CATCH( SMESH::throwCorbaException );
2086 //================================================================================
2088 * \brief Split hexahedra into triangular prisms
2089 * \param elems - elements to split
2090 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2091 * to split into triangles
2092 * \param methodFlags - flags passing splitting method:
2093 * 1 - split the hexahedron into 2 prisms
2094 * 2 - split the hexahedron into 4 prisms
2096 //================================================================================
2098 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2099 const SMESH::PointStruct & startHexPoint,
2100 const SMESH::DirStruct& facetToSplitNormal,
2101 CORBA::Short methodFlags,
2102 CORBA::Boolean allDomains)
2103 throw (SALOME::SALOME_Exception)
2107 prepareIdSource( elems );
2109 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2112 gp_Dir( facetToSplitNormal.PS.x,
2113 facetToSplitNormal.PS.y,
2114 facetToSplitNormal.PS.z ));
2115 TIDSortedElemSet elemSet;
2116 SMESH::long_array_var anElementsId = elems->GetIDs();
2117 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2118 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2120 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2121 while ( !elemSet.empty() )
2123 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2127 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2128 for ( ; ef != elemFacets.end(); ++ef )
2129 elemSet.erase( ef->first );
2132 if ( methodFlags == 2 )
2133 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2135 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2137 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2138 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2140 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2142 << startHexPoint << ", "
2143 << facetToSplitNormal<< ", "
2144 << methodFlags<< ", "
2145 << allDomains << " )";
2147 SMESH_CATCH( SMESH::throwCorbaException );
2150 //================================================================================
2152 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2153 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2154 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2155 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2156 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2157 * will be split in order to keep the mesh conformal.
2158 * \param elems - elements to split
2160 //================================================================================
2162 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2163 throw (SALOME::SALOME_Exception)
2168 TIDSortedElemSet elemSet;
2169 for ( size_t i = 0; i < theElems.length(); ++i )
2171 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2172 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2173 if ( mesh->GetId() != myMesh_i->GetId() )
2174 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2176 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2178 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2180 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2182 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2183 << theElems << " )";
2185 SMESH_CATCH( SMESH::throwCorbaException );
2188 //=======================================================================
2191 //=======================================================================
2194 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2195 const SMESH::long_array & IDsOfFixedNodes,
2196 CORBA::Long MaxNbOfIterations,
2197 CORBA::Double MaxAspectRatio,
2198 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2199 throw (SALOME::SALOME_Exception)
2201 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2202 MaxAspectRatio, Method, false );
2206 //=======================================================================
2207 //function : SmoothParametric
2209 //=======================================================================
2212 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2213 const SMESH::long_array & IDsOfFixedNodes,
2214 CORBA::Long MaxNbOfIterations,
2215 CORBA::Double MaxAspectRatio,
2216 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2217 throw (SALOME::SALOME_Exception)
2219 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2220 MaxAspectRatio, Method, true );
2224 //=======================================================================
2225 //function : SmoothObject
2227 //=======================================================================
2230 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2231 const SMESH::long_array & IDsOfFixedNodes,
2232 CORBA::Long MaxNbOfIterations,
2233 CORBA::Double MaxAspectRatio,
2234 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2235 throw (SALOME::SALOME_Exception)
2237 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2238 MaxAspectRatio, Method, false);
2242 //=======================================================================
2243 //function : SmoothParametricObject
2245 //=======================================================================
2248 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2249 const SMESH::long_array & IDsOfFixedNodes,
2250 CORBA::Long MaxNbOfIterations,
2251 CORBA::Double MaxAspectRatio,
2252 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2253 throw (SALOME::SALOME_Exception)
2255 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2256 MaxAspectRatio, Method, true);
2260 //=============================================================================
2264 //=============================================================================
2267 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2268 const SMESH::long_array & IDsOfFixedNodes,
2269 CORBA::Long MaxNbOfIterations,
2270 CORBA::Double MaxAspectRatio,
2271 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2273 throw (SALOME::SALOME_Exception)
2278 SMESHDS_Mesh* aMesh = getMeshDS();
2280 TIDSortedElemSet elements;
2281 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2283 set<const SMDS_MeshNode*> fixedNodes;
2284 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2285 CORBA::Long index = IDsOfFixedNodes[i];
2286 const SMDS_MeshNode * node = aMesh->FindNode(index);
2288 fixedNodes.insert( node );
2290 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2291 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2292 method = ::SMESH_MeshEditor::CENTROIDAL;
2294 getEditor().Smooth(elements, fixedNodes, method,
2295 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2297 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2299 // Update Python script
2300 TPythonDump() << "isDone = " << this << "."
2301 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2302 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2303 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2304 << "SMESH.SMESH_MeshEditor."
2305 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2306 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2310 SMESH_CATCH( SMESH::throwCorbaException );
2314 //=============================================================================
2318 //=============================================================================
2321 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2322 const SMESH::long_array & IDsOfFixedNodes,
2323 CORBA::Long MaxNbOfIterations,
2324 CORBA::Double MaxAspectRatio,
2325 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2327 throw (SALOME::SALOME_Exception)
2332 TPythonDump aTPythonDump; // suppress dump in smooth()
2334 prepareIdSource( theObject );
2335 SMESH::long_array_var anElementsId = theObject->GetIDs();
2336 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2337 MaxAspectRatio, Method, IsParametric);
2339 // Update Python script
2340 aTPythonDump << "isDone = " << this << "."
2341 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2342 << theObject << ", " << IDsOfFixedNodes << ", "
2343 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2344 << "SMESH.SMESH_MeshEditor."
2345 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2346 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2350 SMESH_CATCH( SMESH::throwCorbaException );
2354 //=============================================================================
2358 //=============================================================================
2360 void SMESH_MeshEditor_i::RenumberNodes()
2361 throw (SALOME::SALOME_Exception)
2364 // Update Python script
2365 TPythonDump() << this << ".RenumberNodes()";
2367 getMeshDS()->Renumber( true );
2369 SMESH_CATCH( SMESH::throwCorbaException );
2372 //=============================================================================
2376 //=============================================================================
2378 void SMESH_MeshEditor_i::RenumberElements()
2379 throw (SALOME::SALOME_Exception)
2382 // Update Python script
2383 TPythonDump() << this << ".RenumberElements()";
2385 getMeshDS()->Renumber( false );
2387 SMESH_CATCH( SMESH::throwCorbaException );
2390 //=======================================================================
2392 * \brief Return groups by their IDs
2394 //=======================================================================
2396 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2397 throw (SALOME::SALOME_Exception)
2402 myMesh_i->CreateGroupServants();
2403 return myMesh_i->GetGroups( *groupIDs );
2405 SMESH_CATCH( SMESH::throwCorbaException );
2409 //=======================================================================
2410 //function : RotationSweepObjects
2412 //=======================================================================
2414 SMESH::ListOfGroups*
2415 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2416 const SMESH::ListOfIDSources & theEdges,
2417 const SMESH::ListOfIDSources & theFaces,
2418 const SMESH::AxisStruct & theAxis,
2419 CORBA::Double theAngleInRadians,
2420 CORBA::Long theNbOfSteps,
2421 CORBA::Double theTolerance,
2422 const bool theMakeGroups)
2423 throw (SALOME::SALOME_Exception)
2428 TIDSortedElemSet elemsNodes[2];
2429 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2430 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2431 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2433 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2434 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2435 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2436 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2438 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2439 bool makeWalls=true;
2440 if ( myIsPreviewMode )
2442 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2443 TPreviewMesh * tmpMesh = getPreviewMesh();
2444 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2445 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2446 workElements = & copyElements[0];
2447 //makeWalls = false; -- faces are needed for preview
2450 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2452 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2453 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2455 ::SMESH_MeshEditor::PGroupIDs groupIds =
2456 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2457 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2459 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2461 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2463 if ( !myIsPreviewMode )
2465 dumpGroupsList( aPythonDump, aGroups );
2466 aPythonDump << this<< ".RotationSweepObjects( "
2471 << TVar( theAngleInRadians ) << ", "
2472 << TVar( theNbOfSteps ) << ", "
2473 << TVar( theTolerance ) << ", "
2474 << theMakeGroups << " )";
2478 getPreviewMesh()->Remove( SMDSAbs_Volume );
2481 return aGroups ? aGroups : new SMESH::ListOfGroups;
2483 SMESH_CATCH( SMESH::throwCorbaException );
2487 namespace MeshEditor_I
2490 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2492 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2494 bool myIsExtrusionByNormal;
2496 static int makeFlags( CORBA::Boolean MakeGroups,
2497 CORBA::Boolean LinearVariation = false,
2498 CORBA::Boolean ByAverageNormal = false,
2499 CORBA::Boolean UseInputElemsOnly = false,
2500 CORBA::Long Flags = 0,
2501 CORBA::Boolean MakeBoundary = true )
2503 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2504 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2505 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2506 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2507 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2511 ExtrusionParams(const SMESH::DirStruct & theDir,
2512 CORBA::Long theNbOfSteps,
2513 const SMESH::double_array & theScaleFactors,
2514 CORBA::Boolean theLinearVariation,
2515 const SMESH::double_array & theBasePoint,
2516 CORBA::Boolean theMakeGroups):
2517 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2521 toList( theScaleFactors ),
2522 TBasePoint( theBasePoint ),
2523 makeFlags( theMakeGroups, theLinearVariation )),
2524 myIsExtrusionByNormal( false )
2528 ExtrusionParams(const SMESH::DirStruct & theDir,
2529 CORBA::Long theNbOfSteps,
2530 CORBA::Boolean theMakeGroups,
2531 CORBA::Long theExtrFlags,
2532 CORBA::Double theSewTolerance):
2533 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2537 std::list<double>(),
2539 makeFlags( theMakeGroups, false, false, false,
2540 theExtrFlags, false ),
2542 myIsExtrusionByNormal( false )
2545 // params for extrusion by normal
2546 ExtrusionParams(CORBA::Double theStepSize,
2547 CORBA::Long theNbOfSteps,
2548 CORBA::Short theDim,
2549 CORBA::Boolean theByAverageNormal,
2550 CORBA::Boolean theUseInputElemsOnly,
2551 CORBA::Boolean theMakeGroups ):
2552 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2554 makeFlags( theMakeGroups, false,
2555 theByAverageNormal, theUseInputElemsOnly ),
2557 myIsExtrusionByNormal( true )
2563 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2568 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2570 std::list<double> scales;
2571 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2572 scales.push_back( theScaleFactors[i] );
2576 // structure used to convert SMESH::double_array to gp_XYZ*
2580 TBasePoint( const SMESH::double_array & theBasePoint )
2583 if ( theBasePoint.length() == 3 )
2585 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2589 operator const gp_XYZ*() const { return pp; }
2594 //=======================================================================
2596 * \brief Generate dim+1 elements by extrusion of elements along vector
2597 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2598 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2599 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2600 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2601 * \param [in] nbOfSteps - number of elements to generate from one element
2602 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2603 * corresponding to groups the input elements included in.
2604 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2606 //=======================================================================
2608 SMESH::ListOfGroups*
2609 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2610 const SMESH::ListOfIDSources & theEdges,
2611 const SMESH::ListOfIDSources & theFaces,
2612 const SMESH::DirStruct & theStepVector,
2613 CORBA::Long theNbOfSteps,
2614 const SMESH::double_array & theScaleFactors,
2615 CORBA::Boolean theLinearVariation,
2616 const SMESH::double_array & theBasePoint,
2617 CORBA::Boolean theToMakeGroups)
2618 throw (SALOME::SALOME_Exception)
2623 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2624 theLinearVariation, theBasePoint, theToMakeGroups );
2626 TIDSortedElemSet elemsNodes[2];
2627 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2628 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2629 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2631 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2632 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2633 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2634 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2636 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2637 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2638 if ( myIsPreviewMode )
2640 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2641 // previewType = SMDSAbs_Edge;
2643 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2644 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2645 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2646 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2647 workElements = & copyElements[0];
2649 params.SetNoGroups();
2651 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2653 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2654 ::SMESH_MeshEditor::PGroupIDs groupIds =
2655 getEditor().ExtrusionSweep( workElements, params, aHistory );
2657 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2659 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2661 if ( !myIsPreviewMode )
2663 dumpGroupsList( aPythonDump, aGroups );
2664 aPythonDump << this<< ".ExtrusionSweepObjects( "
2668 << theStepVector << ", "
2669 << TVar( theNbOfSteps ) << ", "
2670 << theToMakeGroups << " )";
2674 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2677 return aGroups ? aGroups : new SMESH::ListOfGroups;
2679 SMESH_CATCH( SMESH::throwCorbaException );
2683 //=======================================================================
2684 //function : ExtrusionByNormal
2686 //=======================================================================
2688 SMESH::ListOfGroups*
2689 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2690 CORBA::Double stepSize,
2691 CORBA::Long nbOfSteps,
2692 CORBA::Boolean byAverageNormal,
2693 CORBA::Boolean useInputElemsOnly,
2694 CORBA::Boolean makeGroups,
2696 throw (SALOME::SALOME_Exception)
2701 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2703 ExtrusionParams params( stepSize, nbOfSteps, dim,
2704 byAverageNormal, useInputElemsOnly, makeGroups );
2706 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2707 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2709 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2710 if (( elemTypes->length() == 1 ) &&
2711 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2712 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2715 TIDSortedElemSet elemsNodes[2];
2716 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2717 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2719 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2720 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2721 if ( myIsPreviewMode )
2723 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2724 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2725 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2726 workElements = & copyElements[0];
2728 params.SetNoGroups();
2731 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2732 ::SMESH_MeshEditor::PGroupIDs groupIds =
2733 getEditor().ExtrusionSweep( workElements, params, aHistory );
2735 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2737 if (!myIsPreviewMode) {
2738 dumpGroupsList(aPythonDump, aGroups);
2739 aPythonDump << this << ".ExtrusionByNormal( " << objects
2740 << ", " << TVar( stepSize )
2741 << ", " << TVar( nbOfSteps )
2742 << ", " << byAverageNormal
2743 << ", " << useInputElemsOnly
2744 << ", " << makeGroups
2750 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2753 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2755 return aGroups ? aGroups : new SMESH::ListOfGroups;
2757 SMESH_CATCH( SMESH::throwCorbaException );
2761 //=======================================================================
2762 //function : AdvancedExtrusion
2764 //=======================================================================
2766 SMESH::ListOfGroups*
2767 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2768 const SMESH::DirStruct & theStepVector,
2769 CORBA::Long theNbOfSteps,
2770 CORBA::Long theExtrFlags,
2771 CORBA::Double theSewTolerance,
2772 CORBA::Boolean theMakeGroups)
2773 throw (SALOME::SALOME_Exception)
2778 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2780 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2781 theExtrFlags, theSewTolerance );
2783 TIDSortedElemSet elemsNodes[2];
2784 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2786 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2787 ::SMESH_MeshEditor::PGroupIDs groupIds =
2788 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2790 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2792 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2794 if ( !myIsPreviewMode ) {
2795 dumpGroupsList(aPythonDump, aGroups);
2796 aPythonDump << this << ".AdvancedExtrusion( "
2797 << theIDsOfElements << ", "
2798 << theStepVector << ", "
2799 << theNbOfSteps << ", "
2800 << theExtrFlags << ", "
2801 << theSewTolerance << ", "
2802 << theMakeGroups << " )";
2806 getPreviewMesh()->Remove( SMDSAbs_Volume );
2809 return aGroups ? aGroups : new SMESH::ListOfGroups;
2811 SMESH_CATCH( SMESH::throwCorbaException );
2815 //================================================================================
2817 * \brief Convert extrusion error to IDL enum
2819 //================================================================================
2823 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2825 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2829 RETCASE( EXTR_NO_ELEMENTS );
2830 RETCASE( EXTR_PATH_NOT_EDGE );
2831 RETCASE( EXTR_BAD_PATH_SHAPE );
2832 RETCASE( EXTR_BAD_STARTING_NODE );
2833 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2834 RETCASE( EXTR_CANT_GET_TANGENT );
2836 return SMESH::SMESH_MeshEditor::EXTR_OK;
2840 //=======================================================================
2841 //function : extrusionAlongPath
2843 //=======================================================================
2844 SMESH::ListOfGroups*
2845 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2846 const SMESH::ListOfIDSources & theEdges,
2847 const SMESH::ListOfIDSources & theFaces,
2848 SMESH::SMESH_IDSource_ptr thePathMesh,
2849 GEOM::GEOM_Object_ptr thePathShape,
2850 CORBA::Long theNodeStart,
2851 CORBA::Boolean theHasAngles,
2852 const SMESH::double_array & theAngles,
2853 CORBA::Boolean theLinearVariation,
2854 CORBA::Boolean theHasRefPoint,
2855 const SMESH::PointStruct & theRefPoint,
2857 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2858 throw (SALOME::SALOME_Exception)
2863 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2865 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2866 if ( thePathMesh->_is_nil() )
2867 return aGroups._retn();
2870 SMESH_subMesh* aSubMesh = 0;
2871 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2872 if ( thePathShape->_is_nil() )
2874 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2875 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2877 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2878 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2879 if ( !aMeshImp ) return aGroups._retn();
2880 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2881 if ( !aSubMesh ) return aGroups._retn();
2883 else if ( !aMeshImp ||
2884 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2886 return aGroups._retn();
2891 if ( !aMeshImp ) return aGroups._retn();
2892 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2893 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2894 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2895 return aGroups._retn();
2898 SMDS_MeshNode* nodeStart =
2899 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2901 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2902 return aGroups._retn();
2905 TIDSortedElemSet elemsNodes[2];
2906 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2907 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2908 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2910 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2911 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2912 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2913 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2915 list<double> angles;
2916 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2917 angles.push_back( theAngles[i] );
2920 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2922 int nbOldGroups = myMesh->NbGroup();
2924 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2925 if ( myIsPreviewMode )
2927 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2928 TPreviewMesh * tmpMesh = getPreviewMesh();
2929 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2930 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2931 workElements = & copyElements[0];
2932 theMakeGroups = false;
2935 ::SMESH_MeshEditor::Extrusion_Error error;
2937 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2938 theHasAngles, angles, theLinearVariation,
2939 theHasRefPoint, refPnt, theMakeGroups );
2941 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2942 theHasAngles, angles, theLinearVariation,
2943 theHasRefPoint, refPnt, theMakeGroups );
2945 declareMeshModified( /*isReComputeSafe=*/true );
2946 theError = convExtrError( error );
2948 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2949 if ( theMakeGroups ) {
2950 list<int> groupIDs = myMesh->GetGroupIds();
2951 list<int>::iterator newBegin = groupIDs.begin();
2952 std::advance( newBegin, nbOldGroups ); // skip old groups
2953 groupIDs.erase( groupIDs.begin(), newBegin );
2954 aGroups = getGroups( & groupIDs );
2955 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2958 if ( !myIsPreviewMode ) {
2959 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2960 else aPythonDump << "(_noGroups, error) = ";
2961 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2965 << thePathMesh << ", "
2966 << thePathShape << ", "
2967 << theNodeStart << ", "
2968 << theHasAngles << ", "
2969 << TVar( theAngles ) << ", "
2970 << theLinearVariation << ", "
2971 << theHasRefPoint << ", "
2972 << "SMESH.PointStruct( "
2973 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2974 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2975 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2976 << theMakeGroups << " )";
2980 getPreviewMesh()->Remove( SMDSAbs_Volume );
2983 return aGroups._retn();
2985 SMESH_CATCH( SMESH::throwCorbaException );
2989 //================================================================================
2991 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2992 * of given angles along path steps
2993 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2994 * which proceeds the extrusion
2995 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2996 * is used to define the sub-mesh for the path
2998 //================================================================================
3000 SMESH::double_array*
3001 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3002 GEOM::GEOM_Object_ptr thePathShape,
3003 const SMESH::double_array & theAngles)
3005 SMESH::double_array_var aResult = new SMESH::double_array();
3006 int nbAngles = theAngles.length();
3007 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3009 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3010 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3011 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3012 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3013 return aResult._retn();
3014 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3015 if ( nbSteps == nbAngles )
3017 aResult.inout() = theAngles;
3021 aResult->length( nbSteps );
3022 double rAn2St = double( nbAngles ) / double( nbSteps );
3023 double angPrev = 0, angle;
3024 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3026 double angCur = rAn2St * ( iSt+1 );
3027 double angCurFloor = floor( angCur );
3028 double angPrevFloor = floor( angPrev );
3029 if ( angPrevFloor == angCurFloor )
3030 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3033 int iP = int( angPrevFloor );
3034 double angPrevCeil = ceil(angPrev);
3035 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3037 int iC = int( angCurFloor );
3038 if ( iC < nbAngles )
3039 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3041 iP = int( angPrevCeil );
3043 angle += theAngles[ iC ];
3045 aResult[ iSt ] = angle;
3050 // Update Python script
3051 TPythonDump() << "rotAngles = " << theAngles;
3052 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3053 << thePathMesh << ", "
3054 << thePathShape << ", "
3057 return aResult._retn();
3060 //=======================================================================
3063 //=======================================================================
3065 SMESH::ListOfGroups*
3066 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3067 const SMESH::AxisStruct & theAxis,
3068 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3069 CORBA::Boolean theCopy,
3071 ::SMESH_Mesh* theTargetMesh)
3072 throw (SALOME::SALOME_Exception)
3077 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3078 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3080 if ( theTargetMesh )
3084 switch ( theMirrorType ) {
3085 case SMESH::SMESH_MeshEditor::POINT:
3086 aTrsf.SetMirror( P );
3088 case SMESH::SMESH_MeshEditor::AXIS:
3089 aTrsf.SetMirror( gp_Ax1( P, V ));
3092 aTrsf.SetMirror( gp_Ax2( P, V ));
3095 TIDSortedElemSet copyElements;
3096 TIDSortedElemSet* workElements = & theElements;
3098 if ( myIsPreviewMode )
3100 TPreviewMesh * tmpMesh = getPreviewMesh();
3101 tmpMesh->Copy( theElements, copyElements);
3102 if ( !theCopy && !theTargetMesh )
3104 TIDSortedElemSet elemsAround, elemsAroundCopy;
3105 getElementsAround( theElements, getMeshDS(), elemsAround );
3106 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3108 workElements = & copyElements;
3109 theMakeGroups = false;
3112 ::SMESH_MeshEditor::PGroupIDs groupIds =
3113 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3115 if ( !myIsPreviewMode )
3117 if ( theTargetMesh )
3118 theTargetMesh->GetMeshDS()->Modified();
3120 declareMeshModified( /*isReComputeSafe=*/false );
3123 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3125 SMESH_CATCH( SMESH::throwCorbaException );
3129 //=======================================================================
3132 //=======================================================================
3134 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3135 const SMESH::AxisStruct & theAxis,
3136 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3137 CORBA::Boolean theCopy)
3138 throw (SALOME::SALOME_Exception)
3140 if ( !myIsPreviewMode ) {
3141 TPythonDump() << this << ".Mirror( "
3142 << theIDsOfElements << ", "
3144 << mirrorTypeName(theMirrorType) << ", "
3147 if ( theIDsOfElements.length() > 0 )
3149 TIDSortedElemSet elements;
3150 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3151 mirror(elements, theAxis, theMirrorType, theCopy, false);
3156 //=======================================================================
3157 //function : MirrorObject
3159 //=======================================================================
3161 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3162 const SMESH::AxisStruct & theAxis,
3163 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3164 CORBA::Boolean theCopy)
3165 throw (SALOME::SALOME_Exception)
3167 if ( !myIsPreviewMode ) {
3168 TPythonDump() << this << ".MirrorObject( "
3169 << theObject << ", "
3171 << mirrorTypeName(theMirrorType) << ", "
3174 TIDSortedElemSet elements;
3176 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3178 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3179 mirror(elements, theAxis, theMirrorType, theCopy, false);
3182 //=======================================================================
3183 //function : MirrorMakeGroups
3185 //=======================================================================
3187 SMESH::ListOfGroups*
3188 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3189 const SMESH::AxisStruct& theMirror,
3190 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3191 throw (SALOME::SALOME_Exception)
3193 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3195 SMESH::ListOfGroups * aGroups = 0;
3196 if ( theIDsOfElements.length() > 0 )
3198 TIDSortedElemSet elements;
3199 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3200 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3202 if (!myIsPreviewMode) {
3203 dumpGroupsList(aPythonDump, aGroups);
3204 aPythonDump << this << ".MirrorMakeGroups( "
3205 << theIDsOfElements << ", "
3206 << theMirror << ", "
3207 << mirrorTypeName(theMirrorType) << " )";
3212 //=======================================================================
3213 //function : MirrorObjectMakeGroups
3215 //=======================================================================
3217 SMESH::ListOfGroups*
3218 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3219 const SMESH::AxisStruct& theMirror,
3220 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3221 throw (SALOME::SALOME_Exception)
3223 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3225 SMESH::ListOfGroups * aGroups = 0;
3226 TIDSortedElemSet elements;
3227 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3228 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3230 if (!myIsPreviewMode)
3232 dumpGroupsList(aPythonDump,aGroups);
3233 aPythonDump << this << ".MirrorObjectMakeGroups( "
3234 << theObject << ", "
3235 << theMirror << ", "
3236 << mirrorTypeName(theMirrorType) << " )";
3241 //=======================================================================
3242 //function : MirrorMakeMesh
3244 //=======================================================================
3246 SMESH::SMESH_Mesh_ptr
3247 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3248 const SMESH::AxisStruct& theMirror,
3249 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3250 CORBA::Boolean theCopyGroups,
3251 const char* theMeshName)
3252 throw (SALOME::SALOME_Exception)
3254 SMESH_Mesh_i* mesh_i;
3255 SMESH::SMESH_Mesh_var mesh;
3256 { // open new scope to dump "MakeMesh" command
3257 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3259 TPythonDump pydump; // to prevent dump at mesh creation
3261 mesh = makeMesh( theMeshName );
3262 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3263 if (mesh_i && theIDsOfElements.length() > 0 )
3265 TIDSortedElemSet elements;
3266 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3267 mirror(elements, theMirror, theMirrorType,
3268 false, theCopyGroups, & mesh_i->GetImpl());
3269 mesh_i->CreateGroupServants();
3272 if (!myIsPreviewMode) {
3273 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3274 << theIDsOfElements << ", "
3275 << theMirror << ", "
3276 << mirrorTypeName(theMirrorType) << ", "
3277 << theCopyGroups << ", '"
3278 << theMeshName << "' )";
3283 if (!myIsPreviewMode && mesh_i)
3284 mesh_i->GetGroups();
3286 return mesh._retn();
3289 //=======================================================================
3290 //function : MirrorObjectMakeMesh
3292 //=======================================================================
3294 SMESH::SMESH_Mesh_ptr
3295 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3296 const SMESH::AxisStruct& theMirror,
3297 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3298 CORBA::Boolean theCopyGroups,
3299 const char* theMeshName)
3300 throw (SALOME::SALOME_Exception)
3302 SMESH_Mesh_i* mesh_i;
3303 SMESH::SMESH_Mesh_var mesh;
3304 { // open new scope to dump "MakeMesh" command
3305 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3307 TPythonDump pydump; // to prevent dump at mesh creation
3309 mesh = makeMesh( theMeshName );
3310 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3311 TIDSortedElemSet elements;
3313 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3315 mirror(elements, theMirror, theMirrorType,
3316 false, theCopyGroups, & mesh_i->GetImpl());
3317 mesh_i->CreateGroupServants();
3319 if (!myIsPreviewMode) {
3320 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3321 << theObject << ", "
3322 << theMirror << ", "
3323 << mirrorTypeName(theMirrorType) << ", "
3324 << theCopyGroups << ", '"
3325 << theMeshName << "' )";
3330 if (!myIsPreviewMode && mesh_i)
3331 mesh_i->GetGroups();
3333 return mesh._retn();
3336 //=======================================================================
3337 //function : translate
3339 //=======================================================================
3341 SMESH::ListOfGroups*
3342 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3343 const SMESH::DirStruct & theVector,
3344 CORBA::Boolean theCopy,
3346 ::SMESH_Mesh* theTargetMesh)
3347 throw (SALOME::SALOME_Exception)
3352 if ( theTargetMesh )
3356 const SMESH::PointStruct * P = &theVector.PS;
3357 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3359 TIDSortedElemSet copyElements;
3360 TIDSortedElemSet* workElements = &theElements;
3362 if ( myIsPreviewMode )
3364 TPreviewMesh * tmpMesh = getPreviewMesh();
3365 tmpMesh->Copy( theElements, copyElements);
3366 if ( !theCopy && !theTargetMesh )
3368 TIDSortedElemSet elemsAround, elemsAroundCopy;
3369 getElementsAround( theElements, getMeshDS(), elemsAround );
3370 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3372 workElements = & copyElements;
3373 theMakeGroups = false;
3376 ::SMESH_MeshEditor::PGroupIDs groupIds =
3377 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3379 if ( !myIsPreviewMode )
3381 if ( theTargetMesh )
3382 theTargetMesh->GetMeshDS()->Modified();
3384 declareMeshModified( /*isReComputeSafe=*/false );
3387 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3389 SMESH_CATCH( SMESH::throwCorbaException );
3393 //=======================================================================
3394 //function : Translate
3396 //=======================================================================
3398 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3399 const SMESH::DirStruct & theVector,
3400 CORBA::Boolean theCopy)
3401 throw (SALOME::SALOME_Exception)
3403 if (!myIsPreviewMode) {
3404 TPythonDump() << this << ".Translate( "
3405 << theIDsOfElements << ", "
3406 << theVector << ", "
3409 if (theIDsOfElements.length()) {
3410 TIDSortedElemSet elements;
3411 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3412 translate(elements, theVector, theCopy, false);
3416 //=======================================================================
3417 //function : TranslateObject
3419 //=======================================================================
3421 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3422 const SMESH::DirStruct & theVector,
3423 CORBA::Boolean theCopy)
3424 throw (SALOME::SALOME_Exception)
3426 if (!myIsPreviewMode) {
3427 TPythonDump() << this << ".TranslateObject( "
3428 << theObject << ", "
3429 << theVector << ", "
3432 TIDSortedElemSet elements;
3434 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3436 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3437 translate(elements, theVector, theCopy, false);
3440 //=======================================================================
3441 //function : TranslateMakeGroups
3443 //=======================================================================
3445 SMESH::ListOfGroups*
3446 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3447 const SMESH::DirStruct& theVector)
3448 throw (SALOME::SALOME_Exception)
3450 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3452 SMESH::ListOfGroups * aGroups = 0;
3453 if (theIDsOfElements.length()) {
3454 TIDSortedElemSet elements;
3455 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3456 aGroups = translate(elements,theVector,true,true);
3458 if (!myIsPreviewMode) {
3459 dumpGroupsList(aPythonDump, aGroups);
3460 aPythonDump << this << ".TranslateMakeGroups( "
3461 << theIDsOfElements << ", "
3462 << theVector << " )";
3467 //=======================================================================
3468 //function : TranslateObjectMakeGroups
3470 //=======================================================================
3472 SMESH::ListOfGroups*
3473 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3474 const SMESH::DirStruct& theVector)
3475 throw (SALOME::SALOME_Exception)
3477 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3479 SMESH::ListOfGroups * aGroups = 0;
3480 TIDSortedElemSet elements;
3481 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3482 aGroups = translate(elements, theVector, true, true);
3484 if (!myIsPreviewMode) {
3485 dumpGroupsList(aPythonDump, aGroups);
3486 aPythonDump << this << ".TranslateObjectMakeGroups( "
3487 << theObject << ", "
3488 << theVector << " )";
3493 //=======================================================================
3494 //function : TranslateMakeMesh
3496 //=======================================================================
3498 SMESH::SMESH_Mesh_ptr
3499 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3500 const SMESH::DirStruct& theVector,
3501 CORBA::Boolean theCopyGroups,
3502 const char* theMeshName)
3503 throw (SALOME::SALOME_Exception)
3505 SMESH_Mesh_i* mesh_i;
3506 SMESH::SMESH_Mesh_var mesh;
3508 { // open new scope to dump "MakeMesh" command
3509 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3511 TPythonDump pydump; // to prevent dump at mesh creation
3513 mesh = makeMesh( theMeshName );
3514 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3516 if ( mesh_i && theIDsOfElements.length() )
3518 TIDSortedElemSet elements;
3519 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3520 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3521 mesh_i->CreateGroupServants();
3524 if ( !myIsPreviewMode ) {
3525 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3526 << theIDsOfElements << ", "
3527 << theVector << ", "
3528 << theCopyGroups << ", '"
3529 << theMeshName << "' )";
3534 if (!myIsPreviewMode && mesh_i)
3535 mesh_i->GetGroups();
3537 return mesh._retn();
3540 //=======================================================================
3541 //function : TranslateObjectMakeMesh
3543 //=======================================================================
3545 SMESH::SMESH_Mesh_ptr
3546 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3547 const SMESH::DirStruct& theVector,
3548 CORBA::Boolean theCopyGroups,
3549 const char* theMeshName)
3550 throw (SALOME::SALOME_Exception)
3553 SMESH_Mesh_i* mesh_i;
3554 SMESH::SMESH_Mesh_var mesh;
3555 { // open new scope to dump "MakeMesh" command
3556 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3558 TPythonDump pydump; // to prevent dump at mesh creation
3559 mesh = makeMesh( theMeshName );
3560 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3562 TIDSortedElemSet elements;
3564 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3566 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3567 mesh_i->CreateGroupServants();
3569 if ( !myIsPreviewMode ) {
3570 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3571 << theObject << ", "
3572 << theVector << ", "
3573 << theCopyGroups << ", '"
3574 << theMeshName << "' )";
3579 if (!myIsPreviewMode && mesh_i)
3580 mesh_i->GetGroups();
3582 return mesh._retn();
3584 SMESH_CATCH( SMESH::throwCorbaException );
3588 //=======================================================================
3591 //=======================================================================
3593 SMESH::ListOfGroups*
3594 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3595 const SMESH::AxisStruct & theAxis,
3596 CORBA::Double theAngle,
3597 CORBA::Boolean theCopy,
3599 ::SMESH_Mesh* theTargetMesh)
3600 throw (SALOME::SALOME_Exception)
3605 if ( theTargetMesh )
3608 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3609 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3612 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3614 TIDSortedElemSet copyElements;
3615 TIDSortedElemSet* workElements = &theElements;
3616 if ( myIsPreviewMode ) {
3617 TPreviewMesh * tmpMesh = getPreviewMesh();
3618 tmpMesh->Copy( theElements, copyElements );
3619 if ( !theCopy && !theTargetMesh )
3621 TIDSortedElemSet elemsAround, elemsAroundCopy;
3622 getElementsAround( theElements, getMeshDS(), elemsAround );
3623 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3625 workElements = ©Elements;
3626 theMakeGroups = false;
3629 ::SMESH_MeshEditor::PGroupIDs groupIds =
3630 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3632 if ( !myIsPreviewMode)
3634 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3635 else declareMeshModified( /*isReComputeSafe=*/false );
3638 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3640 SMESH_CATCH( SMESH::throwCorbaException );
3644 //=======================================================================
3647 //=======================================================================
3649 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3650 const SMESH::AxisStruct & theAxis,
3651 CORBA::Double theAngle,
3652 CORBA::Boolean theCopy)
3653 throw (SALOME::SALOME_Exception)
3655 if (!myIsPreviewMode) {
3656 TPythonDump() << this << ".Rotate( "
3657 << theIDsOfElements << ", "
3659 << TVar( theAngle ) << ", "
3662 if (theIDsOfElements.length() > 0)
3664 TIDSortedElemSet elements;
3665 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3666 rotate(elements,theAxis,theAngle,theCopy,false);
3670 //=======================================================================
3671 //function : RotateObject
3673 //=======================================================================
3675 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3676 const SMESH::AxisStruct & theAxis,
3677 CORBA::Double theAngle,
3678 CORBA::Boolean theCopy)
3679 throw (SALOME::SALOME_Exception)
3681 if ( !myIsPreviewMode ) {
3682 TPythonDump() << this << ".RotateObject( "
3683 << theObject << ", "
3685 << TVar( theAngle ) << ", "
3688 TIDSortedElemSet elements;
3689 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3690 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3691 rotate(elements,theAxis,theAngle,theCopy,false);
3694 //=======================================================================
3695 //function : RotateMakeGroups
3697 //=======================================================================
3699 SMESH::ListOfGroups*
3700 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3701 const SMESH::AxisStruct& theAxis,
3702 CORBA::Double theAngle)
3703 throw (SALOME::SALOME_Exception)
3705 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3707 SMESH::ListOfGroups * aGroups = 0;
3708 if (theIDsOfElements.length() > 0)
3710 TIDSortedElemSet elements;
3711 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3712 aGroups = rotate(elements,theAxis,theAngle,true,true);
3714 if (!myIsPreviewMode) {
3715 dumpGroupsList(aPythonDump, aGroups);
3716 aPythonDump << this << ".RotateMakeGroups( "
3717 << theIDsOfElements << ", "
3719 << TVar( theAngle ) << " )";
3724 //=======================================================================
3725 //function : RotateObjectMakeGroups
3727 //=======================================================================
3729 SMESH::ListOfGroups*
3730 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3731 const SMESH::AxisStruct& theAxis,
3732 CORBA::Double theAngle)
3733 throw (SALOME::SALOME_Exception)
3735 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3737 SMESH::ListOfGroups * aGroups = 0;
3738 TIDSortedElemSet elements;
3739 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3740 aGroups = rotate(elements, theAxis, theAngle, true, true);
3742 if (!myIsPreviewMode) {
3743 dumpGroupsList(aPythonDump, aGroups);
3744 aPythonDump << this << ".RotateObjectMakeGroups( "
3745 << theObject << ", "
3747 << TVar( theAngle ) << " )";
3752 //=======================================================================
3753 //function : RotateMakeMesh
3755 //=======================================================================
3757 SMESH::SMESH_Mesh_ptr
3758 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3759 const SMESH::AxisStruct& theAxis,
3760 CORBA::Double theAngleInRadians,
3761 CORBA::Boolean theCopyGroups,
3762 const char* theMeshName)
3763 throw (SALOME::SALOME_Exception)
3766 SMESH::SMESH_Mesh_var mesh;
3767 SMESH_Mesh_i* mesh_i;
3769 { // open new scope to dump "MakeMesh" command
3770 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3772 TPythonDump pydump; // to prevent dump at mesh creation
3774 mesh = makeMesh( theMeshName );
3775 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3777 if ( mesh_i && theIDsOfElements.length() > 0 )
3779 TIDSortedElemSet elements;
3780 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3781 rotate(elements, theAxis, theAngleInRadians,
3782 false, theCopyGroups, & mesh_i->GetImpl());
3783 mesh_i->CreateGroupServants();
3785 if ( !myIsPreviewMode ) {
3786 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3787 << theIDsOfElements << ", "
3789 << TVar( theAngleInRadians ) << ", "
3790 << theCopyGroups << ", '"
3791 << theMeshName << "' )";
3796 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3797 mesh_i->GetGroups();
3799 return mesh._retn();
3801 SMESH_CATCH( SMESH::throwCorbaException );
3805 //=======================================================================
3806 //function : RotateObjectMakeMesh
3808 //=======================================================================
3810 SMESH::SMESH_Mesh_ptr
3811 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3812 const SMESH::AxisStruct& theAxis,
3813 CORBA::Double theAngleInRadians,
3814 CORBA::Boolean theCopyGroups,
3815 const char* theMeshName)
3816 throw (SALOME::SALOME_Exception)
3819 SMESH::SMESH_Mesh_var mesh;
3820 SMESH_Mesh_i* mesh_i;
3822 {// open new scope to dump "MakeMesh" command
3823 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3825 TPythonDump pydump; // to prevent dump at mesh creation
3826 mesh = makeMesh( theMeshName );
3827 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3829 TIDSortedElemSet elements;
3831 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3833 rotate(elements, theAxis, theAngleInRadians,
3834 false, theCopyGroups, & mesh_i->GetImpl());
3835 mesh_i->CreateGroupServants();
3837 if ( !myIsPreviewMode ) {
3838 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3839 << theObject << ", "
3841 << TVar( theAngleInRadians ) << ", "
3842 << theCopyGroups << ", '"
3843 << theMeshName << "' )";
3848 if (!myIsPreviewMode && mesh_i)
3849 mesh_i->GetGroups();
3851 return mesh._retn();
3853 SMESH_CATCH( SMESH::throwCorbaException );
3857 //=======================================================================
3860 //=======================================================================
3862 SMESH::ListOfGroups*
3863 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3864 const SMESH::PointStruct& thePoint,
3865 const SMESH::double_array& theScaleFact,
3866 CORBA::Boolean theCopy,
3868 ::SMESH_Mesh* theTargetMesh)
3869 throw (SALOME::SALOME_Exception)
3873 if ( theScaleFact.length() < 1 )
3874 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3875 if ( theScaleFact.length() == 2 )
3876 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3878 if ( theTargetMesh )
3881 TIDSortedElemSet elements;
3882 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3883 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3888 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3889 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3893 #if OCC_VERSION_LARGE > 0x06070100
3894 // fight against orthogonalization
3895 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3896 // 0, S[1], 0, thePoint.y * (1-S[1]),
3897 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3898 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3899 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3900 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3901 loc.SetCoord( thePoint.x * (1-S[0]),
3902 thePoint.y * (1-S[1]),
3903 thePoint.z * (1-S[2]));
3904 M.SetDiagonal( S[0], S[1], S[2] );
3907 double tol = std::numeric_limits<double>::max();
3908 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3909 0, S[1], 0, thePoint.y * (1-S[1]),
3910 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3913 TIDSortedElemSet copyElements;
3914 TIDSortedElemSet* workElements = &elements;
3915 if ( myIsPreviewMode )
3917 TPreviewMesh * tmpMesh = getPreviewMesh();
3918 tmpMesh->Copy( elements, copyElements);
3919 if ( !theCopy && !theTargetMesh )
3921 TIDSortedElemSet elemsAround, elemsAroundCopy;
3922 getElementsAround( elements, getMeshDS(), elemsAround );
3923 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3925 workElements = & copyElements;
3926 theMakeGroups = false;
3929 ::SMESH_MeshEditor::PGroupIDs groupIds =
3930 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3932 if ( !myIsPreviewMode )
3934 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3935 else declareMeshModified( /*isReComputeSafe=*/false );
3937 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3939 SMESH_CATCH( SMESH::throwCorbaException );
3943 //=======================================================================
3946 //=======================================================================
3948 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3949 const SMESH::PointStruct& thePoint,
3950 const SMESH::double_array& theScaleFact,
3951 CORBA::Boolean theCopy)
3952 throw (SALOME::SALOME_Exception)
3954 if ( !myIsPreviewMode ) {
3955 TPythonDump() << this << ".Scale( "
3956 << theObject << ", "
3958 << TVar( theScaleFact ) << ", "
3961 scale(theObject, thePoint, theScaleFact, theCopy, false);
3965 //=======================================================================
3966 //function : ScaleMakeGroups
3968 //=======================================================================
3970 SMESH::ListOfGroups*
3971 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3972 const SMESH::PointStruct& thePoint,
3973 const SMESH::double_array& theScaleFact)
3974 throw (SALOME::SALOME_Exception)
3976 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3978 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3979 if (!myIsPreviewMode) {
3980 dumpGroupsList(aPythonDump, aGroups);
3981 aPythonDump << this << ".Scale("
3984 << TVar( theScaleFact ) << ",True,True)";
3990 //=======================================================================
3991 //function : ScaleMakeMesh
3993 //=======================================================================
3995 SMESH::SMESH_Mesh_ptr
3996 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3997 const SMESH::PointStruct& thePoint,
3998 const SMESH::double_array& theScaleFact,
3999 CORBA::Boolean theCopyGroups,
4000 const char* theMeshName)
4001 throw (SALOME::SALOME_Exception)
4003 SMESH_Mesh_i* mesh_i;
4004 SMESH::SMESH_Mesh_var mesh;
4005 { // open new scope to dump "MakeMesh" command
4006 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4008 TPythonDump pydump; // to prevent dump at mesh creation
4009 mesh = makeMesh( theMeshName );
4010 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4014 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4015 mesh_i->CreateGroupServants();
4017 if ( !myIsPreviewMode )
4018 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4019 << theObject << ", "
4021 << TVar( theScaleFact ) << ", "
4022 << theCopyGroups << ", '"
4023 << theMeshName << "' )";
4027 if (!myIsPreviewMode && mesh_i)
4028 mesh_i->GetGroups();
4030 return mesh._retn();
4034 //=======================================================================
4035 //function : findCoincidentNodes
4037 //=======================================================================
4039 void SMESH_MeshEditor_i::
4040 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4041 CORBA::Double Tolerance,
4042 SMESH::array_of_long_array_out GroupsOfNodes,
4043 CORBA::Boolean SeparateCornersAndMedium)
4045 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4046 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4048 GroupsOfNodes = new SMESH::array_of_long_array;
4049 GroupsOfNodes->length( aListOfListOfNodes.size() );
4050 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4051 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4053 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4054 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4055 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4056 aGroup.length( aListOfNodes.size() );
4057 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4058 aGroup[ j ] = (*lIt)->GetID();
4062 //=======================================================================
4063 //function : FindCoincidentNodes
4065 //=======================================================================
4067 void SMESH_MeshEditor_i::
4068 FindCoincidentNodes (CORBA::Double Tolerance,
4069 SMESH::array_of_long_array_out GroupsOfNodes,
4070 CORBA::Boolean SeparateCornersAndMedium)
4071 throw (SALOME::SALOME_Exception)
4076 TIDSortedNodeSet nodes; // no input nodes
4077 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4079 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4080 << Tolerance << ", "
4081 << SeparateCornersAndMedium << " )";
4083 SMESH_CATCH( SMESH::throwCorbaException );
4086 //=======================================================================
4087 //function : FindCoincidentNodesOnPart
4089 //=======================================================================
4091 void SMESH_MeshEditor_i::
4092 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4093 CORBA::Double Tolerance,
4094 SMESH::array_of_long_array_out GroupsOfNodes,
4095 CORBA::Boolean SeparateCornersAndMedium)
4096 throw (SALOME::SALOME_Exception)
4101 TIDSortedNodeSet nodes;
4102 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4104 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4106 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4108 << Tolerance << ", "
4109 << SeparateCornersAndMedium << " )";
4111 SMESH_CATCH( SMESH::throwCorbaException );
4114 //================================================================================
4116 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4117 * ExceptSubMeshOrGroups
4119 //================================================================================
4121 void SMESH_MeshEditor_i::
4122 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4123 CORBA::Double theTolerance,
4124 SMESH::array_of_long_array_out theGroupsOfNodes,
4125 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4126 CORBA::Boolean theSeparateCornersAndMedium)
4127 throw (SALOME::SALOME_Exception)
4132 TIDSortedNodeSet nodes;
4133 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4135 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4137 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4139 while ( nodeIt->more() )
4140 nodes.erase( cast2Node( nodeIt->next() ));
4142 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4144 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4146 << theTolerance << ", "
4147 << theExceptSubMeshOrGroups << ", "
4148 << theSeparateCornersAndMedium << " )";
4150 SMESH_CATCH( SMESH::throwCorbaException );
4153 //=======================================================================
4154 //function : MergeNodes
4156 //=======================================================================
4158 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4159 const SMESH::ListOfIDSources& NodesToKeep,
4160 CORBA::Boolean AvoidMakingHoles)
4161 throw (SALOME::SALOME_Exception)
4166 SMESHDS_Mesh* aMesh = getMeshDS();
4168 TPythonDump aTPythonDump;
4169 aTPythonDump << this << ".MergeNodes([";
4171 TIDSortedNodeSet setOfNodesToKeep;
4172 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4174 prepareIdSource( NodesToKeep[i] );
4175 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4176 while ( nodeIt->more() )
4177 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4180 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4181 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4183 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4184 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4185 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4186 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4188 CORBA::Long index = aNodeGroup[ j ];
4189 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4191 if ( setOfNodesToKeep.count( node ))
4192 aListOfNodes.push_front( node );
4194 aListOfNodes.push_back( node );
4197 if ( aListOfNodes.size() < 2 )
4198 aListOfListOfNodes.pop_back();
4200 if ( i > 0 ) aTPythonDump << ", ";
4201 aTPythonDump << aNodeGroup;
4204 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4206 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4208 declareMeshModified( /*isReComputeSafe=*/false );
4210 SMESH_CATCH( SMESH::throwCorbaException );
4213 //=======================================================================
4214 //function : FindEqualElements
4216 //=======================================================================
4218 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4219 SMESH::array_of_long_array_out GroupsOfElementsID)
4220 throw (SALOME::SALOME_Exception)
4225 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4226 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4228 TIDSortedElemSet elems;
4229 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4231 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4232 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4234 GroupsOfElementsID = new SMESH::array_of_long_array;
4235 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4237 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4238 aListOfListOfElementsID.begin();
4239 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4241 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4242 list<int>& listOfIDs = *arraysIt;
4243 aGroup.length( listOfIDs.size() );
4244 list<int>::iterator idIt = listOfIDs.begin();
4245 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4246 aGroup[ k ] = *idIt;
4249 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4253 SMESH_CATCH( SMESH::throwCorbaException );
4256 //=======================================================================
4257 //function : MergeElements
4259 //=======================================================================
4261 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4262 throw (SALOME::SALOME_Exception)
4267 TPythonDump aTPythonDump;
4268 aTPythonDump << this << ".MergeElements( [";
4270 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4272 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4273 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4274 aListOfListOfElementsID.push_back( list< int >() );
4275 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4276 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4277 CORBA::Long id = anElemsIDGroup[ j ];
4278 aListOfElemsID.push_back( id );
4280 if ( aListOfElemsID.size() < 2 )
4281 aListOfListOfElementsID.pop_back();
4282 if ( i > 0 ) aTPythonDump << ", ";
4283 aTPythonDump << anElemsIDGroup;
4286 getEditor().MergeElements(aListOfListOfElementsID);
4288 declareMeshModified( /*isReComputeSafe=*/true );
4290 aTPythonDump << "] )";
4292 SMESH_CATCH( SMESH::throwCorbaException );
4295 //=======================================================================
4296 //function : MergeEqualElements
4298 //=======================================================================
4300 void SMESH_MeshEditor_i::MergeEqualElements()
4301 throw (SALOME::SALOME_Exception)
4306 getEditor().MergeEqualElements();
4308 declareMeshModified( /*isReComputeSafe=*/true );
4310 TPythonDump() << this << ".MergeEqualElements()";
4312 SMESH_CATCH( SMESH::throwCorbaException );
4315 //=============================================================================
4317 * Move the node to a given point
4319 //=============================================================================
4321 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4325 throw (SALOME::SALOME_Exception)
4328 initData(/*deleteSearchers=*/false);
4330 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4334 if ( theNodeSearcher )
4335 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4337 if ( myIsPreviewMode ) // make preview data
4339 // in a preview mesh, make edges linked to a node
4340 TPreviewMesh& tmpMesh = *getPreviewMesh();
4341 TIDSortedElemSet linkedNodes;
4342 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4343 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4344 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4345 for ( ; nIt != linkedNodes.end(); ++nIt )
4347 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4348 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4352 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4353 // fill preview data
4355 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4356 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4358 getMeshDS()->MoveNode(node, x, y, z);
4360 if ( !myIsPreviewMode )
4362 // Update Python script
4363 TPythonDump() << "isDone = " << this << ".MoveNode( "
4364 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4365 declareMeshModified( /*isReComputeSafe=*/false );
4368 SMESH_CATCH( SMESH::throwCorbaException );
4373 //================================================================================
4375 * \brief Return ID of node closest to a given point
4377 //================================================================================
4379 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4382 throw (SALOME::SALOME_Exception)
4385 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4387 if ( !theNodeSearcher ) {
4388 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4391 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4392 return node->GetID();
4394 SMESH_CATCH( SMESH::throwCorbaException );
4398 //================================================================================
4400 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4401 * move the node closest to the point to point's location and return ID of the node
4403 //================================================================================
4405 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4408 CORBA::Long theNodeID)
4409 throw (SALOME::SALOME_Exception)
4412 // We keep theNodeSearcher until any mesh modification:
4413 // 1) initData() deletes theNodeSearcher at any edition,
4414 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4416 initData(/*deleteSearchers=*/false);
4418 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4420 int nodeID = theNodeID;
4421 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4422 if ( !node ) // preview moving node
4424 if ( !theNodeSearcher ) {
4425 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4428 node = theNodeSearcher->FindClosestTo( p );
4431 nodeID = node->GetID();
4432 if ( myIsPreviewMode ) // make preview data
4434 // in a preview mesh, make edges linked to a node
4435 TPreviewMesh tmpMesh = *getPreviewMesh();
4436 TIDSortedElemSet linkedNodes;
4437 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4438 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4439 for ( ; nIt != linkedNodes.end(); ++nIt )
4441 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4442 tmpMesh.Copy( &edge );
4445 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4447 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4448 // fill preview data
4450 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4452 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4456 getMeshDS()->MoveNode(node, x, y, z);
4460 if ( !myIsPreviewMode )
4462 TPythonDump() << "nodeID = " << this
4463 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4464 << ", " << nodeID << " )";
4466 declareMeshModified( /*isReComputeSafe=*/false );
4471 SMESH_CATCH( SMESH::throwCorbaException );
4475 //=======================================================================
4477 * Return elements of given type where the given point is IN or ON.
4479 * 'ALL' type means elements of any type excluding nodes
4481 //=======================================================================
4483 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4486 SMESH::ElementType type)
4487 throw (SALOME::SALOME_Exception)
4490 SMESH::long_array_var res = new SMESH::long_array;
4491 vector< const SMDS_MeshElement* > foundElems;
4493 theSearchersDeleter.Set( myMesh );
4494 if ( !theElementSearcher ) {
4495 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4497 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4498 SMDSAbs_ElementType( type ),
4500 res->length( foundElems.size() );
4501 for ( size_t i = 0; i < foundElems.size(); ++i )
4502 res[i] = foundElems[i]->GetID();
4506 SMESH_CATCH( SMESH::throwCorbaException );
4510 //=======================================================================
4511 //function : FindAmongElementsByPoint
4512 //purpose : Searching among the given elements, return elements of given type
4513 // where the given point is IN or ON.
4514 // 'ALL' type means elements of any type excluding nodes
4515 //=======================================================================
4518 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4522 SMESH::ElementType type)
4523 throw (SALOME::SALOME_Exception)
4526 SMESH::long_array_var res = new SMESH::long_array;
4528 if ( type != SMESH::NODE )
4530 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4531 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4532 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4533 type != types[0] ) // but search of elements of dim > 0
4536 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4537 return FindElementsByPoint( x,y,z, type );
4539 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4541 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4542 if ( !theElementSearcher )
4544 // create a searcher from elementIDs
4545 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4546 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4548 if ( !idSourceToSet( elementIDs, meshDS, elements,
4549 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4550 /*emptyIfIsMesh=*/true))
4553 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4554 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4556 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4559 vector< const SMDS_MeshElement* > foundElems;
4561 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4562 SMDSAbs_ElementType( type ),
4564 res->length( foundElems.size() );
4565 for ( size_t i = 0; i < foundElems.size(); ++i )
4566 res[i] = foundElems[i]->GetID();
4570 SMESH_CATCH( SMESH::throwCorbaException );
4574 //=======================================================================
4575 //function : GetPointState
4576 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4577 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4578 //=======================================================================
4580 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4583 throw (SALOME::SALOME_Exception)
4586 theSearchersDeleter.Set( myMesh );
4587 if ( !theElementSearcher ) {
4588 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4590 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4592 SMESH_CATCH( SMESH::throwCorbaException );
4596 //=======================================================================
4597 //function : IsManifold
4598 //purpose : Check if a 2D mesh is manifold
4599 //=======================================================================
4601 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4602 throw (SALOME::SALOME_Exception)
4604 bool isManifold = true;
4607 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4608 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4610 /*closedOnly=*/true,
4612 SMESH_CATCH( SMESH::throwCorbaException );
4617 //=======================================================================
4618 //function : IsCoherentOrientation2D
4619 //purpose : Check if orientation of 2D elements is coherent
4620 //=======================================================================
4622 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4623 throw (SALOME::SALOME_Exception)
4625 bool isGoodOri = true;
4628 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4629 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4631 /*closedOnly=*/true,
4634 SMESH_CATCH( SMESH::throwCorbaException );
4639 //=======================================================================
4640 //function : FindFreeBorders
4641 //purpose : Returns all or only closed FreeBorder's.
4642 //=======================================================================
4644 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4645 throw (SALOME::SALOME_Exception)
4647 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4650 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4651 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4653 resBorders->length( foundFreeBordes.size() );
4654 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4656 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4657 SMESH::FreeBorder& bordOut = resBorders[i];
4658 bordOut.nodeIDs.length( bordNodes.size() );
4659 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4660 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4663 SMESH_CATCH( SMESH::throwCorbaException );
4665 return resBorders._retn();
4668 //=======================================================================
4669 //function : FillHole
4670 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4671 //=======================================================================
4673 void SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole)
4674 throw (SALOME::SALOME_Exception)
4678 if ( theHole.nodeIDs.length() < 4 )
4679 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4680 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4681 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4682 "First and last nodes must be same", SALOME::BAD_PARAM);
4684 SMESH_MeshAlgos::TFreeBorder bordNodes;
4685 bordNodes.resize( theHole.nodeIDs.length() );
4686 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4688 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4689 if ( !bordNodes[ iN ] )
4690 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4691 << " does not exist", SALOME::BAD_PARAM);
4696 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4697 SMDS_Mesh* meshDS = getMeshDS();
4698 if ( myIsPreviewMode )
4700 // copy faces sharing nodes of theHole
4701 TIDSortedElemSet holeFaces;
4702 previewMesh = getPreviewMesh( SMDSAbs_Face );
4703 for ( size_t i = 0; i < bordNodes.size(); ++i )
4705 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4706 while ( fIt->more() )
4708 const SMDS_MeshElement* face = fIt->next();
4709 if ( holeFaces.insert( face ).second )
4710 previewMesh->Copy( face );
4712 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4713 ASSERT( bordNodes[i] );
4715 meshDS = previewMesh->GetMeshDS();
4718 std::vector<const SMDS_MeshElement*> newFaces;
4719 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4721 if ( myIsPreviewMode )
4723 previewMesh->Clear();
4724 for ( size_t i = 0; i < newFaces.size(); ++i )
4725 previewMesh->Copy( newFaces[i] );
4729 getEditor().ClearLastCreated();
4730 SMESH_SequenceOfElemPtr& aSeq =
4731 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
4732 for ( size_t i = 0; i < newFaces.size(); ++i )
4733 aSeq.Append( newFaces[i] );
4735 TPythonDump() << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
4738 SMESH_CATCH( SMESH::throwCorbaException );
4741 //=======================================================================
4742 //function : convError
4744 //=======================================================================
4746 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4748 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4752 RETCASE( SEW_BORDER1_NOT_FOUND );
4753 RETCASE( SEW_BORDER2_NOT_FOUND );
4754 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4755 RETCASE( SEW_BAD_SIDE_NODES );
4756 RETCASE( SEW_VOLUMES_TO_SPLIT );
4757 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4758 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4759 RETCASE( SEW_BAD_SIDE1_NODES );
4760 RETCASE( SEW_BAD_SIDE2_NODES );
4761 RETCASE( SEW_INTERNAL_ERROR );
4763 return SMESH::SMESH_MeshEditor::SEW_OK;
4766 //=======================================================================
4768 * Returns groups of FreeBorder's coincident within the given tolerance.
4769 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4770 * to free borders being compared is used.
4772 //=======================================================================
4774 SMESH::CoincidentFreeBorders*
4775 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4777 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4781 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4782 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4784 // copy free borders
4785 aCFB->borders.length( cfb._borders.size() );
4786 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4788 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4789 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4790 aBRD.nodeIDs.length( nodes.size() );
4791 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4792 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4795 // copy coincident parts
4796 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4797 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4799 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4800 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4801 aGRP.length( grp.size() );
4802 for ( size_t iP = 0; iP < grp.size(); ++iP )
4804 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4805 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4806 aPART.border = part._border;
4807 aPART.node1 = part._node1;
4808 aPART.node2 = part._node2;
4809 aPART.nodeLast = part._nodeLast;
4812 SMESH_CATCH( SMESH::doNothing );
4814 TPythonDump() << "CoincidentFreeBorders = "
4815 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4817 return aCFB._retn();
4820 //=======================================================================
4822 * Sew FreeBorder's of each group
4824 //=======================================================================
4826 CORBA::Short SMESH_MeshEditor_i::
4827 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4828 CORBA::Boolean createPolygons,
4829 CORBA::Boolean createPolyhedra)
4830 throw (SALOME::SALOME_Exception)
4832 CORBA::Short nbSewed = 0;
4834 SMESH_MeshAlgos::TFreeBorderVec groups;
4835 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4837 // check the input and collect nodes
4838 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4840 borderNodes.clear();
4841 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4842 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4844 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4845 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4846 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4848 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4850 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4851 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4852 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4853 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4854 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4855 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4857 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4858 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4859 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4860 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4862 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4864 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4866 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4868 borderNodes.push_back( n1 );
4869 borderNodes.push_back( n2 );
4870 borderNodes.push_back( n3 );
4872 groups.push_back( borderNodes );
4875 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4876 // to get nodes that replace other nodes during merge we create 0D elements
4877 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4880 vector< const SMDS_MeshElement* > tmp0Delems;
4881 for ( size_t i = 0; i < groups.size(); ++i )
4883 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4884 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4886 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4888 tmp0Delems.push_back( it0D->next() );
4890 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4894 // cout << endl << "INIT" << endl;
4895 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4897 // cout << i << " ";
4898 // if ( i % 3 == 0 ) cout << "^ ";
4899 // tmp0Delems[i]->GetNode(0)->Print( cout );
4904 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4906 for ( size_t i = 0; i < groups.size(); ++i )
4908 bool isBordToBord = true;
4909 bool groupSewed = false;
4910 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4911 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4913 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4914 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4915 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4917 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4918 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4919 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4921 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4924 // TIDSortedElemSet emptySet, avoidSet;
4925 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4927 // cout << "WRONG 2nd 1" << endl;
4928 // n0->Print( cout );
4929 // n1->Print( cout );
4931 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4933 // cout << "WRONG 2nd 2" << endl;
4934 // n3->Print( cout );
4935 // n4->Print( cout );
4938 if ( !isBordToBord )
4940 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4941 n2 = 0; // and n2 is not used
4943 // 1st border moves to 2nd
4944 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4946 /*2ndIsFreeBorder=*/ isBordToBord,
4947 createPolygons, createPolyhedra);
4948 groupSewed = ( res == ok );
4950 isBordToBord = false;
4951 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4952 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4954 // cout << t << " ";
4955 // if ( t % 3 == 0 ) cout << "^ ";
4956 // tmp0Delems[t]->GetNode(0)->Print( cout );
4959 i0D += nodes.size();
4960 nbSewed += groupSewed;
4963 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4964 << freeBorders << ", "
4965 << createPolygons << ", "
4966 << createPolyhedra << " )";
4968 SMESH_CATCH( SMESH::doNothing );
4970 declareMeshModified( /*isReComputeSafe=*/false );
4972 // remove tmp 0D elements
4974 set< const SMDS_MeshElement* > removed0D;
4975 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4977 if ( removed0D.insert( tmp0Delems[i] ).second )
4978 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4980 SMESH_CATCH( SMESH::throwCorbaException );
4985 //=======================================================================
4986 //function : SewFreeBorders
4988 //=======================================================================
4990 SMESH::SMESH_MeshEditor::Sew_Error
4991 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4992 CORBA::Long SecondNodeID1,
4993 CORBA::Long LastNodeID1,
4994 CORBA::Long FirstNodeID2,
4995 CORBA::Long SecondNodeID2,
4996 CORBA::Long LastNodeID2,
4997 CORBA::Boolean CreatePolygons,
4998 CORBA::Boolean CreatePolyedrs)
4999 throw (SALOME::SALOME_Exception)
5004 SMESHDS_Mesh* aMesh = getMeshDS();
5006 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5007 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5008 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5009 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5010 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5011 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5013 if (!aBorderFirstNode ||
5014 !aBorderSecondNode||
5016 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5017 if (!aSide2FirstNode ||
5018 !aSide2SecondNode ||
5020 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5022 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5023 << FirstNodeID1 << ", "
5024 << SecondNodeID1 << ", "
5025 << LastNodeID1 << ", "
5026 << FirstNodeID2 << ", "
5027 << SecondNodeID2 << ", "
5028 << LastNodeID2 << ", "
5029 << CreatePolygons<< ", "
5030 << CreatePolyedrs<< " )";
5032 SMESH::SMESH_MeshEditor::Sew_Error error =
5033 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5044 declareMeshModified( /*isReComputeSafe=*/false );
5047 SMESH_CATCH( SMESH::throwCorbaException );
5048 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5052 //=======================================================================
5053 //function : SewConformFreeBorders
5055 //=======================================================================
5057 SMESH::SMESH_MeshEditor::Sew_Error
5058 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5059 CORBA::Long SecondNodeID1,
5060 CORBA::Long LastNodeID1,
5061 CORBA::Long FirstNodeID2,
5062 CORBA::Long SecondNodeID2)
5063 throw (SALOME::SALOME_Exception)
5068 SMESHDS_Mesh* aMesh = getMeshDS();
5070 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5071 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5072 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5073 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5074 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5075 const SMDS_MeshNode* aSide2ThirdNode = 0;
5077 if (!aBorderFirstNode ||
5078 !aBorderSecondNode||
5080 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5081 if (!aSide2FirstNode ||
5083 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5085 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5086 << FirstNodeID1 << ", "
5087 << SecondNodeID1 << ", "
5088 << LastNodeID1 << ", "
5089 << FirstNodeID2 << ", "
5090 << SecondNodeID2 << " )";
5092 SMESH::SMESH_MeshEditor::Sew_Error error =
5093 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5102 declareMeshModified( /*isReComputeSafe=*/false );
5105 SMESH_CATCH( SMESH::throwCorbaException );
5106 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5110 //=======================================================================
5111 //function : SewBorderToSide
5113 //=======================================================================
5115 SMESH::SMESH_MeshEditor::Sew_Error
5116 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5117 CORBA::Long SecondNodeIDOnFreeBorder,
5118 CORBA::Long LastNodeIDOnFreeBorder,
5119 CORBA::Long FirstNodeIDOnSide,
5120 CORBA::Long LastNodeIDOnSide,
5121 CORBA::Boolean CreatePolygons,
5122 CORBA::Boolean CreatePolyedrs)
5123 throw (SALOME::SALOME_Exception)
5128 SMESHDS_Mesh* aMesh = getMeshDS();
5130 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5131 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5132 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5133 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5134 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5135 const SMDS_MeshNode* aSide2ThirdNode = 0;
5137 if (!aBorderFirstNode ||
5138 !aBorderSecondNode||
5140 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5141 if (!aSide2FirstNode ||
5143 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5145 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5146 << FirstNodeIDOnFreeBorder << ", "
5147 << SecondNodeIDOnFreeBorder << ", "
5148 << LastNodeIDOnFreeBorder << ", "
5149 << FirstNodeIDOnSide << ", "
5150 << LastNodeIDOnSide << ", "
5151 << CreatePolygons << ", "
5152 << CreatePolyedrs << ") ";
5154 SMESH::SMESH_MeshEditor::Sew_Error error =
5155 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5165 declareMeshModified( /*isReComputeSafe=*/false );
5168 SMESH_CATCH( SMESH::throwCorbaException );
5169 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5173 //=======================================================================
5174 //function : SewSideElements
5176 //=======================================================================
5178 SMESH::SMESH_MeshEditor::Sew_Error
5179 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5180 const SMESH::long_array& IDsOfSide2Elements,
5181 CORBA::Long NodeID1OfSide1ToMerge,
5182 CORBA::Long NodeID1OfSide2ToMerge,
5183 CORBA::Long NodeID2OfSide1ToMerge,
5184 CORBA::Long NodeID2OfSide2ToMerge)
5185 throw (SALOME::SALOME_Exception)
5190 SMESHDS_Mesh* aMesh = getMeshDS();
5192 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5193 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5194 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5195 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5197 if (!aFirstNode1ToMerge ||
5198 !aFirstNode2ToMerge )
5199 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5200 if (!aSecondNode1ToMerge||
5201 !aSecondNode2ToMerge)
5202 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5204 TIDSortedElemSet aSide1Elems, aSide2Elems;
5205 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5206 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5208 TPythonDump() << "error = " << this << ".SewSideElements( "
5209 << IDsOfSide1Elements << ", "
5210 << IDsOfSide2Elements << ", "
5211 << NodeID1OfSide1ToMerge << ", "
5212 << NodeID1OfSide2ToMerge << ", "
5213 << NodeID2OfSide1ToMerge << ", "
5214 << NodeID2OfSide2ToMerge << ")";
5216 SMESH::SMESH_MeshEditor::Sew_Error error =
5217 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5220 aSecondNode1ToMerge,
5221 aSecondNode2ToMerge));
5223 declareMeshModified( /*isReComputeSafe=*/false );
5226 SMESH_CATCH( SMESH::throwCorbaException );
5227 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5230 //================================================================================
5232 * \brief Set new nodes for given element
5233 * \param ide - element id
5234 * \param newIDs - new node ids
5235 * \retval CORBA::Boolean - true if result is OK
5237 //================================================================================
5239 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5240 const SMESH::long_array& newIDs)
5241 throw (SALOME::SALOME_Exception)
5246 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5247 if(!elem) return false;
5249 int nbn = newIDs.length();
5251 vector<const SMDS_MeshNode*> aNodes(nbn);
5254 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5257 aNodes[nbn1] = aNode;
5260 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5261 << ide << ", " << newIDs << " )";
5263 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5265 declareMeshModified( /*isReComputeSafe=*/ !res );
5269 SMESH_CATCH( SMESH::throwCorbaException );
5273 //=======================================================================
5275 * \brief Makes a part of the mesh quadratic or bi-quadratic
5277 //=======================================================================
5279 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5280 CORBA::Boolean theToBiQuad,
5281 SMESH::SMESH_IDSource_ptr theObject)
5282 throw (SALOME::SALOME_Exception)
5287 TIDSortedElemSet elems;
5289 if ( !( elemsOK = CORBA::is_nil( theObject )))
5291 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5292 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5296 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5297 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5299 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5300 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5302 declareMeshModified( /*isReComputeSafe=*/false );
5305 SMESH_CATCH( SMESH::throwCorbaException );
5308 //=======================================================================
5309 //function : ConvertFromQuadratic
5311 //=======================================================================
5313 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5314 throw (SALOME::SALOME_Exception)
5319 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5320 TPythonDump() << this << ".ConvertFromQuadratic()";
5321 declareMeshModified( /*isReComputeSafe=*/!isDone );
5324 SMESH_CATCH( SMESH::throwCorbaException );
5328 //=======================================================================
5329 //function : ConvertToQuadratic
5331 //=======================================================================
5333 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5334 throw (SALOME::SALOME_Exception)
5336 convertToQuadratic( theForce3d, false );
5337 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5340 //================================================================================
5342 * \brief Makes a part of the mesh quadratic
5344 //================================================================================
5346 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5347 SMESH::SMESH_IDSource_ptr theObject)
5348 throw (SALOME::SALOME_Exception)
5350 convertToQuadratic( theForce3d, false, theObject );
5351 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5354 //================================================================================
5356 * \brief Makes a part of the mesh bi-quadratic
5358 //================================================================================
5360 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5361 SMESH::SMESH_IDSource_ptr theObject)
5362 throw (SALOME::SALOME_Exception)
5364 convertToQuadratic( theForce3d, true, theObject );
5365 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5368 //================================================================================
5370 * \brief Makes a part of the mesh linear
5372 //================================================================================
5374 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5375 throw (SALOME::SALOME_Exception)
5382 TIDSortedElemSet elems;
5383 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5385 if ( elems.empty() )
5387 ConvertFromQuadratic();
5389 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5391 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5395 getEditor().ConvertFromQuadratic(elems);
5398 declareMeshModified( /*isReComputeSafe=*/false );
5400 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5402 SMESH_CATCH( SMESH::throwCorbaException );
5405 //=======================================================================
5406 //function : makeMesh
5407 //purpose : create a named imported mesh
5408 //=======================================================================
5410 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5412 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5413 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5414 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5415 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5416 gen->SetName( meshSO, theMeshName, "Mesh" );
5417 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5419 return mesh._retn();
5422 //=======================================================================
5423 //function : dumpGroupsList
5425 //=======================================================================
5427 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5428 const SMESH::ListOfGroups * theGroupList)
5430 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5431 if ( isDumpGroupList )
5432 theDumpPython << theGroupList << " = ";
5435 //================================================================================
5437 \brief Generates the unique group name.
5438 \param thePrefix name prefix
5441 //================================================================================
5443 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5445 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5446 set<std::string> groupNames;
5448 // Get existing group names
5449 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5450 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5451 if (CORBA::is_nil(aGroup))
5454 CORBA::String_var name = aGroup->GetName();
5455 groupNames.insert( name.in() );
5459 std::string name = thePrefix;
5462 while (!groupNames.insert(name).second)
5463 name = SMESH_Comment( thePrefix ) << "_" << index++;
5468 //================================================================================
5470 * \brief Prepare SMESH_IDSource for work
5472 //================================================================================
5474 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5476 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5478 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5479 filter->SetMesh( mesh );
5482 //================================================================================
5484 * \brief Retrieve elements of given type from SMESH_IDSource
5486 //================================================================================
5488 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5489 const SMESHDS_Mesh* theMeshDS,
5490 TIDSortedElemSet& theElemSet,
5491 const SMDSAbs_ElementType theType,
5492 const bool emptyIfIsMesh,
5493 IDSource_Error* error)
5496 if ( error ) *error = IDSource_OK;
5498 if ( CORBA::is_nil( theIDSource ))
5500 if ( error ) *error = IDSource_INVALID;
5503 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5505 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5506 *error = IDSource_EMPTY;
5509 prepareIdSource( theIDSource );
5510 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5511 if ( anIDs->length() == 0 )
5513 if ( error ) *error = IDSource_EMPTY;
5516 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5517 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5519 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5521 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5525 if ( error ) *error = IDSource_INVALID;
5531 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5532 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5534 if ( error ) *error = IDSource_INVALID;
5541 //================================================================================
5543 * \brief Duplicates given elements, i.e. creates new elements based on the
5544 * same nodes as the given ones.
5545 * \param theElements - container of elements to duplicate.
5546 * \param theGroupName - a name of group to contain the generated elements.
5547 * If a group with such a name already exists, the new elements
5548 * are added to the existng group, else a new group is created.
5549 * If \a theGroupName is empty, new elements are not added
5551 * \return a group where the new elements are added. NULL if theGroupName == "".
5554 //================================================================================
5556 SMESH::SMESH_Group_ptr
5557 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5558 const char* theGroupName)
5559 throw (SALOME::SALOME_Exception)
5561 SMESH::SMESH_Group_var newGroup;
5568 TIDSortedElemSet elems;
5569 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5571 getEditor().DoubleElements( elems );
5573 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5576 SMESH::ElementType type =
5577 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5578 // find existing group
5579 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5580 for ( size_t i = 0; i < groups->length(); ++i )
5581 if ( groups[i]->GetType() == type )
5583 CORBA::String_var name = groups[i]->GetName();
5584 if ( strcmp( name, theGroupName ) == 0 ) {
5585 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5589 // create a new group
5590 if ( newGroup->_is_nil() )
5591 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5593 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5595 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5596 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5597 for ( int i = 1; i <= aSeq.Length(); i++ )
5598 groupDS->SMDSGroup().Add( aSeq(i) );
5603 if ( !newGroup->_is_nil() )
5604 pyDump << newGroup << " = ";
5605 pyDump << this << ".DoubleElements( "
5606 << theElements << ", " << "'" << theGroupName <<"')";
5608 SMESH_CATCH( SMESH::throwCorbaException );
5610 return newGroup._retn();
5613 //================================================================================
5615 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5616 \param theNodes - identifiers of nodes to be doubled
5617 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5618 nodes. If list of element identifiers is empty then nodes are doubled but
5619 they not assigned to elements
5620 \return TRUE if operation has been completed successfully, FALSE otherwise
5621 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5623 //================================================================================
5625 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5626 const SMESH::long_array& theModifiedElems )
5627 throw (SALOME::SALOME_Exception)
5632 list< int > aListOfNodes;
5634 for ( i = 0, n = theNodes.length(); i < n; i++ )
5635 aListOfNodes.push_back( theNodes[ i ] );
5637 list< int > aListOfElems;
5638 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5639 aListOfElems.push_back( theModifiedElems[ i ] );
5641 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5643 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5645 // Update Python script
5646 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5650 SMESH_CATCH( SMESH::throwCorbaException );
5654 //================================================================================
5656 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5657 This method provided for convenience works as DoubleNodes() described above.
5658 \param theNodeId - identifier of node to be doubled.
5659 \param theModifiedElems - identifiers of elements to be updated.
5660 \return TRUE if operation has been completed successfully, FALSE otherwise
5661 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5663 //================================================================================
5665 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5666 const SMESH::long_array& theModifiedElems )
5667 throw (SALOME::SALOME_Exception)
5670 SMESH::long_array_var aNodes = new SMESH::long_array;
5671 aNodes->length( 1 );
5672 aNodes[ 0 ] = theNodeId;
5674 TPythonDump pyDump; // suppress dump by the next line
5676 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5678 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5682 SMESH_CATCH( SMESH::throwCorbaException );
5686 //================================================================================
5688 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5689 This method provided for convenience works as DoubleNodes() described above.
5690 \param theNodes - group of nodes to be doubled.
5691 \param theModifiedElems - group of elements to be updated.
5692 \return TRUE if operation has been completed successfully, FALSE otherwise
5693 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5695 //================================================================================
5697 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5698 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5699 throw (SALOME::SALOME_Exception)
5702 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5705 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5706 SMESH::long_array_var aModifiedElems;
5707 if ( !CORBA::is_nil( theModifiedElems ) )
5708 aModifiedElems = theModifiedElems->GetListOfID();
5711 aModifiedElems = new SMESH::long_array;
5712 aModifiedElems->length( 0 );
5715 TPythonDump pyDump; // suppress dump by the next line
5717 bool done = DoubleNodes( aNodes, aModifiedElems );
5719 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5723 SMESH_CATCH( SMESH::throwCorbaException );
5727 //================================================================================
5729 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5730 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5731 * \param theNodes - group of nodes to be doubled.
5732 * \param theModifiedElems - group of elements to be updated.
5733 * \return a new group with newly created nodes
5734 * \sa DoubleNodeGroup()
5736 //================================================================================
5738 SMESH::SMESH_Group_ptr
5739 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5740 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5741 throw (SALOME::SALOME_Exception)
5744 SMESH::SMESH_Group_var aNewGroup;
5746 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5747 return aNewGroup._retn();
5750 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5751 SMESH::long_array_var aModifiedElems;
5752 if ( !CORBA::is_nil( theModifiedElems ) )
5753 aModifiedElems = theModifiedElems->GetListOfID();
5755 aModifiedElems = new SMESH::long_array;
5756 aModifiedElems->length( 0 );
5759 TPythonDump pyDump; // suppress dump by the next line
5761 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5764 // Create group with newly created nodes
5765 SMESH::long_array_var anIds = GetLastCreatedNodes();
5766 if (anIds->length() > 0) {
5767 std::string anUnindexedName (theNodes->GetName());
5768 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5769 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5770 aNewGroup->Add(anIds);
5771 pyDump << aNewGroup << " = ";
5775 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5776 << theModifiedElems << " )";
5778 return aNewGroup._retn();
5780 SMESH_CATCH( SMESH::throwCorbaException );
5784 //================================================================================
5786 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5787 This method provided for convenience works as DoubleNodes() described above.
5788 \param theNodes - list of groups of nodes to be doubled
5789 \param theModifiedElems - list of groups of elements to be updated.
5790 \return TRUE if operation has been completed successfully, FALSE otherwise
5791 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5793 //================================================================================
5795 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5796 const SMESH::ListOfGroups& theModifiedElems )
5797 throw (SALOME::SALOME_Exception)
5802 std::list< int > aNodes;
5804 for ( i = 0, n = theNodes.length(); i < n; i++ )
5806 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5807 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5809 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5810 for ( j = 0, m = aCurr->length(); j < m; j++ )
5811 aNodes.push_back( aCurr[ j ] );
5815 std::list< int > anElems;
5816 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5818 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5819 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5821 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5822 for ( j = 0, m = aCurr->length(); j < m; j++ )
5823 anElems.push_back( aCurr[ j ] );
5827 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5829 declareMeshModified( /*isReComputeSafe=*/false );
5831 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5835 SMESH_CATCH( SMESH::throwCorbaException );
5839 //================================================================================
5841 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5842 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5843 * \param theNodes - group of nodes to be doubled.
5844 * \param theModifiedElems - group of elements to be updated.
5845 * \return a new group with newly created nodes
5846 * \sa DoubleNodeGroups()
5848 //================================================================================
5850 SMESH::SMESH_Group_ptr
5851 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5852 const SMESH::ListOfGroups& theModifiedElems )
5853 throw (SALOME::SALOME_Exception)
5855 SMESH::SMESH_Group_var aNewGroup;
5857 TPythonDump pyDump; // suppress dump by the next line
5859 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5863 // Create group with newly created nodes
5864 SMESH::long_array_var anIds = GetLastCreatedNodes();
5865 if (anIds->length() > 0) {
5866 std::string anUnindexedName (theNodes[0]->GetName());
5867 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5868 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5869 aNewGroup->Add(anIds);
5870 pyDump << aNewGroup << " = ";
5874 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5875 << theModifiedElems << " )";
5877 return aNewGroup._retn();
5881 //================================================================================
5883 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5884 \param theElems - the list of elements (edges or faces) to be replicated
5885 The nodes for duplication could be found from these elements
5886 \param theNodesNot - list of nodes to NOT replicate
5887 \param theAffectedElems - the list of elements (cells and edges) to which the
5888 replicated nodes should be associated to.
5889 \return TRUE if operation has been completed successfully, FALSE otherwise
5890 \sa DoubleNodeGroup(), DoubleNodeGroups()
5892 //================================================================================
5894 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5895 const SMESH::long_array& theNodesNot,
5896 const SMESH::long_array& theAffectedElems )
5897 throw (SALOME::SALOME_Exception)
5902 SMESHDS_Mesh* aMeshDS = getMeshDS();
5903 TIDSortedElemSet anElems, aNodes, anAffected;
5904 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5905 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5906 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5908 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5910 // Update Python script
5911 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5912 << theNodesNot << ", " << theAffectedElems << " )";
5914 declareMeshModified( /*isReComputeSafe=*/false );
5917 SMESH_CATCH( SMESH::throwCorbaException );
5921 //================================================================================
5923 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5924 \param theElems - the list of elements (edges or faces) to be replicated
5925 The nodes for duplication could be found from these elements
5926 \param theNodesNot - list of nodes to NOT replicate
5927 \param theShape - shape to detect affected elements (element which geometric center
5928 located on or inside shape).
5929 The replicated nodes should be associated to affected elements.
5930 \return TRUE if operation has been completed successfully, FALSE otherwise
5931 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5933 //================================================================================
5935 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5936 const SMESH::long_array& theNodesNot,
5937 GEOM::GEOM_Object_ptr theShape )
5938 throw (SALOME::SALOME_Exception)
5944 SMESHDS_Mesh* aMeshDS = getMeshDS();
5945 TIDSortedElemSet anElems, aNodes;
5946 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5947 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5949 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5950 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5952 // Update Python script
5953 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5954 << theNodesNot << ", " << theShape << " )";
5956 declareMeshModified( /*isReComputeSafe=*/false );
5959 SMESH_CATCH( SMESH::throwCorbaException );
5963 //================================================================================
5965 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5966 \param theElems - group of of elements (edges or faces) to be replicated
5967 \param theNodesNot - group of nodes not to replicated
5968 \param theAffectedElems - group of elements to which the replicated nodes
5969 should be associated to.
5970 \return TRUE if operation has been completed successfully, FALSE otherwise
5971 \sa DoubleNodes(), DoubleNodeGroups()
5973 //================================================================================
5976 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5977 SMESH::SMESH_GroupBase_ptr theNodesNot,
5978 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5979 throw (SALOME::SALOME_Exception)
5982 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5988 SMESHDS_Mesh* aMeshDS = getMeshDS();
5989 TIDSortedElemSet anElems, aNodes, anAffected;
5990 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5991 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5992 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5994 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5996 // Update Python script
5997 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5998 << theNodesNot << ", " << theAffectedElems << " )";
6000 declareMeshModified( /*isReComputeSafe=*/false );
6003 SMESH_CATCH( SMESH::throwCorbaException );
6007 //================================================================================
6009 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6010 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6011 * \param theElems - group of of elements (edges or faces) to be replicated
6012 * \param theNodesNot - group of nodes not to replicated
6013 * \param theAffectedElems - group of elements to which the replicated nodes
6014 * should be associated to.
6015 * \return a new group with newly created elements
6016 * \sa DoubleNodeElemGroup()
6018 //================================================================================
6020 SMESH::SMESH_Group_ptr
6021 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6022 SMESH::SMESH_GroupBase_ptr theNodesNot,
6023 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6024 throw (SALOME::SALOME_Exception)
6027 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6031 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6032 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6034 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6036 << theNodesNot << ", "
6037 << theAffectedElems << " )";
6039 return elemGroup._retn();
6042 //================================================================================
6044 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6045 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6046 * \param theElems - group of of elements (edges or faces) to be replicated
6047 * \param theNodesNot - group of nodes not to replicated
6048 * \param theAffectedElems - group of elements to which the replicated nodes
6049 * should be associated to.
6050 * \return a new group with newly created elements
6051 * \sa DoubleNodeElemGroup()
6053 //================================================================================
6055 SMESH::ListOfGroups*
6056 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6057 SMESH::SMESH_GroupBase_ptr theNodesNot,
6058 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6059 CORBA::Boolean theElemGroupNeeded,
6060 CORBA::Boolean theNodeGroupNeeded)
6061 throw (SALOME::SALOME_Exception)
6064 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6065 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6066 aTwoGroups->length( 2 );
6068 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6069 return aTwoGroups._retn();
6074 SMESHDS_Mesh* aMeshDS = getMeshDS();
6075 TIDSortedElemSet anElems, aNodes, anAffected;
6076 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6077 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6078 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6081 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6083 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6089 // Create group with newly created elements
6090 CORBA::String_var elemGroupName = theElems->GetName();
6091 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6092 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6094 SMESH::long_array_var anIds = GetLastCreatedElems();
6095 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6096 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6097 aNewElemGroup->Add(anIds);
6099 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6101 SMESH::long_array_var anIds = GetLastCreatedNodes();
6102 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6103 aNewNodeGroup->Add(anIds);
6107 // Update Python script
6110 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6111 else pyDump << aNewElemGroup << ", ";
6112 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6113 else pyDump << aNewNodeGroup << " ] = ";
6115 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6116 << theNodesNot << ", "
6117 << theAffectedElems << ", "
6118 << theElemGroupNeeded << ", "
6119 << theNodeGroupNeeded <<" )";
6121 aTwoGroups[0] = aNewElemGroup._retn();
6122 aTwoGroups[1] = aNewNodeGroup._retn();
6123 return aTwoGroups._retn();
6125 SMESH_CATCH( SMESH::throwCorbaException );
6129 //================================================================================
6131 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6132 \param theElems - group of of elements (edges or faces) to be replicated
6133 \param theNodesNot - group of nodes not to replicated
6134 \param theShape - shape to detect affected elements (element which geometric center
6135 located on or inside shape).
6136 The replicated nodes should be associated to affected elements.
6137 \return TRUE if operation has been completed successfully, FALSE otherwise
6138 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6140 //================================================================================
6143 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6144 SMESH::SMESH_GroupBase_ptr theNodesNot,
6145 GEOM::GEOM_Object_ptr theShape )
6146 throw (SALOME::SALOME_Exception)
6149 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6155 SMESHDS_Mesh* aMeshDS = getMeshDS();
6156 TIDSortedElemSet anElems, aNodes, anAffected;
6157 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6158 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6160 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6161 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6164 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6166 // Update Python script
6167 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6168 << theNodesNot << ", " << theShape << " )";
6171 SMESH_CATCH( SMESH::throwCorbaException );
6175 //================================================================================
6177 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6178 * \param [in] theGrpList - groups
6179 * \param [in] theMeshDS - mesh
6180 * \param [out] theElemSet - set of elements
6181 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6183 //================================================================================
6185 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6186 SMESHDS_Mesh* theMeshDS,
6187 TIDSortedElemSet& theElemSet,
6188 const bool theIsNodeGrp)
6190 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6192 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6193 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6194 : aGrp->GetType() != SMESH::NODE ) )
6196 SMESH::long_array_var anIDs = aGrp->GetIDs();
6197 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6202 //================================================================================
6204 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6205 This method provided for convenience works as DoubleNodes() described above.
6206 \param theElems - list of groups of elements (edges or faces) to be replicated
6207 \param theNodesNot - list of groups of nodes not to replicated
6208 \param theAffectedElems - group of elements to which the replicated nodes
6209 should be associated to.
6210 \return TRUE if operation has been completed successfully, FALSE otherwise
6211 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6213 //================================================================================
6216 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6217 const SMESH::ListOfGroups& theNodesNot,
6218 const SMESH::ListOfGroups& theAffectedElems)
6219 throw (SALOME::SALOME_Exception)
6225 SMESHDS_Mesh* aMeshDS = getMeshDS();
6226 TIDSortedElemSet anElems, aNodes, anAffected;
6227 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6228 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6229 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6231 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6233 // Update Python script
6234 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6235 << &theNodesNot << ", " << &theAffectedElems << " )";
6237 declareMeshModified( /*isReComputeSafe=*/false );
6240 SMESH_CATCH( SMESH::throwCorbaException );
6244 //================================================================================
6246 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6247 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6248 \param theElems - list of groups of elements (edges or faces) to be replicated
6249 \param theNodesNot - list of groups of nodes not to replicated
6250 \param theAffectedElems - group of elements to which the replicated nodes
6251 should be associated to.
6252 * \return a new group with newly created elements
6253 * \sa DoubleNodeElemGroups()
6255 //================================================================================
6257 SMESH::SMESH_Group_ptr
6258 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6259 const SMESH::ListOfGroups& theNodesNot,
6260 const SMESH::ListOfGroups& theAffectedElems)
6261 throw (SALOME::SALOME_Exception)
6264 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6268 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6269 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6271 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6273 << theNodesNot << ", "
6274 << theAffectedElems << " )";
6276 return elemGroup._retn();
6279 //================================================================================
6281 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6282 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6283 \param theElems - list of groups of elements (edges or faces) to be replicated
6284 \param theNodesNot - list of groups of nodes not to replicated
6285 \param theAffectedElems - group of elements to which the replicated nodes
6286 should be associated to.
6287 * \return a new group with newly created elements
6288 * \sa DoubleNodeElemGroups()
6290 //================================================================================
6292 SMESH::ListOfGroups*
6293 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6294 const SMESH::ListOfGroups& theNodesNot,
6295 const SMESH::ListOfGroups& theAffectedElems,
6296 CORBA::Boolean theElemGroupNeeded,
6297 CORBA::Boolean theNodeGroupNeeded)
6298 throw (SALOME::SALOME_Exception)
6301 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6302 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6303 aTwoGroups->length( 2 );
6308 SMESHDS_Mesh* aMeshDS = getMeshDS();
6309 TIDSortedElemSet anElems, aNodes, anAffected;
6310 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6311 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6312 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6314 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6316 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6321 // Create group with newly created elements
6322 CORBA::String_var elemGroupName = theElems[0]->GetName();
6323 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6324 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6326 SMESH::long_array_var anIds = GetLastCreatedElems();
6327 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6328 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6329 aNewElemGroup->Add(anIds);
6331 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6333 SMESH::long_array_var anIds = GetLastCreatedNodes();
6334 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6335 aNewNodeGroup->Add(anIds);
6339 // Update Python script
6342 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6343 else pyDump << aNewElemGroup << ", ";
6344 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6345 else pyDump << aNewNodeGroup << " ] = ";
6347 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6348 << &theNodesNot << ", "
6349 << &theAffectedElems << ", "
6350 << theElemGroupNeeded << ", "
6351 << theNodeGroupNeeded << " )";
6353 aTwoGroups[0] = aNewElemGroup._retn();
6354 aTwoGroups[1] = aNewNodeGroup._retn();
6355 return aTwoGroups._retn();
6357 SMESH_CATCH( SMESH::throwCorbaException );
6361 //================================================================================
6363 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6364 This method provided for convenience works as DoubleNodes() described above.
6365 \param theElems - list of groups of elements (edges or faces) to be replicated
6366 \param theNodesNot - list of groups of nodes not to replicated
6367 \param theShape - shape to detect affected elements (element which geometric center
6368 located on or inside shape).
6369 The replicated nodes should be associated to affected elements.
6370 \return TRUE if operation has been completed successfully, FALSE otherwise
6371 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6373 //================================================================================
6376 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6377 const SMESH::ListOfGroups& theNodesNot,
6378 GEOM::GEOM_Object_ptr theShape )
6379 throw (SALOME::SALOME_Exception)
6385 SMESHDS_Mesh* aMeshDS = getMeshDS();
6386 TIDSortedElemSet anElems, aNodes;
6387 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6388 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6390 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6391 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6393 // Update Python script
6394 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6395 << &theNodesNot << ", " << theShape << " )";
6397 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6400 SMESH_CATCH( SMESH::throwCorbaException );
6404 //================================================================================
6406 \brief Identify the elements that will be affected by node duplication (actual
6407 duplication is not performed.
6408 This method is the first step of DoubleNodeElemGroupsInRegion.
6409 \param theElems - list of groups of elements (edges or faces) to be replicated
6410 \param theNodesNot - list of groups of nodes not to replicated
6411 \param theShape - shape to detect affected elements (element which geometric center
6412 located on or inside shape).
6413 The replicated nodes should be associated to affected elements.
6414 \return groups of affected elements
6415 \sa DoubleNodeElemGroupsInRegion()
6417 //================================================================================
6418 SMESH::ListOfGroups*
6419 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6420 const SMESH::ListOfGroups& theNodesNot,
6421 GEOM::GEOM_Object_ptr theShape )
6422 throw (SALOME::SALOME_Exception)
6425 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6426 bool isEdgeGroup = false;
6427 bool isFaceGroup = false;
6428 bool isVolumeGroup = false;
6429 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6430 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6431 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6435 ::SMESH_MeshEditor aMeshEditor(myMesh);
6437 SMESHDS_Mesh* aMeshDS = getMeshDS();
6438 TIDSortedElemSet anElems, aNodes;
6439 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6440 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6442 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6443 TIDSortedElemSet anAffected;
6444 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6447 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6452 int lg = anAffected.size();
6453 SMESH::long_array_var volumeIds = new SMESH::long_array;
6454 volumeIds->length(lg);
6455 SMESH::long_array_var faceIds = new SMESH::long_array;
6456 faceIds->length(lg);
6457 SMESH::long_array_var edgeIds = new SMESH::long_array;
6458 edgeIds->length(lg);
6463 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6464 for (; eIt != anAffected.end(); ++eIt)
6466 const SMDS_MeshElement* anElem = *eIt;
6469 int elemId = anElem->GetID();
6470 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6471 volumeIds[ivol++] = elemId;
6472 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6473 faceIds[iface++] = elemId;
6474 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6475 edgeIds[iedge++] = elemId;
6477 volumeIds->length(ivol);
6478 faceIds->length(iface);
6479 edgeIds->length(iedge);
6481 aNewVolumeGroup->Add(volumeIds);
6482 aNewFaceGroup->Add(faceIds);
6483 aNewEdgeGroup->Add(edgeIds);
6484 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6485 isFaceGroup = (aNewFaceGroup->Size() > 0);
6486 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6490 if (isEdgeGroup) nbGroups++;
6491 if (isFaceGroup) nbGroups++;
6492 if (isVolumeGroup) nbGroups++;
6493 aListOfGroups->length(nbGroups);
6496 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6497 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6498 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6500 // Update Python script
6503 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6504 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6505 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6507 pyDump << this << ".AffectedElemGroupsInRegion( "
6508 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6510 return aListOfGroups._retn();
6512 SMESH_CATCH( SMESH::throwCorbaException );
6516 //================================================================================
6518 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6519 The created 2D mesh elements based on nodes of free faces of boundary volumes
6520 \return TRUE if operation has been completed successfully, FALSE otherwise
6522 //================================================================================
6524 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6525 throw (SALOME::SALOME_Exception)
6530 bool aResult = getEditor().Make2DMeshFrom3D();
6532 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6534 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6537 SMESH_CATCH( SMESH::throwCorbaException );
6541 //================================================================================
6543 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6544 * The list of groups must contain at least two groups. The groups have to be disjoint:
6545 * no common element into two different groups.
6546 * The nodes of the internal faces at the boundaries of the groups are doubled.
6547 * Optionally, the internal faces are replaced by flat elements.
6548 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6549 * The flat elements are stored in groups of volumes.
6550 * These groups are named according to the position of the group in the list:
6551 * 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.
6552 * 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.
6553 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6554 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6555 * \param theDomains - list of groups of volumes
6556 * \param createJointElems - if TRUE, create the elements
6557 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6558 * the boundary between \a theDomains and the rest mesh
6559 * \return TRUE if operation has been completed successfully, FALSE otherwise
6561 //================================================================================
6564 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6565 CORBA::Boolean createJointElems,
6566 CORBA::Boolean onAllBoundaries )
6567 throw (SALOME::SALOME_Exception)
6574 SMESHDS_Mesh* aMeshDS = getMeshDS();
6576 // MESSAGE("theDomains.length = "<<theDomains.length());
6577 if ( theDomains.length() <= 1 && !onAllBoundaries )
6578 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6580 vector<TIDSortedElemSet> domains;
6581 domains.resize( theDomains.length() );
6583 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6585 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6586 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6588 // if ( aGrp->GetType() != SMESH::VOLUME )
6589 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6590 SMESH::long_array_var anIDs = aGrp->GetIDs();
6591 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6595 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6596 // TODO publish the groups of flat elements in study
6598 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6600 // Update Python script
6601 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6602 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6604 SMESH_CATCH( SMESH::throwCorbaException );
6606 myMesh_i->CreateGroupServants(); // publish created groups if any
6611 //================================================================================
6613 * \brief Double nodes on some external faces and create flat elements.
6614 * Flat elements are mainly used by some types of mechanic calculations.
6616 * Each group of the list must be constituted of faces.
6617 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6618 * @param theGroupsOfFaces - list of groups of faces
6619 * @return TRUE if operation has been completed successfully, FALSE otherwise
6621 //================================================================================
6624 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6625 throw (SALOME::SALOME_Exception)
6630 SMESHDS_Mesh* aMeshDS = getMeshDS();
6632 vector<TIDSortedElemSet> faceGroups;
6635 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6637 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6638 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6640 TIDSortedElemSet faceGroup;
6642 faceGroups.push_back(faceGroup);
6643 SMESH::long_array_var anIDs = aGrp->GetIDs();
6644 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6648 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6649 // TODO publish the groups of flat elements in study
6651 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6653 // Update Python script
6654 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6657 SMESH_CATCH( SMESH::throwCorbaException );
6661 //================================================================================
6663 * \brief Identify all the elements around a geom shape, get the faces delimiting
6666 * Build groups of volume to remove, groups of faces to replace on the skin of the
6667 * object, groups of faces to remove inside the object, (idem edges).
6668 * Build ordered list of nodes at the border of each group of faces to replace
6669 * (to be used to build a geom subshape).
6671 //================================================================================
6673 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6674 GEOM::GEOM_Object_ptr theShape,
6675 const char* groupName,
6676 const SMESH::double_array& theNodesCoords,
6677 SMESH::array_of_long_array_out GroupsOfNodes)
6678 throw (SALOME::SALOME_Exception)
6683 std::vector<std::vector<int> > aListOfListOfNodes;
6684 ::SMESH_MeshEditor aMeshEditor( myMesh );
6686 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6687 if ( !theNodeSearcher )
6688 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6690 vector<double> nodesCoords;
6691 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6693 nodesCoords.push_back( theNodesCoords[i] );
6696 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6697 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6698 nodesCoords, aListOfListOfNodes);
6700 GroupsOfNodes = new SMESH::array_of_long_array;
6701 GroupsOfNodes->length( aListOfListOfNodes.size() );
6702 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6703 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6705 vector<int>& aListOfNodes = *llIt;
6706 vector<int>::iterator lIt = aListOfNodes.begin();;
6707 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6708 aGroup.length( aListOfNodes.size() );
6709 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6710 aGroup[ j ] = (*lIt);
6712 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6715 << ", '" << groupName << "', "
6716 << theNodesCoords << " )";
6718 SMESH_CATCH( SMESH::throwCorbaException );
6721 // issue 20749 ===================================================================
6723 * \brief Creates missing boundary elements
6724 * \param elements - elements whose boundary is to be checked
6725 * \param dimension - defines type of boundary elements to create
6726 * \param groupName - a name of group to store created boundary elements in,
6727 * "" means not to create the group
6728 * \param meshName - a name of new mesh to store created boundary elements in,
6729 * "" means not to create the new mesh
6730 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6731 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6732 * boundary elements will be copied into the new mesh
6733 * \param group - returns the create group, if any
6734 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6736 // ================================================================================
6738 SMESH::SMESH_Mesh_ptr
6739 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6740 SMESH::Bnd_Dimension dim,
6741 const char* groupName,
6742 const char* meshName,
6743 CORBA::Boolean toCopyElements,
6744 CORBA::Boolean toCopyExistingBondary,
6745 SMESH::SMESH_Group_out group)
6746 throw (SALOME::SALOME_Exception)
6751 if ( dim > SMESH::BND_1DFROM2D )
6752 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6754 SMESHDS_Mesh* aMeshDS = getMeshDS();
6756 SMESH::SMESH_Mesh_var mesh_var;
6757 SMESH::SMESH_Group_var group_var;
6761 TIDSortedElemSet elements;
6762 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6763 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6767 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6768 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6770 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6772 // group of new boundary elements
6773 SMESH_Group* smesh_group = 0;
6774 if ( strlen(groupName) )
6776 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6777 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6778 smesh_group = group_i->GetSmeshGroup();
6782 getEditor().MakeBoundaryMesh( elements,
6783 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6787 toCopyExistingBondary);
6790 smesh_mesh->GetMeshDS()->Modified();
6793 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6795 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6796 if ( mesh_var->_is_nil() )
6797 pyDump << myMesh_i->_this() << ", ";
6799 pyDump << mesh_var << ", ";
6800 if ( group_var->_is_nil() )
6801 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6803 pyDump << group_var << " = ";
6804 pyDump << this << ".MakeBoundaryMesh( "
6806 << "SMESH." << dimName[int(dim)] << ", "
6807 << "'" << groupName << "', "
6808 << "'" << meshName<< "', "
6809 << toCopyElements << ", "
6810 << toCopyExistingBondary << ")";
6812 group = group_var._retn();
6813 return mesh_var._retn();
6815 SMESH_CATCH( SMESH::throwCorbaException );
6816 return SMESH::SMESH_Mesh::_nil();
6819 //================================================================================
6821 * \brief Creates missing boundary elements
6822 * \param dimension - defines type of boundary elements to create
6823 * \param groupName - a name of group to store all boundary elements in,
6824 * "" means not to create the group
6825 * \param meshName - a name of a new mesh, which is a copy of the initial
6826 * mesh + created boundary elements; "" means not to create the new mesh
6827 * \param toCopyAll - if true, the whole initial mesh will be copied into
6828 * the new mesh else only boundary elements will be copied into the new mesh
6829 * \param groups - optional groups of elements to make boundary around
6830 * \param mesh - returns the mesh where elements were added to
6831 * \param group - returns the created group, if any
6832 * \retval long - number of added boundary elements
6834 //================================================================================
6836 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6837 const char* groupName,
6838 const char* meshName,
6839 CORBA::Boolean toCopyAll,
6840 const SMESH::ListOfIDSources& groups,
6841 SMESH::SMESH_Mesh_out mesh,
6842 SMESH::SMESH_Group_out group)
6843 throw (SALOME::SALOME_Exception)
6848 if ( dim > SMESH::BND_1DFROM2D )
6849 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6851 // separate groups belonging to this and other mesh
6852 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6853 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6854 groupsOfThisMesh ->length( groups.length() );
6855 groupsOfOtherMesh->length( groups.length() );
6856 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6857 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6859 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6860 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6861 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6863 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6864 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6865 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6867 groupsOfThisMesh->length( nbGroups );
6868 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6873 if ( nbGroupsOfOtherMesh > 0 )
6875 // process groups belonging to another mesh
6876 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6877 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6878 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6879 groupsOfOtherMesh, mesh, group );
6882 SMESH::SMESH_Mesh_var mesh_var;
6883 SMESH::SMESH_Group_var group_var;
6886 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6887 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6891 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6893 /*toCopyGroups=*/false,
6894 /*toKeepIDs=*/true);
6896 mesh_var = makeMesh(meshName);
6898 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6899 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6902 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6903 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6905 // group of boundary elements
6906 SMESH_Group* smesh_group = 0;
6907 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6908 if ( strlen(groupName) )
6910 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6911 group_var = mesh_i->CreateGroup( groupType, groupName );
6912 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6913 smesh_group = group_i->GetSmeshGroup();
6916 TIDSortedElemSet elements;
6918 if ( groups.length() > 0 )
6920 for ( int i = 0; i < nbGroups; ++i )
6923 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6925 SMESH::Bnd_Dimension bdim =
6926 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6927 nbAdded += getEditor().MakeBoundaryMesh( elements,
6928 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6931 /*toCopyElements=*/false,
6932 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6933 /*toAddExistingBondary=*/true,
6934 /*aroundElements=*/true);
6940 nbAdded += getEditor().MakeBoundaryMesh( elements,
6941 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6944 /*toCopyElements=*/false,
6945 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6946 /*toAddExistingBondary=*/true);
6948 tgtMesh->GetMeshDS()->Modified();
6950 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6952 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6953 pyDump << "nbAdded, ";
6954 if ( mesh_var->_is_nil() )
6955 pyDump << myMesh_i->_this() << ", ";
6957 pyDump << mesh_var << ", ";
6958 if ( group_var->_is_nil() )
6959 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6961 pyDump << group_var << " = ";
6962 pyDump << this << ".MakeBoundaryElements( "
6963 << "SMESH." << dimName[int(dim)] << ", "
6964 << "'" << groupName << "', "
6965 << "'" << meshName<< "', "
6966 << toCopyAll << ", "
6969 mesh = mesh_var._retn();
6970 group = group_var._retn();
6973 SMESH_CATCH( SMESH::throwCorbaException );