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 27: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],
1156 n[15],n[16],n[17],n[18],n[19],
1157 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1161 // Update Python script
1162 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1164 declareMeshModified( /*isReComputeSafe=*/false );
1165 return elem ? elem->GetID() : 0;
1167 SMESH_CATCH( SMESH::throwCorbaException );
1171 //=============================================================================
1173 * AddPolyhedralVolume
1175 //=============================================================================
1176 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1177 const SMESH::long_array & Quantities)
1178 throw (SALOME::SALOME_Exception)
1183 int NbNodes = IDsOfNodes.length();
1184 std::vector<const SMDS_MeshNode*> n (NbNodes);
1185 for (int i = 0; i < NbNodes; i++)
1187 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1188 if (!aNode) return 0;
1192 int NbFaces = Quantities.length();
1193 std::vector<int> q (NbFaces);
1194 for (int j = 0; j < NbFaces; j++)
1195 q[j] = Quantities[j];
1197 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1199 // Update Python script
1200 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1201 << IDsOfNodes << ", " << Quantities << " )";
1203 declareMeshModified( /*isReComputeSafe=*/false );
1204 return elem ? elem->GetID() : 0;
1206 SMESH_CATCH( SMESH::throwCorbaException );
1210 //=============================================================================
1212 * AddPolyhedralVolumeByFaces
1214 //=============================================================================
1216 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1217 throw (SALOME::SALOME_Exception)
1222 int NbFaces = IdsOfFaces.length();
1223 std::vector<const SMDS_MeshNode*> poly_nodes;
1224 std::vector<int> quantities (NbFaces);
1226 for (int i = 0; i < NbFaces; i++) {
1227 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1228 quantities[i] = aFace->NbNodes();
1230 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1231 while (It->more()) {
1232 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1236 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1238 // Update Python script
1239 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1240 << IdsOfFaces << " )";
1242 declareMeshModified( /*isReComputeSafe=*/false );
1243 return elem ? elem->GetID() : 0;
1245 SMESH_CATCH( SMESH::throwCorbaException );
1249 //=============================================================================
1251 // \brief Create 0D elements on all nodes of the given object.
1252 // \param theObject object on whose nodes 0D elements will be created.
1253 // \param theGroupName optional name of a group to add 0D elements created
1254 // and/or found on nodes of \a theObject.
1255 // \param DuplicateElements to add one more 0D element to a node or not.
1256 // \return an object (a new group or a temporary SMESH_IDSource) holding
1257 // ids of new and/or found 0D elements.
1259 //=============================================================================
1261 SMESH::SMESH_IDSource_ptr
1262 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1263 const char* theGroupName,
1264 CORBA::Boolean theDuplicateElements)
1265 throw (SALOME::SALOME_Exception)
1270 SMESH::SMESH_IDSource_var result;
1273 TIDSortedElemSet elements, elems0D;
1274 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1275 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1277 SMESH::long_array_var newElems = new SMESH::long_array;
1278 newElems->length( elems0D.size() );
1279 TIDSortedElemSet::iterator eIt = elems0D.begin();
1280 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1281 newElems[ i ] = (*eIt)->GetID();
1283 SMESH::SMESH_GroupBase_var groupToFill;
1284 if ( theGroupName && strlen( theGroupName ))
1286 // Get existing group named theGroupName
1287 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1288 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1289 SMESH::SMESH_GroupBase_var group = groups[i];
1290 if ( !group->_is_nil() ) {
1291 CORBA::String_var name = group->GetName();
1292 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1293 groupToFill = group;
1298 if ( groupToFill->_is_nil() )
1299 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1300 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1301 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1304 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1306 group_i->Add( newElems );
1307 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1308 pyDump << groupToFill;
1312 result = MakeIDSource( newElems, SMESH::ELEM0D );
1313 pyDump << "elem0DIDs";
1316 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1317 << theObject << ", '" << theGroupName << "' )";
1319 return result._retn();
1321 SMESH_CATCH( SMESH::throwCorbaException );
1325 //=============================================================================
1327 * \brief Bind a node to a vertex
1328 * \param NodeID - node ID
1329 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1330 * \retval boolean - false if NodeID or VertexID is invalid
1332 //=============================================================================
1334 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1335 throw (SALOME::SALOME_Exception)
1339 SMESHDS_Mesh * mesh = getMeshDS();
1340 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1342 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1344 if ( mesh->MaxShapeIndex() < VertexID )
1345 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1347 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1348 if ( shape.ShapeType() != TopAbs_VERTEX )
1349 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1351 mesh->SetNodeOnVertex( node, VertexID );
1353 myMesh->SetIsModified( true );
1355 SMESH_CATCH( SMESH::throwCorbaException );
1358 //=============================================================================
1360 * \brief Store node position on an edge
1361 * \param NodeID - node ID
1362 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1363 * \param paramOnEdge - parameter on edge where the node is located
1364 * \retval boolean - false if any parameter is invalid
1366 //=============================================================================
1368 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1369 CORBA::Double paramOnEdge)
1370 throw (SALOME::SALOME_Exception)
1374 SMESHDS_Mesh * mesh = getMeshDS();
1375 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1377 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1379 if ( mesh->MaxShapeIndex() < EdgeID )
1380 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1382 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1383 if ( shape.ShapeType() != TopAbs_EDGE )
1384 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1387 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1388 if ( paramOnEdge < f || paramOnEdge > l )
1389 THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1391 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1393 myMesh->SetIsModified( true );
1395 SMESH_CATCH( SMESH::throwCorbaException );
1398 //=============================================================================
1400 * \brief Store node position on a face
1401 * \param NodeID - node ID
1402 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1403 * \param u - U parameter on face where the node is located
1404 * \param v - V parameter on face where the node is located
1405 * \retval boolean - false if any parameter is invalid
1407 //=============================================================================
1409 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1410 CORBA::Double u, CORBA::Double v)
1411 throw (SALOME::SALOME_Exception)
1414 SMESHDS_Mesh * mesh = getMeshDS();
1415 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1417 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1419 if ( mesh->MaxShapeIndex() < FaceID )
1420 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1422 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1423 if ( shape.ShapeType() != TopAbs_FACE )
1424 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1426 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1427 bool isOut = ( u < surf.FirstUParameter() ||
1428 u > surf.LastUParameter() ||
1429 v < surf.FirstVParameter() ||
1430 v > surf.LastVParameter() );
1434 MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1435 << " u( " << surf.FirstUParameter()
1436 << "," << surf.LastUParameter()
1437 << ") v( " << surf.FirstVParameter()
1438 << "," << surf.LastVParameter() << ")" );
1440 THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1443 mesh->SetNodeOnFace( node, FaceID, u, v );
1444 myMesh->SetIsModified( true );
1446 SMESH_CATCH( SMESH::throwCorbaException );
1449 //=============================================================================
1451 * \brief Bind a node to a solid
1452 * \param NodeID - node ID
1453 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1454 * \retval boolean - false if NodeID or SolidID is invalid
1456 //=============================================================================
1458 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1459 throw (SALOME::SALOME_Exception)
1462 SMESHDS_Mesh * mesh = getMeshDS();
1463 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1465 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1467 if ( mesh->MaxShapeIndex() < SolidID )
1468 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1470 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1471 if ( shape.ShapeType() != TopAbs_SOLID &&
1472 shape.ShapeType() != TopAbs_SHELL)
1473 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1475 mesh->SetNodeInVolume( node, SolidID );
1477 SMESH_CATCH( SMESH::throwCorbaException );
1480 //=============================================================================
1482 * \brief Bind an element to a shape
1483 * \param ElementID - element ID
1484 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1486 //=============================================================================
1488 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1489 CORBA::Long ShapeID)
1490 throw (SALOME::SALOME_Exception)
1493 SMESHDS_Mesh * mesh = getMeshDS();
1494 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1496 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1498 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1499 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1501 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1502 if ( shape.ShapeType() != TopAbs_EDGE &&
1503 shape.ShapeType() != TopAbs_FACE &&
1504 shape.ShapeType() != TopAbs_SOLID &&
1505 shape.ShapeType() != TopAbs_SHELL )
1506 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1508 mesh->SetMeshElementOnShape( elem, ShapeID );
1510 myMesh->SetIsModified( true );
1512 SMESH_CATCH( SMESH::throwCorbaException );
1515 //=============================================================================
1519 //=============================================================================
1521 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1522 CORBA::Long NodeID2)
1523 throw (SALOME::SALOME_Exception)
1528 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1529 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1533 // Update Python script
1534 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1535 << NodeID1 << ", " << NodeID2 << " )";
1537 int ret = getEditor().InverseDiag ( n1, n2 );
1539 declareMeshModified( /*isReComputeSafe=*/false );
1542 SMESH_CATCH( SMESH::throwCorbaException );
1546 //=============================================================================
1550 //=============================================================================
1552 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1553 CORBA::Long NodeID2)
1554 throw (SALOME::SALOME_Exception)
1559 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1560 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1564 // Update Python script
1565 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1566 << NodeID1 << ", " << NodeID2 << " )";
1569 bool stat = getEditor().DeleteDiag ( n1, n2 );
1571 declareMeshModified( /*isReComputeSafe=*/!stat );
1575 SMESH_CATCH( SMESH::throwCorbaException );
1579 //=============================================================================
1583 //=============================================================================
1585 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1586 throw (SALOME::SALOME_Exception)
1591 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1593 CORBA::Long index = IDsOfElements[i];
1594 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1596 getEditor().Reorient( elem );
1598 // Update Python script
1599 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1601 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1604 SMESH_CATCH( SMESH::throwCorbaException );
1608 //=============================================================================
1612 //=============================================================================
1614 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1615 throw (SALOME::SALOME_Exception)
1620 TPythonDump aTPythonDump; // suppress dump in Reorient()
1622 prepareIdSource( theObject );
1624 SMESH::long_array_var anElementsId = theObject->GetIDs();
1625 CORBA::Boolean isDone = Reorient(anElementsId);
1627 // Update Python script
1628 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1630 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1633 SMESH_CATCH( SMESH::throwCorbaException );
1637 //=======================================================================
1638 //function : Reorient2D
1639 //purpose : Reorient faces contained in \a the2Dgroup.
1640 // the2Dgroup - the mesh or its part to reorient
1641 // theDirection - desired direction of normal of \a theFace
1642 // theFace - ID of face whose orientation is checked.
1643 // It can be < 1 then \a thePoint is used to find a face.
1644 // thePoint - is used to find a face if \a theFace < 1.
1645 // return number of reoriented elements.
1646 //=======================================================================
1648 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1649 const SMESH::DirStruct& theDirection,
1650 CORBA::Long theFace,
1651 const SMESH::PointStruct& thePoint)
1652 throw (SALOME::SALOME_Exception)
1655 initData(/*deleteSearchers=*/false);
1657 TIDSortedElemSet elements;
1658 IDSource_Error error;
1659 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1660 if ( error == IDSource_EMPTY )
1662 if ( error == IDSource_INVALID )
1663 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1666 const SMDS_MeshElement* face = 0;
1669 face = getMeshDS()->FindElement( theFace );
1671 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1672 if ( face->GetType() != SMDSAbs_Face )
1673 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1677 // create theElementSearcher if needed
1678 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1679 if ( !theElementSearcher )
1681 if ( elements.empty() ) // search in the whole mesh
1683 if ( myMesh->NbFaces() == 0 )
1684 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1686 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1690 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1691 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1693 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1697 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1698 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1701 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1702 if ( !elements.empty() && !elements.count( face ))
1703 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1706 const SMESH::PointStruct * P = &theDirection.PS;
1707 gp_Vec dirVec( P->x, P->y, P->z );
1708 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1709 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1711 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1714 declareMeshModified( /*isReComputeSafe=*/false );
1716 TPythonDump() << this << ".Reorient2D( "
1717 << the2Dgroup << ", "
1718 << theDirection << ", "
1720 << thePoint << " )";
1724 SMESH_CATCH( SMESH::throwCorbaException );
1728 //=======================================================================
1729 //function : Reorient2DBy3D
1730 //purpose : Reorient faces basing on orientation of adjacent volumes.
1731 //=======================================================================
1733 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1734 SMESH::SMESH_IDSource_ptr volumeGroup,
1735 CORBA::Boolean outsideNormal)
1736 throw (SALOME::SALOME_Exception)
1741 TIDSortedElemSet volumes;
1742 IDSource_Error volsError;
1743 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1746 for ( size_t i = 0; i < faceGroups.length(); ++i )
1748 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1750 TIDSortedElemSet faces;
1751 IDSource_Error error;
1752 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1753 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1754 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1755 if ( error == IDSource_OK && volsError != IDSource_OK )
1756 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1758 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1760 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1765 declareMeshModified( /*isReComputeSafe=*/false );
1767 TPythonDump() << this << ".Reorient2DBy3D( "
1768 << faceGroups << ", "
1769 << volumeGroup << ", "
1770 << outsideNormal << " )";
1774 SMESH_CATCH( SMESH::throwCorbaException );
1778 //=============================================================================
1780 * \brief Fuse neighbour triangles into quadrangles.
1782 //=============================================================================
1784 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1785 SMESH::NumericalFunctor_ptr Criterion,
1786 CORBA::Double MaxAngle)
1787 throw (SALOME::SALOME_Exception)
1792 SMESHDS_Mesh* aMesh = getMeshDS();
1793 TIDSortedElemSet faces,copyFaces;
1794 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1795 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1796 TIDSortedElemSet* workElements = & faces;
1798 if ( myIsPreviewMode ) {
1799 SMDSAbs_ElementType select = SMDSAbs_Face;
1800 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1801 workElements = & copyFaces;
1804 SMESH::NumericalFunctor_i* aNumericalFunctor =
1805 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1806 SMESH::Controls::NumericalFunctorPtr aCrit;
1807 if ( !aNumericalFunctor )
1808 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1810 aCrit = aNumericalFunctor->GetNumericalFunctor();
1812 if ( !myIsPreviewMode ) {
1813 // Update Python script
1814 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1815 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1818 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1820 declareMeshModified( /*isReComputeSafe=*/!stat );
1823 SMESH_CATCH( SMESH::throwCorbaException );
1827 //=============================================================================
1829 * \brief Fuse neighbour triangles into quadrangles.
1831 //=============================================================================
1833 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1834 SMESH::NumericalFunctor_ptr Criterion,
1835 CORBA::Double MaxAngle)
1836 throw (SALOME::SALOME_Exception)
1841 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1843 prepareIdSource( theObject );
1844 SMESH::long_array_var anElementsId = theObject->GetIDs();
1845 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1847 if ( !myIsPreviewMode ) {
1848 SMESH::NumericalFunctor_i* aNumericalFunctor =
1849 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1851 // Update Python script
1852 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1853 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1858 SMESH_CATCH( SMESH::throwCorbaException );
1862 //=============================================================================
1864 * \brief Split quadrangles into triangles.
1866 //=============================================================================
1868 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1869 SMESH::NumericalFunctor_ptr Criterion)
1870 throw (SALOME::SALOME_Exception)
1875 SMESHDS_Mesh* aMesh = getMeshDS();
1876 TIDSortedElemSet faces;
1877 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1879 SMESH::NumericalFunctor_i* aNumericalFunctor =
1880 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1881 SMESH::Controls::NumericalFunctorPtr aCrit;
1882 if ( !aNumericalFunctor )
1883 aCrit.reset( new SMESH::Controls::AspectRatio() );
1885 aCrit = aNumericalFunctor->GetNumericalFunctor();
1888 // Update Python script
1889 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1891 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1893 declareMeshModified( /*isReComputeSafe=*/false );
1896 SMESH_CATCH( SMESH::throwCorbaException );
1900 //=============================================================================
1902 * \brief Split quadrangles into triangles.
1904 //=============================================================================
1906 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1907 SMESH::NumericalFunctor_ptr Criterion)
1908 throw (SALOME::SALOME_Exception)
1913 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1915 prepareIdSource( theObject );
1916 SMESH::long_array_var anElementsId = theObject->GetIDs();
1917 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1919 SMESH::NumericalFunctor_i* aNumericalFunctor =
1920 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1922 // Update Python script
1923 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1925 declareMeshModified( /*isReComputeSafe=*/false );
1928 SMESH_CATCH( SMESH::throwCorbaException );
1932 //================================================================================
1934 * \brief Split each of quadrangles into 4 triangles.
1935 * \param [in] theObject - theQuads Container of quadrangles to split.
1937 //================================================================================
1939 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1940 throw (SALOME::SALOME_Exception)
1945 TIDSortedElemSet faces;
1946 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1948 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1950 getEditor().QuadTo4Tri( faces );
1951 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1953 SMESH_CATCH( SMESH::throwCorbaException );
1956 //=============================================================================
1958 * \brief Split quadrangles into triangles.
1960 //=============================================================================
1962 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1963 CORBA::Boolean Diag13)
1964 throw (SALOME::SALOME_Exception)
1969 SMESHDS_Mesh* aMesh = getMeshDS();
1970 TIDSortedElemSet faces;
1971 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1973 // Update Python script
1974 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1975 << IDsOfElements << ", " << Diag13 << " )";
1977 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1979 declareMeshModified( /*isReComputeSafe=*/ !stat );
1982 SMESH_CATCH( SMESH::throwCorbaException );
1986 //=============================================================================
1988 * \brief Split quadrangles into triangles.
1990 //=============================================================================
1992 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1993 CORBA::Boolean Diag13)
1994 throw (SALOME::SALOME_Exception)
1999 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2001 prepareIdSource( theObject );
2002 SMESH::long_array_var anElementsId = theObject->GetIDs();
2003 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2005 // Update Python script
2006 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2007 << theObject << ", " << Diag13 << " )";
2009 declareMeshModified( /*isReComputeSafe=*/!isDone );
2012 SMESH_CATCH( SMESH::throwCorbaException );
2017 //=============================================================================
2019 * Find better splitting of the given quadrangle.
2020 * \param IDOfQuad ID of the quadrangle to be splitted.
2021 * \param Criterion A criterion to choose a diagonal for splitting.
2022 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2023 * diagonal is better, 0 if error occurs.
2025 //=============================================================================
2027 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2028 SMESH::NumericalFunctor_ptr Criterion)
2029 throw (SALOME::SALOME_Exception)
2034 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2035 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2037 SMESH::NumericalFunctor_i* aNumericalFunctor =
2038 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2039 SMESH::Controls::NumericalFunctorPtr aCrit;
2040 if (aNumericalFunctor)
2041 aCrit = aNumericalFunctor->GetNumericalFunctor();
2043 aCrit.reset(new SMESH::Controls::AspectRatio());
2045 int id = getEditor().BestSplit(quad, aCrit);
2046 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2050 SMESH_CATCH( SMESH::throwCorbaException );
2054 //================================================================================
2056 * \brief Split volumic elements into tetrahedrons
2058 //================================================================================
2060 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2061 CORBA::Short methodFlags)
2062 throw (SALOME::SALOME_Exception)
2067 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2068 const int noneFacet = -1;
2069 SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2070 while( volIt->more() )
2071 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2073 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2074 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2076 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2077 << elems << ", " << methodFlags << " )";
2079 SMESH_CATCH( SMESH::throwCorbaException );
2082 //================================================================================
2084 * \brief Split hexahedra into triangular prisms
2085 * \param elems - elements to split
2086 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2087 * to split into triangles
2088 * \param methodFlags - flags passing splitting method:
2089 * 1 - split the hexahedron into 2 prisms
2090 * 2 - split the hexahedron into 4 prisms
2092 //================================================================================
2094 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2095 const SMESH::PointStruct & startHexPoint,
2096 const SMESH::DirStruct& facetToSplitNormal,
2097 CORBA::Short methodFlags,
2098 CORBA::Boolean allDomains)
2099 throw (SALOME::SALOME_Exception)
2103 prepareIdSource( elems );
2105 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2108 gp_Dir( facetToSplitNormal.PS.x,
2109 facetToSplitNormal.PS.y,
2110 facetToSplitNormal.PS.z ));
2111 TIDSortedElemSet elemSet;
2112 SMESH::long_array_var anElementsId = elems->GetIDs();
2113 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2114 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2116 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2117 while ( !elemSet.empty() )
2119 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2123 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2124 for ( ; ef != elemFacets.end(); ++ef )
2125 elemSet.erase( ef->first );
2128 if ( methodFlags == 2 )
2129 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2131 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2133 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2134 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2136 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2138 << startHexPoint << ", "
2139 << facetToSplitNormal<< ", "
2140 << methodFlags<< ", "
2141 << allDomains << " )";
2143 SMESH_CATCH( SMESH::throwCorbaException );
2146 //================================================================================
2148 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2149 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2150 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2151 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2152 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2153 * will be split in order to keep the mesh conformal.
2154 * \param elems - elements to split
2156 //================================================================================
2158 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2159 throw (SALOME::SALOME_Exception)
2164 TIDSortedElemSet elemSet;
2165 for ( size_t i = 0; i < theElems.length(); ++i )
2167 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2168 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2169 if ( mesh->GetId() != myMesh_i->GetId() )
2170 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2172 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2174 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2176 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2178 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2179 << theElems << " )";
2181 SMESH_CATCH( SMESH::throwCorbaException );
2184 //=======================================================================
2187 //=======================================================================
2190 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2191 const SMESH::long_array & IDsOfFixedNodes,
2192 CORBA::Long MaxNbOfIterations,
2193 CORBA::Double MaxAspectRatio,
2194 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2195 throw (SALOME::SALOME_Exception)
2197 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2198 MaxAspectRatio, Method, false );
2202 //=======================================================================
2203 //function : SmoothParametric
2205 //=======================================================================
2208 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2209 const SMESH::long_array & IDsOfFixedNodes,
2210 CORBA::Long MaxNbOfIterations,
2211 CORBA::Double MaxAspectRatio,
2212 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2213 throw (SALOME::SALOME_Exception)
2215 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2216 MaxAspectRatio, Method, true );
2220 //=======================================================================
2221 //function : SmoothObject
2223 //=======================================================================
2226 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2227 const SMESH::long_array & IDsOfFixedNodes,
2228 CORBA::Long MaxNbOfIterations,
2229 CORBA::Double MaxAspectRatio,
2230 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2231 throw (SALOME::SALOME_Exception)
2233 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2234 MaxAspectRatio, Method, false);
2238 //=======================================================================
2239 //function : SmoothParametricObject
2241 //=======================================================================
2244 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2245 const SMESH::long_array & IDsOfFixedNodes,
2246 CORBA::Long MaxNbOfIterations,
2247 CORBA::Double MaxAspectRatio,
2248 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2249 throw (SALOME::SALOME_Exception)
2251 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2252 MaxAspectRatio, Method, true);
2256 //=============================================================================
2260 //=============================================================================
2263 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2264 const SMESH::long_array & IDsOfFixedNodes,
2265 CORBA::Long MaxNbOfIterations,
2266 CORBA::Double MaxAspectRatio,
2267 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2269 throw (SALOME::SALOME_Exception)
2274 SMESHDS_Mesh* aMesh = getMeshDS();
2276 TIDSortedElemSet elements;
2277 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2279 set<const SMDS_MeshNode*> fixedNodes;
2280 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2281 CORBA::Long index = IDsOfFixedNodes[i];
2282 const SMDS_MeshNode * node = aMesh->FindNode(index);
2284 fixedNodes.insert( node );
2286 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2287 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2288 method = ::SMESH_MeshEditor::CENTROIDAL;
2290 getEditor().Smooth(elements, fixedNodes, method,
2291 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2293 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2295 // Update Python script
2296 TPythonDump() << "isDone = " << this << "."
2297 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2298 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2299 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2300 << "SMESH.SMESH_MeshEditor."
2301 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2302 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2306 SMESH_CATCH( SMESH::throwCorbaException );
2310 //=============================================================================
2314 //=============================================================================
2317 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2318 const SMESH::long_array & IDsOfFixedNodes,
2319 CORBA::Long MaxNbOfIterations,
2320 CORBA::Double MaxAspectRatio,
2321 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2323 throw (SALOME::SALOME_Exception)
2328 TPythonDump aTPythonDump; // suppress dump in smooth()
2330 prepareIdSource( theObject );
2331 SMESH::long_array_var anElementsId = theObject->GetIDs();
2332 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2333 MaxAspectRatio, Method, IsParametric);
2335 // Update Python script
2336 aTPythonDump << "isDone = " << this << "."
2337 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2338 << theObject << ", " << IDsOfFixedNodes << ", "
2339 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2340 << "SMESH.SMESH_MeshEditor."
2341 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2342 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2346 SMESH_CATCH( SMESH::throwCorbaException );
2350 //=============================================================================
2354 //=============================================================================
2356 void SMESH_MeshEditor_i::RenumberNodes()
2357 throw (SALOME::SALOME_Exception)
2360 // Update Python script
2361 TPythonDump() << this << ".RenumberNodes()";
2363 getMeshDS()->Renumber( true );
2365 SMESH_CATCH( SMESH::throwCorbaException );
2368 //=============================================================================
2372 //=============================================================================
2374 void SMESH_MeshEditor_i::RenumberElements()
2375 throw (SALOME::SALOME_Exception)
2378 // Update Python script
2379 TPythonDump() << this << ".RenumberElements()";
2381 getMeshDS()->Renumber( false );
2383 SMESH_CATCH( SMESH::throwCorbaException );
2386 //=======================================================================
2388 * \brief Return groups by their IDs
2390 //=======================================================================
2392 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2393 throw (SALOME::SALOME_Exception)
2398 myMesh_i->CreateGroupServants();
2399 return myMesh_i->GetGroups( *groupIDs );
2401 SMESH_CATCH( SMESH::throwCorbaException );
2405 //=======================================================================
2406 //function : RotationSweepObjects
2408 //=======================================================================
2410 SMESH::ListOfGroups*
2411 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2412 const SMESH::ListOfIDSources & theEdges,
2413 const SMESH::ListOfIDSources & theFaces,
2414 const SMESH::AxisStruct & theAxis,
2415 CORBA::Double theAngleInRadians,
2416 CORBA::Long theNbOfSteps,
2417 CORBA::Double theTolerance,
2418 const bool theMakeGroups)
2419 throw (SALOME::SALOME_Exception)
2424 TIDSortedElemSet elemsNodes[2];
2425 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2426 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2427 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2429 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2430 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2431 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2432 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2434 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2435 bool makeWalls=true;
2436 if ( myIsPreviewMode )
2438 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2439 TPreviewMesh * tmpMesh = getPreviewMesh();
2440 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2441 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2442 workElements = & copyElements[0];
2443 //makeWalls = false; -- faces are needed for preview
2446 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2448 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2449 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2451 ::SMESH_MeshEditor::PGroupIDs groupIds =
2452 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2453 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2455 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2457 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2459 if ( !myIsPreviewMode )
2461 dumpGroupsList( aPythonDump, aGroups );
2462 aPythonDump << this<< ".RotationSweepObjects( "
2467 << TVar( theAngleInRadians ) << ", "
2468 << TVar( theNbOfSteps ) << ", "
2469 << TVar( theTolerance ) << ", "
2470 << theMakeGroups << " )";
2474 getPreviewMesh()->Remove( SMDSAbs_Volume );
2477 return aGroups ? aGroups : new SMESH::ListOfGroups;
2479 SMESH_CATCH( SMESH::throwCorbaException );
2483 namespace MeshEditor_I
2486 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2488 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2490 bool myIsExtrusionByNormal;
2492 static int makeFlags( CORBA::Boolean MakeGroups,
2493 CORBA::Boolean LinearVariation = false,
2494 CORBA::Boolean ByAverageNormal = false,
2495 CORBA::Boolean UseInputElemsOnly = false,
2496 CORBA::Long Flags = 0,
2497 CORBA::Boolean MakeBoundary = true )
2499 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2500 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2501 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2502 if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2503 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2507 ExtrusionParams(const SMESH::DirStruct & theDir,
2508 CORBA::Long theNbOfSteps,
2509 const SMESH::double_array & theScaleFactors,
2510 CORBA::Boolean theLinearVariation,
2511 const SMESH::double_array & theBasePoint,
2512 CORBA::Boolean theMakeGroups):
2513 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2517 toList( theScaleFactors ),
2518 TBasePoint( theBasePoint ),
2519 makeFlags( theMakeGroups, theLinearVariation )),
2520 myIsExtrusionByNormal( false )
2524 ExtrusionParams(const SMESH::DirStruct & theDir,
2525 CORBA::Long theNbOfSteps,
2526 CORBA::Boolean theMakeGroups,
2527 CORBA::Long theExtrFlags,
2528 CORBA::Double theSewTolerance):
2529 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2533 std::list<double>(),
2535 makeFlags( theMakeGroups, false, false, false,
2536 theExtrFlags, false ),
2538 myIsExtrusionByNormal( false )
2541 // params for extrusion by normal
2542 ExtrusionParams(CORBA::Double theStepSize,
2543 CORBA::Long theNbOfSteps,
2544 CORBA::Short theDim,
2545 CORBA::Boolean theByAverageNormal,
2546 CORBA::Boolean theUseInputElemsOnly,
2547 CORBA::Boolean theMakeGroups ):
2548 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2550 makeFlags( theMakeGroups, false,
2551 theByAverageNormal, theUseInputElemsOnly ),
2553 myIsExtrusionByNormal( true )
2559 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2564 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2566 std::list<double> scales;
2567 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2568 scales.push_back( theScaleFactors[i] );
2572 // structure used to convert SMESH::double_array to gp_XYZ*
2576 TBasePoint( const SMESH::double_array & theBasePoint )
2579 if ( theBasePoint.length() == 3 )
2581 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2585 operator const gp_XYZ*() const { return pp; }
2590 //=======================================================================
2592 * \brief Generate dim+1 elements by extrusion of elements along vector
2593 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2594 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2595 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2596 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2597 * \param [in] nbOfSteps - number of elements to generate from one element
2598 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2599 * corresponding to groups the input elements included in.
2600 * \return ListOfGroups - new groups craeted if \a toMakeGroups is true
2602 //=======================================================================
2604 SMESH::ListOfGroups*
2605 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2606 const SMESH::ListOfIDSources & theEdges,
2607 const SMESH::ListOfIDSources & theFaces,
2608 const SMESH::DirStruct & theStepVector,
2609 CORBA::Long theNbOfSteps,
2610 const SMESH::double_array & theScaleFactors,
2611 CORBA::Boolean theLinearVariation,
2612 const SMESH::double_array & theBasePoint,
2613 CORBA::Boolean theToMakeGroups)
2614 throw (SALOME::SALOME_Exception)
2619 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
2620 theLinearVariation, theBasePoint, theToMakeGroups );
2622 TIDSortedElemSet elemsNodes[2];
2623 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2624 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2625 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2627 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2628 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2629 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2630 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2632 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2633 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2634 if ( myIsPreviewMode )
2636 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2637 // previewType = SMDSAbs_Edge;
2639 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2640 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2641 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2642 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2643 workElements = & copyElements[0];
2645 params.SetNoGroups();
2647 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2649 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2650 ::SMESH_MeshEditor::PGroupIDs groupIds =
2651 getEditor().ExtrusionSweep( workElements, params, aHistory );
2653 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2655 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2657 if ( !myIsPreviewMode )
2659 dumpGroupsList( aPythonDump, aGroups );
2660 aPythonDump << this<< ".ExtrusionSweepObjects( "
2664 << theStepVector << ", "
2665 << TVar( theNbOfSteps ) << ", "
2666 << theToMakeGroups << " )";
2670 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2673 return aGroups ? aGroups : new SMESH::ListOfGroups;
2675 SMESH_CATCH( SMESH::throwCorbaException );
2679 //=======================================================================
2680 //function : ExtrusionByNormal
2682 //=======================================================================
2684 SMESH::ListOfGroups*
2685 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2686 CORBA::Double stepSize,
2687 CORBA::Long nbOfSteps,
2688 CORBA::Boolean byAverageNormal,
2689 CORBA::Boolean useInputElemsOnly,
2690 CORBA::Boolean makeGroups,
2692 throw (SALOME::SALOME_Exception)
2697 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2699 ExtrusionParams params( stepSize, nbOfSteps, dim,
2700 byAverageNormal, useInputElemsOnly, makeGroups );
2702 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2703 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2705 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2706 if (( elemTypes->length() == 1 ) &&
2707 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2708 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2711 TIDSortedElemSet elemsNodes[2];
2712 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2713 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2715 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2716 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2717 if ( myIsPreviewMode )
2719 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2720 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2721 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2722 workElements = & copyElements[0];
2724 params.SetNoGroups();
2727 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2728 ::SMESH_MeshEditor::PGroupIDs groupIds =
2729 getEditor().ExtrusionSweep( workElements, params, aHistory );
2731 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2733 if (!myIsPreviewMode) {
2734 dumpGroupsList(aPythonDump, aGroups);
2735 aPythonDump << this << ".ExtrusionByNormal( " << objects
2736 << ", " << TVar( stepSize )
2737 << ", " << TVar( nbOfSteps )
2738 << ", " << byAverageNormal
2739 << ", " << useInputElemsOnly
2740 << ", " << makeGroups
2746 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2749 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2751 return aGroups ? aGroups : new SMESH::ListOfGroups;
2753 SMESH_CATCH( SMESH::throwCorbaException );
2757 //=======================================================================
2758 //function : AdvancedExtrusion
2760 //=======================================================================
2762 SMESH::ListOfGroups*
2763 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2764 const SMESH::DirStruct & theStepVector,
2765 CORBA::Long theNbOfSteps,
2766 CORBA::Long theExtrFlags,
2767 CORBA::Double theSewTolerance,
2768 CORBA::Boolean theMakeGroups)
2769 throw (SALOME::SALOME_Exception)
2774 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2776 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2777 theExtrFlags, theSewTolerance );
2779 TIDSortedElemSet elemsNodes[2];
2780 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2782 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2783 ::SMESH_MeshEditor::PGroupIDs groupIds =
2784 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2786 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2788 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2790 if ( !myIsPreviewMode ) {
2791 dumpGroupsList(aPythonDump, aGroups);
2792 aPythonDump << this << ".AdvancedExtrusion( "
2793 << theIDsOfElements << ", "
2794 << theStepVector << ", "
2795 << theNbOfSteps << ", "
2796 << theExtrFlags << ", "
2797 << theSewTolerance << ", "
2798 << theMakeGroups << " )";
2802 getPreviewMesh()->Remove( SMDSAbs_Volume );
2805 return aGroups ? aGroups : new SMESH::ListOfGroups;
2807 SMESH_CATCH( SMESH::throwCorbaException );
2811 //================================================================================
2813 * \brief Convert extrusion error to IDL enum
2815 //================================================================================
2819 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2821 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2825 RETCASE( EXTR_NO_ELEMENTS );
2826 RETCASE( EXTR_PATH_NOT_EDGE );
2827 RETCASE( EXTR_BAD_PATH_SHAPE );
2828 RETCASE( EXTR_BAD_STARTING_NODE );
2829 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2830 RETCASE( EXTR_CANT_GET_TANGENT );
2832 return SMESH::SMESH_MeshEditor::EXTR_OK;
2836 //=======================================================================
2837 //function : extrusionAlongPath
2839 //=======================================================================
2840 SMESH::ListOfGroups*
2841 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2842 const SMESH::ListOfIDSources & theEdges,
2843 const SMESH::ListOfIDSources & theFaces,
2844 SMESH::SMESH_IDSource_ptr thePathMesh,
2845 GEOM::GEOM_Object_ptr thePathShape,
2846 CORBA::Long theNodeStart,
2847 CORBA::Boolean theHasAngles,
2848 const SMESH::double_array & theAngles,
2849 CORBA::Boolean theLinearVariation,
2850 CORBA::Boolean theHasRefPoint,
2851 const SMESH::PointStruct & theRefPoint,
2853 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2854 throw (SALOME::SALOME_Exception)
2859 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2861 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2862 if ( thePathMesh->_is_nil() )
2863 return aGroups._retn();
2866 SMESH_subMesh* aSubMesh = 0;
2867 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2868 if ( thePathShape->_is_nil() )
2870 // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
2871 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
2873 SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
2874 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2875 if ( !aMeshImp ) return aGroups._retn();
2876 aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
2877 if ( !aSubMesh ) return aGroups._retn();
2879 else if ( !aMeshImp ||
2880 aMeshImp->NbEdges() != aMeshImp->NbElements() )
2882 return aGroups._retn();
2887 if ( !aMeshImp ) return aGroups._retn();
2888 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2889 aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2890 if ( !aSubMesh /*|| !aSubMesh->GetSubMeshDS()*/ )
2891 return aGroups._retn();
2894 SMDS_MeshNode* nodeStart =
2895 (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2897 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2898 return aGroups._retn();
2901 TIDSortedElemSet elemsNodes[2];
2902 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2903 SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
2904 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2906 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2907 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2908 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2909 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2911 list<double> angles;
2912 for ( CORBA::ULong i = 0; i < theAngles.length(); i++ ) {
2913 angles.push_back( theAngles[i] );
2916 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2918 int nbOldGroups = myMesh->NbGroup();
2920 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2921 if ( myIsPreviewMode )
2923 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2924 TPreviewMesh * tmpMesh = getPreviewMesh();
2925 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2926 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2927 workElements = & copyElements[0];
2928 theMakeGroups = false;
2931 ::SMESH_MeshEditor::Extrusion_Error error;
2933 error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
2934 theHasAngles, angles, theLinearVariation,
2935 theHasRefPoint, refPnt, theMakeGroups );
2937 error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
2938 theHasAngles, angles, theLinearVariation,
2939 theHasRefPoint, refPnt, theMakeGroups );
2941 declareMeshModified( /*isReComputeSafe=*/true );
2942 theError = convExtrError( error );
2944 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2945 if ( theMakeGroups ) {
2946 list<int> groupIDs = myMesh->GetGroupIds();
2947 list<int>::iterator newBegin = groupIDs.begin();
2948 std::advance( newBegin, nbOldGroups ); // skip old groups
2949 groupIDs.erase( groupIDs.begin(), newBegin );
2950 aGroups = getGroups( & groupIDs );
2951 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2954 if ( !myIsPreviewMode ) {
2955 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2956 else aPythonDump << "(_noGroups, error) = ";
2957 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2961 << thePathMesh << ", "
2962 << thePathShape << ", "
2963 << theNodeStart << ", "
2964 << theHasAngles << ", "
2965 << TVar( theAngles ) << ", "
2966 << theLinearVariation << ", "
2967 << theHasRefPoint << ", "
2968 << "SMESH.PointStruct( "
2969 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2970 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2971 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2972 << theMakeGroups << " )";
2976 getPreviewMesh()->Remove( SMDSAbs_Volume );
2979 return aGroups._retn();
2981 SMESH_CATCH( SMESH::throwCorbaException );
2985 //================================================================================
2987 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2988 * of given angles along path steps
2989 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2990 * which proceeds the extrusion
2991 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2992 * is used to define the sub-mesh for the path
2994 //================================================================================
2996 SMESH::double_array*
2997 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2998 GEOM::GEOM_Object_ptr thePathShape,
2999 const SMESH::double_array & theAngles)
3001 SMESH::double_array_var aResult = new SMESH::double_array();
3002 int nbAngles = theAngles.length();
3003 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3005 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3006 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3007 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3008 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3009 return aResult._retn();
3010 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3011 if ( nbSteps == nbAngles )
3013 aResult.inout() = theAngles;
3017 aResult->length( nbSteps );
3018 double rAn2St = double( nbAngles ) / double( nbSteps );
3019 double angPrev = 0, angle;
3020 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3022 double angCur = rAn2St * ( iSt+1 );
3023 double angCurFloor = floor( angCur );
3024 double angPrevFloor = floor( angPrev );
3025 if ( angPrevFloor == angCurFloor )
3026 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3029 int iP = int( angPrevFloor );
3030 double angPrevCeil = ceil(angPrev);
3031 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3033 int iC = int( angCurFloor );
3034 if ( iC < nbAngles )
3035 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3037 iP = int( angPrevCeil );
3039 angle += theAngles[ iC ];
3041 aResult[ iSt ] = angle;
3046 // Update Python script
3047 TPythonDump() << "rotAngles = " << theAngles;
3048 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3049 << thePathMesh << ", "
3050 << thePathShape << ", "
3053 return aResult._retn();
3056 //=======================================================================
3059 //=======================================================================
3061 SMESH::ListOfGroups*
3062 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3063 const SMESH::AxisStruct & theAxis,
3064 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3065 CORBA::Boolean theCopy,
3067 ::SMESH_Mesh* theTargetMesh)
3068 throw (SALOME::SALOME_Exception)
3073 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3074 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3076 if ( theTargetMesh )
3080 switch ( theMirrorType ) {
3081 case SMESH::SMESH_MeshEditor::POINT:
3082 aTrsf.SetMirror( P );
3084 case SMESH::SMESH_MeshEditor::AXIS:
3085 aTrsf.SetMirror( gp_Ax1( P, V ));
3088 aTrsf.SetMirror( gp_Ax2( P, V ));
3091 TIDSortedElemSet copyElements;
3092 TIDSortedElemSet* workElements = & theElements;
3094 if ( myIsPreviewMode )
3096 TPreviewMesh * tmpMesh = getPreviewMesh();
3097 tmpMesh->Copy( theElements, copyElements);
3098 if ( !theCopy && !theTargetMesh )
3100 TIDSortedElemSet elemsAround, elemsAroundCopy;
3101 getElementsAround( theElements, getMeshDS(), elemsAround );
3102 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3104 workElements = & copyElements;
3105 theMakeGroups = false;
3108 ::SMESH_MeshEditor::PGroupIDs groupIds =
3109 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3111 if ( theCopy && !myIsPreviewMode)
3113 if ( theTargetMesh )
3115 theTargetMesh->GetMeshDS()->Modified();
3119 declareMeshModified( /*isReComputeSafe=*/false );
3122 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3124 SMESH_CATCH( SMESH::throwCorbaException );
3128 //=======================================================================
3131 //=======================================================================
3133 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3134 const SMESH::AxisStruct & theAxis,
3135 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3136 CORBA::Boolean theCopy)
3137 throw (SALOME::SALOME_Exception)
3139 if ( !myIsPreviewMode ) {
3140 TPythonDump() << this << ".Mirror( "
3141 << theIDsOfElements << ", "
3143 << mirrorTypeName(theMirrorType) << ", "
3146 if ( theIDsOfElements.length() > 0 )
3148 TIDSortedElemSet elements;
3149 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3150 mirror(elements, theAxis, theMirrorType, theCopy, false);
3155 //=======================================================================
3156 //function : MirrorObject
3158 //=======================================================================
3160 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3161 const SMESH::AxisStruct & theAxis,
3162 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3163 CORBA::Boolean theCopy)
3164 throw (SALOME::SALOME_Exception)
3166 if ( !myIsPreviewMode ) {
3167 TPythonDump() << this << ".MirrorObject( "
3168 << theObject << ", "
3170 << mirrorTypeName(theMirrorType) << ", "
3173 TIDSortedElemSet elements;
3175 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3177 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3178 mirror(elements, theAxis, theMirrorType, theCopy, false);
3181 //=======================================================================
3182 //function : MirrorMakeGroups
3184 //=======================================================================
3186 SMESH::ListOfGroups*
3187 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3188 const SMESH::AxisStruct& theMirror,
3189 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3190 throw (SALOME::SALOME_Exception)
3192 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3194 SMESH::ListOfGroups * aGroups = 0;
3195 if ( theIDsOfElements.length() > 0 )
3197 TIDSortedElemSet elements;
3198 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3199 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3201 if (!myIsPreviewMode) {
3202 dumpGroupsList(aPythonDump, aGroups);
3203 aPythonDump << this << ".MirrorMakeGroups( "
3204 << theIDsOfElements << ", "
3205 << theMirror << ", "
3206 << mirrorTypeName(theMirrorType) << " )";
3211 //=======================================================================
3212 //function : MirrorObjectMakeGroups
3214 //=======================================================================
3216 SMESH::ListOfGroups*
3217 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3218 const SMESH::AxisStruct& theMirror,
3219 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3220 throw (SALOME::SALOME_Exception)
3222 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3224 SMESH::ListOfGroups * aGroups = 0;
3225 TIDSortedElemSet elements;
3226 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3227 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3229 if (!myIsPreviewMode)
3231 dumpGroupsList(aPythonDump,aGroups);
3232 aPythonDump << this << ".MirrorObjectMakeGroups( "
3233 << theObject << ", "
3234 << theMirror << ", "
3235 << mirrorTypeName(theMirrorType) << " )";
3240 //=======================================================================
3241 //function : MirrorMakeMesh
3243 //=======================================================================
3245 SMESH::SMESH_Mesh_ptr
3246 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3247 const SMESH::AxisStruct& theMirror,
3248 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3249 CORBA::Boolean theCopyGroups,
3250 const char* theMeshName)
3251 throw (SALOME::SALOME_Exception)
3253 SMESH_Mesh_i* mesh_i;
3254 SMESH::SMESH_Mesh_var mesh;
3255 { // open new scope to dump "MakeMesh" command
3256 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3258 TPythonDump pydump; // to prevent dump at mesh creation
3260 mesh = makeMesh( theMeshName );
3261 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3262 if (mesh_i && theIDsOfElements.length() > 0 )
3264 TIDSortedElemSet elements;
3265 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3266 mirror(elements, theMirror, theMirrorType,
3267 false, theCopyGroups, & mesh_i->GetImpl());
3268 mesh_i->CreateGroupServants();
3271 if (!myIsPreviewMode) {
3272 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3273 << theIDsOfElements << ", "
3274 << theMirror << ", "
3275 << mirrorTypeName(theMirrorType) << ", "
3276 << theCopyGroups << ", '"
3277 << theMeshName << "' )";
3282 if (!myIsPreviewMode && mesh_i)
3283 mesh_i->GetGroups();
3285 return mesh._retn();
3288 //=======================================================================
3289 //function : MirrorObjectMakeMesh
3291 //=======================================================================
3293 SMESH::SMESH_Mesh_ptr
3294 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3295 const SMESH::AxisStruct& theMirror,
3296 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3297 CORBA::Boolean theCopyGroups,
3298 const char* theMeshName)
3299 throw (SALOME::SALOME_Exception)
3301 SMESH_Mesh_i* mesh_i;
3302 SMESH::SMESH_Mesh_var mesh;
3303 { // open new scope to dump "MakeMesh" command
3304 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3306 TPythonDump pydump; // to prevent dump at mesh creation
3308 mesh = makeMesh( theMeshName );
3309 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3310 TIDSortedElemSet elements;
3312 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3314 mirror(elements, theMirror, theMirrorType,
3315 false, theCopyGroups, & mesh_i->GetImpl());
3316 mesh_i->CreateGroupServants();
3318 if (!myIsPreviewMode) {
3319 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3320 << theObject << ", "
3321 << theMirror << ", "
3322 << mirrorTypeName(theMirrorType) << ", "
3323 << theCopyGroups << ", '"
3324 << theMeshName << "' )";
3329 if (!myIsPreviewMode && mesh_i)
3330 mesh_i->GetGroups();
3332 return mesh._retn();
3335 //=======================================================================
3336 //function : translate
3338 //=======================================================================
3340 SMESH::ListOfGroups*
3341 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3342 const SMESH::DirStruct & theVector,
3343 CORBA::Boolean theCopy,
3345 ::SMESH_Mesh* theTargetMesh)
3346 throw (SALOME::SALOME_Exception)
3351 if ( theTargetMesh )
3355 const SMESH::PointStruct * P = &theVector.PS;
3356 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3358 TIDSortedElemSet copyElements;
3359 TIDSortedElemSet* workElements = &theElements;
3361 if ( myIsPreviewMode )
3363 TPreviewMesh * tmpMesh = getPreviewMesh();
3364 tmpMesh->Copy( theElements, copyElements);
3365 if ( !theCopy && !theTargetMesh )
3367 TIDSortedElemSet elemsAround, elemsAroundCopy;
3368 getElementsAround( theElements, getMeshDS(), elemsAround );
3369 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3371 workElements = & copyElements;
3372 theMakeGroups = false;
3375 ::SMESH_MeshEditor::PGroupIDs groupIds =
3376 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3378 if ( theCopy && !myIsPreviewMode )
3380 if ( theTargetMesh )
3382 theTargetMesh->GetMeshDS()->Modified();
3386 declareMeshModified( /*isReComputeSafe=*/false );
3390 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3392 SMESH_CATCH( SMESH::throwCorbaException );
3396 //=======================================================================
3397 //function : Translate
3399 //=======================================================================
3401 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3402 const SMESH::DirStruct & theVector,
3403 CORBA::Boolean theCopy)
3404 throw (SALOME::SALOME_Exception)
3406 if (!myIsPreviewMode) {
3407 TPythonDump() << this << ".Translate( "
3408 << theIDsOfElements << ", "
3409 << theVector << ", "
3412 if (theIDsOfElements.length()) {
3413 TIDSortedElemSet elements;
3414 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3415 translate(elements, theVector, theCopy, false);
3419 //=======================================================================
3420 //function : TranslateObject
3422 //=======================================================================
3424 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3425 const SMESH::DirStruct & theVector,
3426 CORBA::Boolean theCopy)
3427 throw (SALOME::SALOME_Exception)
3429 if (!myIsPreviewMode) {
3430 TPythonDump() << this << ".TranslateObject( "
3431 << theObject << ", "
3432 << theVector << ", "
3435 TIDSortedElemSet elements;
3437 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3439 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3440 translate(elements, theVector, theCopy, false);
3443 //=======================================================================
3444 //function : TranslateMakeGroups
3446 //=======================================================================
3448 SMESH::ListOfGroups*
3449 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3450 const SMESH::DirStruct& theVector)
3451 throw (SALOME::SALOME_Exception)
3453 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3455 SMESH::ListOfGroups * aGroups = 0;
3456 if (theIDsOfElements.length()) {
3457 TIDSortedElemSet elements;
3458 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3459 aGroups = translate(elements,theVector,true,true);
3461 if (!myIsPreviewMode) {
3462 dumpGroupsList(aPythonDump, aGroups);
3463 aPythonDump << this << ".TranslateMakeGroups( "
3464 << theIDsOfElements << ", "
3465 << theVector << " )";
3470 //=======================================================================
3471 //function : TranslateObjectMakeGroups
3473 //=======================================================================
3475 SMESH::ListOfGroups*
3476 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3477 const SMESH::DirStruct& theVector)
3478 throw (SALOME::SALOME_Exception)
3480 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3482 SMESH::ListOfGroups * aGroups = 0;
3483 TIDSortedElemSet elements;
3484 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3485 aGroups = translate(elements, theVector, true, true);
3487 if (!myIsPreviewMode) {
3488 dumpGroupsList(aPythonDump, aGroups);
3489 aPythonDump << this << ".TranslateObjectMakeGroups( "
3490 << theObject << ", "
3491 << theVector << " )";
3496 //=======================================================================
3497 //function : TranslateMakeMesh
3499 //=======================================================================
3501 SMESH::SMESH_Mesh_ptr
3502 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3503 const SMESH::DirStruct& theVector,
3504 CORBA::Boolean theCopyGroups,
3505 const char* theMeshName)
3506 throw (SALOME::SALOME_Exception)
3508 SMESH_Mesh_i* mesh_i;
3509 SMESH::SMESH_Mesh_var mesh;
3511 { // open new scope to dump "MakeMesh" command
3512 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3514 TPythonDump pydump; // to prevent dump at mesh creation
3516 mesh = makeMesh( theMeshName );
3517 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3519 if ( mesh_i && theIDsOfElements.length() )
3521 TIDSortedElemSet elements;
3522 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3523 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3524 mesh_i->CreateGroupServants();
3527 if ( !myIsPreviewMode ) {
3528 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3529 << theIDsOfElements << ", "
3530 << theVector << ", "
3531 << theCopyGroups << ", '"
3532 << theMeshName << "' )";
3537 if (!myIsPreviewMode && mesh_i)
3538 mesh_i->GetGroups();
3540 return mesh._retn();
3543 //=======================================================================
3544 //function : TranslateObjectMakeMesh
3546 //=======================================================================
3548 SMESH::SMESH_Mesh_ptr
3549 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3550 const SMESH::DirStruct& theVector,
3551 CORBA::Boolean theCopyGroups,
3552 const char* theMeshName)
3553 throw (SALOME::SALOME_Exception)
3556 SMESH_Mesh_i* mesh_i;
3557 SMESH::SMESH_Mesh_var mesh;
3558 { // open new scope to dump "MakeMesh" command
3559 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3561 TPythonDump pydump; // to prevent dump at mesh creation
3562 mesh = makeMesh( theMeshName );
3563 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3565 TIDSortedElemSet elements;
3567 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3569 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3570 mesh_i->CreateGroupServants();
3572 if ( !myIsPreviewMode ) {
3573 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3574 << theObject << ", "
3575 << theVector << ", "
3576 << theCopyGroups << ", '"
3577 << theMeshName << "' )";
3582 if (!myIsPreviewMode && mesh_i)
3583 mesh_i->GetGroups();
3585 return mesh._retn();
3587 SMESH_CATCH( SMESH::throwCorbaException );
3591 //=======================================================================
3594 //=======================================================================
3596 SMESH::ListOfGroups*
3597 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3598 const SMESH::AxisStruct & theAxis,
3599 CORBA::Double theAngle,
3600 CORBA::Boolean theCopy,
3602 ::SMESH_Mesh* theTargetMesh)
3603 throw (SALOME::SALOME_Exception)
3608 if ( theTargetMesh )
3611 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3612 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3615 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3617 TIDSortedElemSet copyElements;
3618 TIDSortedElemSet* workElements = &theElements;
3619 if ( myIsPreviewMode ) {
3620 TPreviewMesh * tmpMesh = getPreviewMesh();
3621 tmpMesh->Copy( theElements, copyElements );
3622 if ( !theCopy && !theTargetMesh )
3624 TIDSortedElemSet elemsAround, elemsAroundCopy;
3625 getElementsAround( theElements, getMeshDS(), elemsAround );
3626 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3628 workElements = ©Elements;
3629 theMakeGroups = false;
3632 ::SMESH_MeshEditor::PGroupIDs groupIds =
3633 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3635 if ( theCopy && !myIsPreviewMode)
3637 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3638 else declareMeshModified( /*isReComputeSafe=*/false );
3641 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3643 SMESH_CATCH( SMESH::throwCorbaException );
3647 //=======================================================================
3650 //=======================================================================
3652 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3653 const SMESH::AxisStruct & theAxis,
3654 CORBA::Double theAngle,
3655 CORBA::Boolean theCopy)
3656 throw (SALOME::SALOME_Exception)
3658 if (!myIsPreviewMode) {
3659 TPythonDump() << this << ".Rotate( "
3660 << theIDsOfElements << ", "
3662 << TVar( theAngle ) << ", "
3665 if (theIDsOfElements.length() > 0)
3667 TIDSortedElemSet elements;
3668 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3669 rotate(elements,theAxis,theAngle,theCopy,false);
3673 //=======================================================================
3674 //function : RotateObject
3676 //=======================================================================
3678 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3679 const SMESH::AxisStruct & theAxis,
3680 CORBA::Double theAngle,
3681 CORBA::Boolean theCopy)
3682 throw (SALOME::SALOME_Exception)
3684 if ( !myIsPreviewMode ) {
3685 TPythonDump() << this << ".RotateObject( "
3686 << theObject << ", "
3688 << TVar( theAngle ) << ", "
3691 TIDSortedElemSet elements;
3692 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3693 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3694 rotate(elements,theAxis,theAngle,theCopy,false);
3697 //=======================================================================
3698 //function : RotateMakeGroups
3700 //=======================================================================
3702 SMESH::ListOfGroups*
3703 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3704 const SMESH::AxisStruct& theAxis,
3705 CORBA::Double theAngle)
3706 throw (SALOME::SALOME_Exception)
3708 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3710 SMESH::ListOfGroups * aGroups = 0;
3711 if (theIDsOfElements.length() > 0)
3713 TIDSortedElemSet elements;
3714 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3715 aGroups = rotate(elements,theAxis,theAngle,true,true);
3717 if (!myIsPreviewMode) {
3718 dumpGroupsList(aPythonDump, aGroups);
3719 aPythonDump << this << ".RotateMakeGroups( "
3720 << theIDsOfElements << ", "
3722 << TVar( theAngle ) << " )";
3727 //=======================================================================
3728 //function : RotateObjectMakeGroups
3730 //=======================================================================
3732 SMESH::ListOfGroups*
3733 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3734 const SMESH::AxisStruct& theAxis,
3735 CORBA::Double theAngle)
3736 throw (SALOME::SALOME_Exception)
3738 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3740 SMESH::ListOfGroups * aGroups = 0;
3741 TIDSortedElemSet elements;
3742 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3743 aGroups = rotate(elements, theAxis, theAngle, true, true);
3745 if (!myIsPreviewMode) {
3746 dumpGroupsList(aPythonDump, aGroups);
3747 aPythonDump << this << ".RotateObjectMakeGroups( "
3748 << theObject << ", "
3750 << TVar( theAngle ) << " )";
3755 //=======================================================================
3756 //function : RotateMakeMesh
3758 //=======================================================================
3760 SMESH::SMESH_Mesh_ptr
3761 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3762 const SMESH::AxisStruct& theAxis,
3763 CORBA::Double theAngleInRadians,
3764 CORBA::Boolean theCopyGroups,
3765 const char* theMeshName)
3766 throw (SALOME::SALOME_Exception)
3769 SMESH::SMESH_Mesh_var mesh;
3770 SMESH_Mesh_i* mesh_i;
3772 { // open new scope to dump "MakeMesh" command
3773 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3775 TPythonDump pydump; // to prevent dump at mesh creation
3777 mesh = makeMesh( theMeshName );
3778 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3780 if ( mesh_i && theIDsOfElements.length() > 0 )
3782 TIDSortedElemSet elements;
3783 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3784 rotate(elements, theAxis, theAngleInRadians,
3785 false, theCopyGroups, & mesh_i->GetImpl());
3786 mesh_i->CreateGroupServants();
3788 if ( !myIsPreviewMode ) {
3789 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3790 << theIDsOfElements << ", "
3792 << TVar( theAngleInRadians ) << ", "
3793 << theCopyGroups << ", '"
3794 << theMeshName << "' )";
3799 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3800 mesh_i->GetGroups();
3802 return mesh._retn();
3804 SMESH_CATCH( SMESH::throwCorbaException );
3808 //=======================================================================
3809 //function : RotateObjectMakeMesh
3811 //=======================================================================
3813 SMESH::SMESH_Mesh_ptr
3814 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3815 const SMESH::AxisStruct& theAxis,
3816 CORBA::Double theAngleInRadians,
3817 CORBA::Boolean theCopyGroups,
3818 const char* theMeshName)
3819 throw (SALOME::SALOME_Exception)
3822 SMESH::SMESH_Mesh_var mesh;
3823 SMESH_Mesh_i* mesh_i;
3825 {// open new scope to dump "MakeMesh" command
3826 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3828 TPythonDump pydump; // to prevent dump at mesh creation
3829 mesh = makeMesh( theMeshName );
3830 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3832 TIDSortedElemSet elements;
3834 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3836 rotate(elements, theAxis, theAngleInRadians,
3837 false, theCopyGroups, & mesh_i->GetImpl());
3838 mesh_i->CreateGroupServants();
3840 if ( !myIsPreviewMode ) {
3841 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3842 << theObject << ", "
3844 << TVar( theAngleInRadians ) << ", "
3845 << theCopyGroups << ", '"
3846 << theMeshName << "' )";
3851 if (!myIsPreviewMode && mesh_i)
3852 mesh_i->GetGroups();
3854 return mesh._retn();
3856 SMESH_CATCH( SMESH::throwCorbaException );
3860 //=======================================================================
3863 //=======================================================================
3865 SMESH::ListOfGroups*
3866 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3867 const SMESH::PointStruct& thePoint,
3868 const SMESH::double_array& theScaleFact,
3869 CORBA::Boolean theCopy,
3871 ::SMESH_Mesh* theTargetMesh)
3872 throw (SALOME::SALOME_Exception)
3876 if ( theScaleFact.length() < 1 )
3877 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3878 if ( theScaleFact.length() == 2 )
3879 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3881 if ( theTargetMesh )
3884 TIDSortedElemSet elements;
3885 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3886 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3891 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3892 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3896 #if OCC_VERSION_LARGE > 0x06070100
3897 // fight against orthogonalization
3898 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3899 // 0, S[1], 0, thePoint.y * (1-S[1]),
3900 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3901 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3902 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3903 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3904 loc.SetCoord( thePoint.x * (1-S[0]),
3905 thePoint.y * (1-S[1]),
3906 thePoint.z * (1-S[2]));
3907 M.SetDiagonal( S[0], S[1], S[2] );
3910 double tol = std::numeric_limits<double>::max();
3911 aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3912 0, S[1], 0, thePoint.y * (1-S[1]),
3913 0, 0, S[2], thePoint.z * (1-S[2]), tol, tol);
3916 TIDSortedElemSet copyElements;
3917 TIDSortedElemSet* workElements = &elements;
3918 if ( myIsPreviewMode )
3920 TPreviewMesh * tmpMesh = getPreviewMesh();
3921 tmpMesh->Copy( elements, copyElements);
3922 if ( !theCopy && !theTargetMesh )
3924 TIDSortedElemSet elemsAround, elemsAroundCopy;
3925 getElementsAround( elements, getMeshDS(), elemsAround );
3926 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3928 workElements = & copyElements;
3929 theMakeGroups = false;
3932 ::SMESH_MeshEditor::PGroupIDs groupIds =
3933 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3935 if ( theCopy && !myIsPreviewMode )
3937 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3938 else declareMeshModified( /*isReComputeSafe=*/false );
3940 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3942 SMESH_CATCH( SMESH::throwCorbaException );
3946 //=======================================================================
3949 //=======================================================================
3951 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3952 const SMESH::PointStruct& thePoint,
3953 const SMESH::double_array& theScaleFact,
3954 CORBA::Boolean theCopy)
3955 throw (SALOME::SALOME_Exception)
3957 if ( !myIsPreviewMode ) {
3958 TPythonDump() << this << ".Scale( "
3959 << theObject << ", "
3961 << TVar( theScaleFact ) << ", "
3964 scale(theObject, thePoint, theScaleFact, theCopy, false);
3968 //=======================================================================
3969 //function : ScaleMakeGroups
3971 //=======================================================================
3973 SMESH::ListOfGroups*
3974 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3975 const SMESH::PointStruct& thePoint,
3976 const SMESH::double_array& theScaleFact)
3977 throw (SALOME::SALOME_Exception)
3979 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3981 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3982 if (!myIsPreviewMode) {
3983 dumpGroupsList(aPythonDump, aGroups);
3984 aPythonDump << this << ".Scale("
3987 << TVar( theScaleFact ) << ",True,True)";
3993 //=======================================================================
3994 //function : ScaleMakeMesh
3996 //=======================================================================
3998 SMESH::SMESH_Mesh_ptr
3999 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4000 const SMESH::PointStruct& thePoint,
4001 const SMESH::double_array& theScaleFact,
4002 CORBA::Boolean theCopyGroups,
4003 const char* theMeshName)
4004 throw (SALOME::SALOME_Exception)
4006 SMESH_Mesh_i* mesh_i;
4007 SMESH::SMESH_Mesh_var mesh;
4008 { // open new scope to dump "MakeMesh" command
4009 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4011 TPythonDump pydump; // to prevent dump at mesh creation
4012 mesh = makeMesh( theMeshName );
4013 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4017 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4018 mesh_i->CreateGroupServants();
4020 if ( !myIsPreviewMode )
4021 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4022 << theObject << ", "
4024 << TVar( theScaleFact ) << ", "
4025 << theCopyGroups << ", '"
4026 << theMeshName << "' )";
4030 if (!myIsPreviewMode && mesh_i)
4031 mesh_i->GetGroups();
4033 return mesh._retn();
4037 //=======================================================================
4038 //function : findCoincidentNodes
4040 //=======================================================================
4042 void SMESH_MeshEditor_i::
4043 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4044 CORBA::Double Tolerance,
4045 SMESH::array_of_long_array_out GroupsOfNodes,
4046 CORBA::Boolean SeparateCornersAndMedium)
4048 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4049 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4051 GroupsOfNodes = new SMESH::array_of_long_array;
4052 GroupsOfNodes->length( aListOfListOfNodes.size() );
4053 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4054 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4056 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4057 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4058 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4059 aGroup.length( aListOfNodes.size() );
4060 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4061 aGroup[ j ] = (*lIt)->GetID();
4065 //=======================================================================
4066 //function : FindCoincidentNodes
4068 //=======================================================================
4070 void SMESH_MeshEditor_i::
4071 FindCoincidentNodes (CORBA::Double Tolerance,
4072 SMESH::array_of_long_array_out GroupsOfNodes,
4073 CORBA::Boolean SeparateCornersAndMedium)
4074 throw (SALOME::SALOME_Exception)
4079 TIDSortedNodeSet nodes; // no input nodes
4080 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4082 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4083 << Tolerance << ", "
4084 << SeparateCornersAndMedium << " )";
4086 SMESH_CATCH( SMESH::throwCorbaException );
4089 //=======================================================================
4090 //function : FindCoincidentNodesOnPart
4092 //=======================================================================
4094 void SMESH_MeshEditor_i::
4095 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4096 CORBA::Double Tolerance,
4097 SMESH::array_of_long_array_out GroupsOfNodes,
4098 CORBA::Boolean SeparateCornersAndMedium)
4099 throw (SALOME::SALOME_Exception)
4104 TIDSortedNodeSet nodes;
4105 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4107 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4109 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4111 << Tolerance << ", "
4112 << SeparateCornersAndMedium << " )";
4114 SMESH_CATCH( SMESH::throwCorbaException );
4117 //================================================================================
4119 * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4120 * ExceptSubMeshOrGroups
4122 //================================================================================
4124 void SMESH_MeshEditor_i::
4125 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject,
4126 CORBA::Double theTolerance,
4127 SMESH::array_of_long_array_out theGroupsOfNodes,
4128 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4129 CORBA::Boolean theSeparateCornersAndMedium)
4130 throw (SALOME::SALOME_Exception)
4135 TIDSortedNodeSet nodes;
4136 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4138 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4140 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4142 while ( nodeIt->more() )
4143 nodes.erase( cast2Node( nodeIt->next() ));
4145 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4147 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4149 << theTolerance << ", "
4150 << theExceptSubMeshOrGroups << ", "
4151 << theSeparateCornersAndMedium << " )";
4153 SMESH_CATCH( SMESH::throwCorbaException );
4156 //=======================================================================
4157 //function : MergeNodes
4159 //=======================================================================
4161 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4162 const SMESH::ListOfIDSources& NodesToKeep,
4163 CORBA::Boolean AvoidMakingHoles)
4164 throw (SALOME::SALOME_Exception)
4169 SMESHDS_Mesh* aMesh = getMeshDS();
4171 TPythonDump aTPythonDump;
4172 aTPythonDump << this << ".MergeNodes([";
4174 TIDSortedNodeSet setOfNodesToKeep;
4175 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4177 prepareIdSource( NodesToKeep[i] );
4178 SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE );
4179 while ( nodeIt->more() )
4180 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4183 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4184 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4186 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4187 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4188 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4189 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4191 CORBA::Long index = aNodeGroup[ j ];
4192 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4194 if ( setOfNodesToKeep.count( node ))
4195 aListOfNodes.push_front( node );
4197 aListOfNodes.push_back( node );
4200 if ( aListOfNodes.size() < 2 )
4201 aListOfListOfNodes.pop_back();
4203 if ( i > 0 ) aTPythonDump << ", ";
4204 aTPythonDump << aNodeGroup;
4207 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4209 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4211 declareMeshModified( /*isReComputeSafe=*/false );
4213 SMESH_CATCH( SMESH::throwCorbaException );
4216 //=======================================================================
4217 //function : FindEqualElements
4219 //=======================================================================
4221 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr theObject,
4222 SMESH::array_of_long_array_out GroupsOfElementsID)
4223 throw (SALOME::SALOME_Exception)
4228 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4229 if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4231 TIDSortedElemSet elems;
4232 idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4234 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4235 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4237 GroupsOfElementsID = new SMESH::array_of_long_array;
4238 GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4240 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4241 aListOfListOfElementsID.begin();
4242 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4244 SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4245 list<int>& listOfIDs = *arraysIt;
4246 aGroup.length( listOfIDs.size() );
4247 list<int>::iterator idIt = listOfIDs.begin();
4248 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4249 aGroup[ k ] = *idIt;
4252 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4256 SMESH_CATCH( SMESH::throwCorbaException );
4259 //=======================================================================
4260 //function : MergeElements
4262 //=======================================================================
4264 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4265 throw (SALOME::SALOME_Exception)
4270 TPythonDump aTPythonDump;
4271 aTPythonDump << this << ".MergeElements( [";
4273 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4275 for ( CORBA::ULong i = 0; i < GroupsOfElementsID.length(); i++ ) {
4276 const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4277 aListOfListOfElementsID.push_back( list< int >() );
4278 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4279 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ ) {
4280 CORBA::Long id = anElemsIDGroup[ j ];
4281 aListOfElemsID.push_back( id );
4283 if ( aListOfElemsID.size() < 2 )
4284 aListOfListOfElementsID.pop_back();
4285 if ( i > 0 ) aTPythonDump << ", ";
4286 aTPythonDump << anElemsIDGroup;
4289 getEditor().MergeElements(aListOfListOfElementsID);
4291 declareMeshModified( /*isReComputeSafe=*/true );
4293 aTPythonDump << "] )";
4295 SMESH_CATCH( SMESH::throwCorbaException );
4298 //=======================================================================
4299 //function : MergeEqualElements
4301 //=======================================================================
4303 void SMESH_MeshEditor_i::MergeEqualElements()
4304 throw (SALOME::SALOME_Exception)
4309 getEditor().MergeEqualElements();
4311 declareMeshModified( /*isReComputeSafe=*/true );
4313 TPythonDump() << this << ".MergeEqualElements()";
4315 SMESH_CATCH( SMESH::throwCorbaException );
4318 //=============================================================================
4320 * Move the node to a given point
4322 //=============================================================================
4324 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4328 throw (SALOME::SALOME_Exception)
4331 initData(/*deleteSearchers=*/false);
4333 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4337 if ( theNodeSearcher )
4338 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4340 if ( myIsPreviewMode ) // make preview data
4342 // in a preview mesh, make edges linked to a node
4343 TPreviewMesh& tmpMesh = *getPreviewMesh();
4344 TIDSortedElemSet linkedNodes;
4345 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4346 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4347 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4348 for ( ; nIt != linkedNodes.end(); ++nIt )
4350 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4351 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4355 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4356 // fill preview data
4358 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4359 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4361 getMeshDS()->MoveNode(node, x, y, z);
4363 if ( !myIsPreviewMode )
4365 // Update Python script
4366 TPythonDump() << "isDone = " << this << ".MoveNode( "
4367 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4368 declareMeshModified( /*isReComputeSafe=*/false );
4371 SMESH_CATCH( SMESH::throwCorbaException );
4376 //================================================================================
4378 * \brief Return ID of node closest to a given point
4380 //================================================================================
4382 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4385 throw (SALOME::SALOME_Exception)
4388 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4390 if ( !theNodeSearcher ) {
4391 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4394 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4395 return node->GetID();
4397 SMESH_CATCH( SMESH::throwCorbaException );
4401 //================================================================================
4403 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4404 * move the node closest to the point to point's location and return ID of the node
4406 //================================================================================
4408 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4411 CORBA::Long theNodeID)
4412 throw (SALOME::SALOME_Exception)
4415 // We keep theNodeSearcher until any mesh modification:
4416 // 1) initData() deletes theNodeSearcher at any edition,
4417 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4419 initData(/*deleteSearchers=*/false);
4421 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4423 int nodeID = theNodeID;
4424 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4425 if ( !node ) // preview moving node
4427 if ( !theNodeSearcher ) {
4428 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4431 node = theNodeSearcher->FindClosestTo( p );
4434 nodeID = node->GetID();
4435 if ( myIsPreviewMode ) // make preview data
4437 // in a preview mesh, make edges linked to a node
4438 TPreviewMesh tmpMesh = *getPreviewMesh();
4439 TIDSortedElemSet linkedNodes;
4440 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4441 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4442 for ( ; nIt != linkedNodes.end(); ++nIt )
4444 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4445 tmpMesh.Copy( &edge );
4448 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4450 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4451 // fill preview data
4453 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4455 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4459 getMeshDS()->MoveNode(node, x, y, z);
4463 if ( !myIsPreviewMode )
4465 TPythonDump() << "nodeID = " << this
4466 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4467 << ", " << nodeID << " )";
4469 declareMeshModified( /*isReComputeSafe=*/false );
4474 SMESH_CATCH( SMESH::throwCorbaException );
4478 //=======================================================================
4480 * Return elements of given type where the given point is IN or ON.
4482 * 'ALL' type means elements of any type excluding nodes
4484 //=======================================================================
4486 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4489 SMESH::ElementType type)
4490 throw (SALOME::SALOME_Exception)
4493 SMESH::long_array_var res = new SMESH::long_array;
4494 vector< const SMDS_MeshElement* > foundElems;
4496 theSearchersDeleter.Set( myMesh );
4497 if ( !theElementSearcher ) {
4498 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4500 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4501 SMDSAbs_ElementType( type ),
4503 res->length( foundElems.size() );
4504 for ( size_t i = 0; i < foundElems.size(); ++i )
4505 res[i] = foundElems[i]->GetID();
4509 SMESH_CATCH( SMESH::throwCorbaException );
4513 //=======================================================================
4514 //function : FindAmongElementsByPoint
4515 //purpose : Searching among the given elements, return elements of given type
4516 // where the given point is IN or ON.
4517 // 'ALL' type means elements of any type excluding nodes
4518 //=======================================================================
4521 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4525 SMESH::ElementType type)
4526 throw (SALOME::SALOME_Exception)
4529 SMESH::long_array_var res = new SMESH::long_array;
4531 if ( type != SMESH::NODE )
4533 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4534 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4535 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4536 type != types[0] ) // but search of elements of dim > 0
4539 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4540 return FindElementsByPoint( x,y,z, type );
4542 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4544 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4545 if ( !theElementSearcher )
4547 // create a searcher from elementIDs
4548 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4549 SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4551 if ( !idSourceToSet( elementIDs, meshDS, elements,
4552 ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
4553 /*emptyIfIsMesh=*/true))
4556 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4557 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4559 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
4562 vector< const SMDS_MeshElement* > foundElems;
4564 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4565 SMDSAbs_ElementType( type ),
4567 res->length( foundElems.size() );
4568 for ( size_t i = 0; i < foundElems.size(); ++i )
4569 res[i] = foundElems[i]->GetID();
4573 SMESH_CATCH( SMESH::throwCorbaException );
4577 //=======================================================================
4578 //function : GetPointState
4579 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4580 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4581 //=======================================================================
4583 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4586 throw (SALOME::SALOME_Exception)
4589 theSearchersDeleter.Set( myMesh );
4590 if ( !theElementSearcher ) {
4591 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4593 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4595 SMESH_CATCH( SMESH::throwCorbaException );
4599 //=======================================================================
4600 //function : convError
4602 //=======================================================================
4604 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4606 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4610 RETCASE( SEW_BORDER1_NOT_FOUND );
4611 RETCASE( SEW_BORDER2_NOT_FOUND );
4612 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4613 RETCASE( SEW_BAD_SIDE_NODES );
4614 RETCASE( SEW_VOLUMES_TO_SPLIT );
4615 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4616 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4617 RETCASE( SEW_BAD_SIDE1_NODES );
4618 RETCASE( SEW_BAD_SIDE2_NODES );
4619 RETCASE( SEW_INTERNAL_ERROR );
4621 return SMESH::SMESH_MeshEditor::SEW_OK;
4624 //=======================================================================
4626 * Returns groups of FreeBorder's coincident within the given tolerance.
4627 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
4628 * to free borders being compared is used.
4630 //=======================================================================
4632 SMESH::CoincidentFreeBorders*
4633 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
4635 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
4639 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
4640 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
4642 // copy free borders
4643 aCFB->borders.length( cfb._borders.size() );
4644 for ( size_t i = 0; i < cfb._borders.size(); ++i )
4646 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
4647 SMESH::FreeBorder& aBRD = aCFB->borders[i];
4648 aBRD.nodeIDs.length( nodes.size() );
4649 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4650 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
4653 // copy coincident parts
4654 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
4655 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
4657 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
4658 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
4659 aGRP.length( grp.size() );
4660 for ( size_t iP = 0; iP < grp.size(); ++iP )
4662 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
4663 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4664 aPART.border = part._border;
4665 aPART.node1 = part._node1;
4666 aPART.node2 = part._node2;
4667 aPART.nodeLast = part._nodeLast;
4670 SMESH_CATCH( SMESH::doNothing );
4672 TPythonDump() << "CoincidentFreeBorders = "
4673 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
4675 return aCFB._retn();
4678 //=======================================================================
4680 * Sew FreeBorder's of each group
4682 //=======================================================================
4684 CORBA::Short SMESH_MeshEditor_i::
4685 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
4686 CORBA::Boolean createPolygons,
4687 CORBA::Boolean createPolyhedra)
4688 throw (SALOME::SALOME_Exception)
4690 CORBA::Short nbSewed = 0;
4692 SMESH_MeshAlgos::TFreeBorderVec groups;
4693 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
4695 // check the input and collect nodes
4696 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
4698 borderNodes.clear();
4699 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
4700 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
4702 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
4703 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
4704 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
4706 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
4708 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
4709 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
4710 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
4711 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
4712 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
4713 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4715 // do not keep these nodes for further sewing as nodes can be removed by the sewing
4716 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
4717 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
4718 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
4720 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
4722 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
4724 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
4726 borderNodes.push_back( n1 );
4727 borderNodes.push_back( n2 );
4728 borderNodes.push_back( n3 );
4730 groups.push_back( borderNodes );
4733 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
4734 // to get nodes that replace other nodes during merge we create 0D elements
4735 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
4738 vector< const SMDS_MeshElement* > tmp0Delems;
4739 for ( size_t i = 0; i < groups.size(); ++i )
4741 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4742 for ( size_t iN = 0; iN < nodes.size(); ++iN )
4744 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
4746 tmp0Delems.push_back( it0D->next() );
4748 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
4752 // cout << endl << "INIT" << endl;
4753 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4755 // cout << i << " ";
4756 // if ( i % 3 == 0 ) cout << "^ ";
4757 // tmp0Delems[i]->GetNode(0)->Print( cout );
4762 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
4764 for ( size_t i = 0; i < groups.size(); ++i )
4766 bool isBordToBord = true;
4767 bool groupSewed = false;
4768 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
4769 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
4771 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
4772 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
4773 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
4775 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
4776 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
4777 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
4779 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
4782 // TIDSortedElemSet emptySet, avoidSet;
4783 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
4785 // cout << "WRONG 2nd 1" << endl;
4786 // n0->Print( cout );
4787 // n1->Print( cout );
4789 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
4791 // cout << "WRONG 2nd 2" << endl;
4792 // n3->Print( cout );
4793 // n4->Print( cout );
4796 if ( !isBordToBord )
4798 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
4799 n2 = 0; // and n2 is not used
4801 // 1st border moves to 2nd
4802 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
4804 /*2ndIsFreeBorder=*/ isBordToBord,
4805 createPolygons, createPolyhedra);
4806 groupSewed = ( res == ok );
4808 isBordToBord = false;
4809 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
4810 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
4812 // cout << t << " ";
4813 // if ( t % 3 == 0 ) cout << "^ ";
4814 // tmp0Delems[t]->GetNode(0)->Print( cout );
4817 i0D += nodes.size();
4818 nbSewed += groupSewed;
4821 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
4822 << freeBorders << ", "
4823 << createPolygons << ", "
4824 << createPolyhedra << " )";
4826 SMESH_CATCH( SMESH::doNothing );
4828 declareMeshModified( /*isReComputeSafe=*/false );
4830 // remove tmp 0D elements
4832 set< const SMDS_MeshElement* > removed0D;
4833 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
4835 if ( removed0D.insert( tmp0Delems[i] ).second )
4836 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
4838 SMESH_CATCH( SMESH::throwCorbaException );
4843 //=======================================================================
4844 //function : SewFreeBorders
4846 //=======================================================================
4848 SMESH::SMESH_MeshEditor::Sew_Error
4849 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4850 CORBA::Long SecondNodeID1,
4851 CORBA::Long LastNodeID1,
4852 CORBA::Long FirstNodeID2,
4853 CORBA::Long SecondNodeID2,
4854 CORBA::Long LastNodeID2,
4855 CORBA::Boolean CreatePolygons,
4856 CORBA::Boolean CreatePolyedrs)
4857 throw (SALOME::SALOME_Exception)
4862 SMESHDS_Mesh* aMesh = getMeshDS();
4864 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4865 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4866 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4867 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4868 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4869 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
4871 if (!aBorderFirstNode ||
4872 !aBorderSecondNode||
4874 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4875 if (!aSide2FirstNode ||
4876 !aSide2SecondNode ||
4878 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4880 TPythonDump() << "error = " << this << ".SewFreeBorders( "
4881 << FirstNodeID1 << ", "
4882 << SecondNodeID1 << ", "
4883 << LastNodeID1 << ", "
4884 << FirstNodeID2 << ", "
4885 << SecondNodeID2 << ", "
4886 << LastNodeID2 << ", "
4887 << CreatePolygons<< ", "
4888 << CreatePolyedrs<< " )";
4890 SMESH::SMESH_MeshEditor::Sew_Error error =
4891 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4902 declareMeshModified( /*isReComputeSafe=*/false );
4905 SMESH_CATCH( SMESH::throwCorbaException );
4906 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4910 //=======================================================================
4911 //function : SewConformFreeBorders
4913 //=======================================================================
4915 SMESH::SMESH_MeshEditor::Sew_Error
4916 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4917 CORBA::Long SecondNodeID1,
4918 CORBA::Long LastNodeID1,
4919 CORBA::Long FirstNodeID2,
4920 CORBA::Long SecondNodeID2)
4921 throw (SALOME::SALOME_Exception)
4926 SMESHDS_Mesh* aMesh = getMeshDS();
4928 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
4929 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4930 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
4931 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
4932 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
4933 const SMDS_MeshNode* aSide2ThirdNode = 0;
4935 if (!aBorderFirstNode ||
4936 !aBorderSecondNode||
4938 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4939 if (!aSide2FirstNode ||
4941 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4943 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4944 << FirstNodeID1 << ", "
4945 << SecondNodeID1 << ", "
4946 << LastNodeID1 << ", "
4947 << FirstNodeID2 << ", "
4948 << SecondNodeID2 << " )";
4950 SMESH::SMESH_MeshEditor::Sew_Error error =
4951 convError( getEditor().SewFreeBorder (aBorderFirstNode,
4960 declareMeshModified( /*isReComputeSafe=*/false );
4963 SMESH_CATCH( SMESH::throwCorbaException );
4964 return SMESH::SMESH_MeshEditor::Sew_Error(0);
4968 //=======================================================================
4969 //function : SewBorderToSide
4971 //=======================================================================
4973 SMESH::SMESH_MeshEditor::Sew_Error
4974 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4975 CORBA::Long SecondNodeIDOnFreeBorder,
4976 CORBA::Long LastNodeIDOnFreeBorder,
4977 CORBA::Long FirstNodeIDOnSide,
4978 CORBA::Long LastNodeIDOnSide,
4979 CORBA::Boolean CreatePolygons,
4980 CORBA::Boolean CreatePolyedrs)
4981 throw (SALOME::SALOME_Exception)
4986 SMESHDS_Mesh* aMesh = getMeshDS();
4988 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
4989 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4990 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
4991 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
4992 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
4993 const SMDS_MeshNode* aSide2ThirdNode = 0;
4995 if (!aBorderFirstNode ||
4996 !aBorderSecondNode||
4998 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4999 if (!aSide2FirstNode ||
5001 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5003 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5004 << FirstNodeIDOnFreeBorder << ", "
5005 << SecondNodeIDOnFreeBorder << ", "
5006 << LastNodeIDOnFreeBorder << ", "
5007 << FirstNodeIDOnSide << ", "
5008 << LastNodeIDOnSide << ", "
5009 << CreatePolygons << ", "
5010 << CreatePolyedrs << ") ";
5012 SMESH::SMESH_MeshEditor::Sew_Error error =
5013 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5023 declareMeshModified( /*isReComputeSafe=*/false );
5026 SMESH_CATCH( SMESH::throwCorbaException );
5027 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5031 //=======================================================================
5032 //function : SewSideElements
5034 //=======================================================================
5036 SMESH::SMESH_MeshEditor::Sew_Error
5037 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5038 const SMESH::long_array& IDsOfSide2Elements,
5039 CORBA::Long NodeID1OfSide1ToMerge,
5040 CORBA::Long NodeID1OfSide2ToMerge,
5041 CORBA::Long NodeID2OfSide1ToMerge,
5042 CORBA::Long NodeID2OfSide2ToMerge)
5043 throw (SALOME::SALOME_Exception)
5048 SMESHDS_Mesh* aMesh = getMeshDS();
5050 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5051 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5052 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5053 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5055 if (!aFirstNode1ToMerge ||
5056 !aFirstNode2ToMerge )
5057 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5058 if (!aSecondNode1ToMerge||
5059 !aSecondNode2ToMerge)
5060 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5062 TIDSortedElemSet aSide1Elems, aSide2Elems;
5063 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5064 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5066 TPythonDump() << "error = " << this << ".SewSideElements( "
5067 << IDsOfSide1Elements << ", "
5068 << IDsOfSide2Elements << ", "
5069 << NodeID1OfSide1ToMerge << ", "
5070 << NodeID1OfSide2ToMerge << ", "
5071 << NodeID2OfSide1ToMerge << ", "
5072 << NodeID2OfSide2ToMerge << ")";
5074 SMESH::SMESH_MeshEditor::Sew_Error error =
5075 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5078 aSecondNode1ToMerge,
5079 aSecondNode2ToMerge));
5081 declareMeshModified( /*isReComputeSafe=*/false );
5084 SMESH_CATCH( SMESH::throwCorbaException );
5085 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5088 //================================================================================
5090 * \brief Set new nodes for given element
5091 * \param ide - element id
5092 * \param newIDs - new node ids
5093 * \retval CORBA::Boolean - true if result is OK
5095 //================================================================================
5097 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5098 const SMESH::long_array& newIDs)
5099 throw (SALOME::SALOME_Exception)
5104 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5105 if(!elem) return false;
5107 int nbn = newIDs.length();
5109 vector<const SMDS_MeshNode*> aNodes(nbn);
5112 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5115 aNodes[nbn1] = aNode;
5118 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5119 << ide << ", " << newIDs << " )";
5121 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5123 declareMeshModified( /*isReComputeSafe=*/ !res );
5127 SMESH_CATCH( SMESH::throwCorbaException );
5131 //=======================================================================
5133 * \brief Makes a part of the mesh quadratic or bi-quadratic
5135 //=======================================================================
5137 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5138 CORBA::Boolean theToBiQuad,
5139 SMESH::SMESH_IDSource_ptr theObject)
5140 throw (SALOME::SALOME_Exception)
5145 TIDSortedElemSet elems;
5147 if ( !( elemsOK = CORBA::is_nil( theObject )))
5149 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5150 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5154 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5155 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5157 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5158 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5160 declareMeshModified( /*isReComputeSafe=*/false );
5163 SMESH_CATCH( SMESH::throwCorbaException );
5166 //=======================================================================
5167 //function : ConvertFromQuadratic
5169 //=======================================================================
5171 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5172 throw (SALOME::SALOME_Exception)
5177 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5178 TPythonDump() << this << ".ConvertFromQuadratic()";
5179 declareMeshModified( /*isReComputeSafe=*/!isDone );
5182 SMESH_CATCH( SMESH::throwCorbaException );
5186 //=======================================================================
5187 //function : ConvertToQuadratic
5189 //=======================================================================
5191 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5192 throw (SALOME::SALOME_Exception)
5194 convertToQuadratic( theForce3d, false );
5195 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5198 //================================================================================
5200 * \brief Makes a part of the mesh quadratic
5202 //================================================================================
5204 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5205 SMESH::SMESH_IDSource_ptr theObject)
5206 throw (SALOME::SALOME_Exception)
5208 convertToQuadratic( theForce3d, false, theObject );
5209 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5212 //================================================================================
5214 * \brief Makes a part of the mesh bi-quadratic
5216 //================================================================================
5218 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5219 SMESH::SMESH_IDSource_ptr theObject)
5220 throw (SALOME::SALOME_Exception)
5222 convertToQuadratic( theForce3d, true, theObject );
5223 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5226 //================================================================================
5228 * \brief Makes a part of the mesh linear
5230 //================================================================================
5232 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5233 throw (SALOME::SALOME_Exception)
5240 TIDSortedElemSet elems;
5241 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5243 if ( elems.empty() )
5245 ConvertFromQuadratic();
5247 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5249 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5253 getEditor().ConvertFromQuadratic(elems);
5256 declareMeshModified( /*isReComputeSafe=*/false );
5258 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5260 SMESH_CATCH( SMESH::throwCorbaException );
5263 //=======================================================================
5264 //function : makeMesh
5265 //purpose : create a named imported mesh
5266 //=======================================================================
5268 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5270 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5271 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5272 SALOMEDS::Study_var study = gen->GetCurrentStudy();
5273 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5274 gen->SetName( meshSO, theMeshName, "Mesh" );
5275 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5277 return mesh._retn();
5280 //=======================================================================
5281 //function : dumpGroupsList
5283 //=======================================================================
5285 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5286 const SMESH::ListOfGroups * theGroupList)
5288 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5289 if ( isDumpGroupList )
5290 theDumpPython << theGroupList << " = ";
5293 //================================================================================
5295 \brief Generates the unique group name.
5296 \param thePrefix name prefix
5299 //================================================================================
5301 std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
5303 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5304 set<std::string> groupNames;
5306 // Get existing group names
5307 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5308 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5309 if (CORBA::is_nil(aGroup))
5312 CORBA::String_var name = aGroup->GetName();
5313 groupNames.insert( name.in() );
5317 std::string name = thePrefix;
5320 while (!groupNames.insert(name).second)
5321 name = SMESH_Comment( thePrefix ) << "_" << index++;
5326 //================================================================================
5328 * \brief Prepare SMESH_IDSource for work
5330 //================================================================================
5332 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5334 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5336 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5337 filter->SetMesh( mesh );
5340 //================================================================================
5342 * \brief Retrieve elements of given type from SMESH_IDSource
5344 //================================================================================
5346 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5347 const SMESHDS_Mesh* theMeshDS,
5348 TIDSortedElemSet& theElemSet,
5349 const SMDSAbs_ElementType theType,
5350 const bool emptyIfIsMesh,
5351 IDSource_Error* error)
5354 if ( error ) *error = IDSource_OK;
5356 if ( CORBA::is_nil( theIDSource ))
5358 if ( error ) *error = IDSource_INVALID;
5361 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5363 if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
5364 *error = IDSource_EMPTY;
5367 prepareIdSource( theIDSource );
5368 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5369 if ( anIDs->length() == 0 )
5371 if ( error ) *error = IDSource_EMPTY;
5374 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5375 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5377 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5379 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5383 if ( error ) *error = IDSource_INVALID;
5389 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5390 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5392 if ( error ) *error = IDSource_INVALID;
5399 //================================================================================
5401 * \brief Duplicates given elements, i.e. creates new elements based on the
5402 * same nodes as the given ones.
5403 * \param theElements - container of elements to duplicate.
5404 * \param theGroupName - a name of group to contain the generated elements.
5405 * If a group with such a name already exists, the new elements
5406 * are added to the existng group, else a new group is created.
5407 * If \a theGroupName is empty, new elements are not added
5409 * \return a group where the new elements are added. NULL if theGroupName == "".
5412 //================================================================================
5414 SMESH::SMESH_Group_ptr
5415 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5416 const char* theGroupName)
5417 throw (SALOME::SALOME_Exception)
5419 SMESH::SMESH_Group_var newGroup;
5426 TIDSortedElemSet elems;
5427 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5429 getEditor().DoubleElements( elems );
5431 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5434 SMESH::ElementType type =
5435 SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5436 // find existing group
5437 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5438 for ( size_t i = 0; i < groups->length(); ++i )
5439 if ( groups[i]->GetType() == type )
5441 CORBA::String_var name = groups[i]->GetName();
5442 if ( strcmp( name, theGroupName ) == 0 ) {
5443 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5447 // create a new group
5448 if ( newGroup->_is_nil() )
5449 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5451 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5453 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5454 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5455 for ( int i = 1; i <= aSeq.Length(); i++ )
5456 groupDS->SMDSGroup().Add( aSeq(i) );
5461 if ( !newGroup->_is_nil() )
5462 pyDump << newGroup << " = ";
5463 pyDump << this << ".DoubleElements( "
5464 << theElements << ", " << "'" << theGroupName <<"')";
5466 SMESH_CATCH( SMESH::throwCorbaException );
5468 return newGroup._retn();
5471 //================================================================================
5473 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5474 \param theNodes - identifiers of nodes to be doubled
5475 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5476 nodes. If list of element identifiers is empty then nodes are doubled but
5477 they not assigned to elements
5478 \return TRUE if operation has been completed successfully, FALSE otherwise
5479 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5481 //================================================================================
5483 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5484 const SMESH::long_array& theModifiedElems )
5485 throw (SALOME::SALOME_Exception)
5490 list< int > aListOfNodes;
5492 for ( i = 0, n = theNodes.length(); i < n; i++ )
5493 aListOfNodes.push_back( theNodes[ i ] );
5495 list< int > aListOfElems;
5496 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5497 aListOfElems.push_back( theModifiedElems[ i ] );
5499 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5501 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5503 // Update Python script
5504 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5508 SMESH_CATCH( SMESH::throwCorbaException );
5512 //================================================================================
5514 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5515 This method provided for convenience works as DoubleNodes() described above.
5516 \param theNodeId - identifier of node to be doubled.
5517 \param theModifiedElems - identifiers of elements to be updated.
5518 \return TRUE if operation has been completed successfully, FALSE otherwise
5519 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5521 //================================================================================
5523 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5524 const SMESH::long_array& theModifiedElems )
5525 throw (SALOME::SALOME_Exception)
5528 SMESH::long_array_var aNodes = new SMESH::long_array;
5529 aNodes->length( 1 );
5530 aNodes[ 0 ] = theNodeId;
5532 TPythonDump pyDump; // suppress dump by the next line
5534 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5536 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5540 SMESH_CATCH( SMESH::throwCorbaException );
5544 //================================================================================
5546 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5547 This method provided for convenience works as DoubleNodes() described above.
5548 \param theNodes - group of nodes to be doubled.
5549 \param theModifiedElems - group of elements to be updated.
5550 \return TRUE if operation has been completed successfully, FALSE otherwise
5551 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5553 //================================================================================
5555 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5556 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5557 throw (SALOME::SALOME_Exception)
5560 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5563 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5564 SMESH::long_array_var aModifiedElems;
5565 if ( !CORBA::is_nil( theModifiedElems ) )
5566 aModifiedElems = theModifiedElems->GetListOfID();
5569 aModifiedElems = new SMESH::long_array;
5570 aModifiedElems->length( 0 );
5573 TPythonDump pyDump; // suppress dump by the next line
5575 bool done = DoubleNodes( aNodes, aModifiedElems );
5577 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5581 SMESH_CATCH( SMESH::throwCorbaException );
5585 //================================================================================
5587 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5588 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5589 * \param theNodes - group of nodes to be doubled.
5590 * \param theModifiedElems - group of elements to be updated.
5591 * \return a new group with newly created nodes
5592 * \sa DoubleNodeGroup()
5594 //================================================================================
5596 SMESH::SMESH_Group_ptr
5597 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5598 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5599 throw (SALOME::SALOME_Exception)
5602 SMESH::SMESH_Group_var aNewGroup;
5604 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5605 return aNewGroup._retn();
5608 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5609 SMESH::long_array_var aModifiedElems;
5610 if ( !CORBA::is_nil( theModifiedElems ) )
5611 aModifiedElems = theModifiedElems->GetListOfID();
5613 aModifiedElems = new SMESH::long_array;
5614 aModifiedElems->length( 0 );
5617 TPythonDump pyDump; // suppress dump by the next line
5619 bool aResult = DoubleNodes( aNodes, aModifiedElems );
5622 // Create group with newly created nodes
5623 SMESH::long_array_var anIds = GetLastCreatedNodes();
5624 if (anIds->length() > 0) {
5625 std::string anUnindexedName (theNodes->GetName());
5626 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5627 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5628 aNewGroup->Add(anIds);
5629 pyDump << aNewGroup << " = ";
5633 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5634 << theModifiedElems << " )";
5636 return aNewGroup._retn();
5638 SMESH_CATCH( SMESH::throwCorbaException );
5642 //================================================================================
5644 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5645 This method provided for convenience works as DoubleNodes() described above.
5646 \param theNodes - list of groups of nodes to be doubled
5647 \param theModifiedElems - list of groups of elements to be updated.
5648 \return TRUE if operation has been completed successfully, FALSE otherwise
5649 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5651 //================================================================================
5653 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5654 const SMESH::ListOfGroups& theModifiedElems )
5655 throw (SALOME::SALOME_Exception)
5660 std::list< int > aNodes;
5662 for ( i = 0, n = theNodes.length(); i < n; i++ )
5664 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5665 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5667 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5668 for ( j = 0, m = aCurr->length(); j < m; j++ )
5669 aNodes.push_back( aCurr[ j ] );
5673 std::list< int > anElems;
5674 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5676 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5677 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5679 SMESH::long_array_var aCurr = aGrp->GetListOfID();
5680 for ( j = 0, m = aCurr->length(); j < m; j++ )
5681 anElems.push_back( aCurr[ j ] );
5685 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
5687 declareMeshModified( /*isReComputeSafe=*/false );
5689 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5693 SMESH_CATCH( SMESH::throwCorbaException );
5697 //================================================================================
5699 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5700 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5701 * \param theNodes - group of nodes to be doubled.
5702 * \param theModifiedElems - group of elements to be updated.
5703 * \return a new group with newly created nodes
5704 * \sa DoubleNodeGroups()
5706 //================================================================================
5708 SMESH::SMESH_Group_ptr
5709 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5710 const SMESH::ListOfGroups& theModifiedElems )
5711 throw (SALOME::SALOME_Exception)
5713 SMESH::SMESH_Group_var aNewGroup;
5715 TPythonDump pyDump; // suppress dump by the next line
5717 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5721 // Create group with newly created nodes
5722 SMESH::long_array_var anIds = GetLastCreatedNodes();
5723 if (anIds->length() > 0) {
5724 std::string anUnindexedName (theNodes[0]->GetName());
5725 std::string aNewName = generateGroupName(anUnindexedName + "_double");
5726 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5727 aNewGroup->Add(anIds);
5728 pyDump << aNewGroup << " = ";
5732 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5733 << theModifiedElems << " )";
5735 return aNewGroup._retn();
5739 //================================================================================
5741 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5742 \param theElems - the list of elements (edges or faces) to be replicated
5743 The nodes for duplication could be found from these elements
5744 \param theNodesNot - list of nodes to NOT replicate
5745 \param theAffectedElems - the list of elements (cells and edges) to which the
5746 replicated nodes should be associated to.
5747 \return TRUE if operation has been completed successfully, FALSE otherwise
5748 \sa DoubleNodeGroup(), DoubleNodeGroups()
5750 //================================================================================
5752 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5753 const SMESH::long_array& theNodesNot,
5754 const SMESH::long_array& theAffectedElems )
5755 throw (SALOME::SALOME_Exception)
5760 SMESHDS_Mesh* aMeshDS = getMeshDS();
5761 TIDSortedElemSet anElems, aNodes, anAffected;
5762 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5763 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5764 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5766 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5768 // Update Python script
5769 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5770 << theNodesNot << ", " << theAffectedElems << " )";
5772 declareMeshModified( /*isReComputeSafe=*/false );
5775 SMESH_CATCH( SMESH::throwCorbaException );
5779 //================================================================================
5781 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5782 \param theElems - the list of elements (edges or faces) to be replicated
5783 The nodes for duplication could be found from these elements
5784 \param theNodesNot - list of nodes to NOT replicate
5785 \param theShape - shape to detect affected elements (element which geometric center
5786 located on or inside shape).
5787 The replicated nodes should be associated to affected elements.
5788 \return TRUE if operation has been completed successfully, FALSE otherwise
5789 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5791 //================================================================================
5793 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5794 const SMESH::long_array& theNodesNot,
5795 GEOM::GEOM_Object_ptr theShape )
5796 throw (SALOME::SALOME_Exception)
5802 SMESHDS_Mesh* aMeshDS = getMeshDS();
5803 TIDSortedElemSet anElems, aNodes;
5804 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5805 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5807 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5808 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
5810 // Update Python script
5811 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5812 << theNodesNot << ", " << theShape << " )";
5814 declareMeshModified( /*isReComputeSafe=*/false );
5817 SMESH_CATCH( SMESH::throwCorbaException );
5821 //================================================================================
5823 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5824 \param theElems - group of of elements (edges or faces) to be replicated
5825 \param theNodesNot - group of nodes not to replicated
5826 \param theAffectedElems - group of elements to which the replicated nodes
5827 should be associated to.
5828 \return TRUE if operation has been completed successfully, FALSE otherwise
5829 \sa DoubleNodes(), DoubleNodeGroups()
5831 //================================================================================
5834 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5835 SMESH::SMESH_GroupBase_ptr theNodesNot,
5836 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5837 throw (SALOME::SALOME_Exception)
5840 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5846 SMESHDS_Mesh* aMeshDS = getMeshDS();
5847 TIDSortedElemSet anElems, aNodes, anAffected;
5848 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5849 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5850 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5852 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5854 // Update Python script
5855 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5856 << theNodesNot << ", " << theAffectedElems << " )";
5858 declareMeshModified( /*isReComputeSafe=*/false );
5861 SMESH_CATCH( SMESH::throwCorbaException );
5865 //================================================================================
5867 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5868 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5869 * \param theElems - group of of elements (edges or faces) to be replicated
5870 * \param theNodesNot - group of nodes not to replicated
5871 * \param theAffectedElems - group of elements to which the replicated nodes
5872 * should be associated to.
5873 * \return a new group with newly created elements
5874 * \sa DoubleNodeElemGroup()
5876 //================================================================================
5878 SMESH::SMESH_Group_ptr
5879 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5880 SMESH::SMESH_GroupBase_ptr theNodesNot,
5881 SMESH::SMESH_GroupBase_ptr theAffectedElems)
5882 throw (SALOME::SALOME_Exception)
5885 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
5889 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
5890 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
5892 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
5894 << theNodesNot << ", "
5895 << theAffectedElems << " )";
5897 return elemGroup._retn();
5900 //================================================================================
5902 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5903 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5904 * \param theElems - group of of elements (edges or faces) to be replicated
5905 * \param theNodesNot - group of nodes not to replicated
5906 * \param theAffectedElems - group of elements to which the replicated nodes
5907 * should be associated to.
5908 * \return a new group with newly created elements
5909 * \sa DoubleNodeElemGroup()
5911 //================================================================================
5913 SMESH::ListOfGroups*
5914 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
5915 SMESH::SMESH_GroupBase_ptr theNodesNot,
5916 SMESH::SMESH_GroupBase_ptr theAffectedElems,
5917 CORBA::Boolean theElemGroupNeeded,
5918 CORBA::Boolean theNodeGroupNeeded)
5919 throw (SALOME::SALOME_Exception)
5922 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
5923 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
5924 aTwoGroups->length( 2 );
5926 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5927 return aTwoGroups._retn();
5932 SMESHDS_Mesh* aMeshDS = getMeshDS();
5933 TIDSortedElemSet anElems, aNodes, anAffected;
5934 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5935 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5936 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5939 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
5941 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5947 // Create group with newly created elements
5948 CORBA::String_var elemGroupName = theElems->GetName();
5949 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
5950 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
5952 SMESH::long_array_var anIds = GetLastCreatedElems();
5953 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5954 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5955 aNewElemGroup->Add(anIds);
5957 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
5959 SMESH::long_array_var anIds = GetLastCreatedNodes();
5960 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5961 aNewNodeGroup->Add(anIds);
5965 // Update Python script
5968 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
5969 else pyDump << aNewElemGroup << ", ";
5970 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
5971 else pyDump << aNewNodeGroup << " ] = ";
5973 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
5974 << theNodesNot << ", "
5975 << theAffectedElems << ", "
5976 << theElemGroupNeeded << ", "
5977 << theNodeGroupNeeded <<" )";
5979 aTwoGroups[0] = aNewElemGroup._retn();
5980 aTwoGroups[1] = aNewNodeGroup._retn();
5981 return aTwoGroups._retn();
5983 SMESH_CATCH( SMESH::throwCorbaException );
5987 //================================================================================
5989 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5990 \param theElems - group of of elements (edges or faces) to be replicated
5991 \param theNodesNot - group of nodes not to replicated
5992 \param theShape - shape to detect affected elements (element which geometric center
5993 located on or inside shape).
5994 The replicated nodes should be associated to affected elements.
5995 \return TRUE if operation has been completed successfully, FALSE otherwise
5996 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5998 //================================================================================
6001 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6002 SMESH::SMESH_GroupBase_ptr theNodesNot,
6003 GEOM::GEOM_Object_ptr theShape )
6004 throw (SALOME::SALOME_Exception)
6007 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6013 SMESHDS_Mesh* aMeshDS = getMeshDS();
6014 TIDSortedElemSet anElems, aNodes, anAffected;
6015 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6016 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6018 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6019 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6022 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6024 // Update Python script
6025 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6026 << theNodesNot << ", " << theShape << " )";
6029 SMESH_CATCH( SMESH::throwCorbaException );
6033 //================================================================================
6035 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6036 * \param [in] theGrpList - groups
6037 * \param [in] theMeshDS - mesh
6038 * \param [out] theElemSet - set of elements
6039 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6041 //================================================================================
6043 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6044 SMESHDS_Mesh* theMeshDS,
6045 TIDSortedElemSet& theElemSet,
6046 const bool theIsNodeGrp)
6048 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6050 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6051 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6052 : aGrp->GetType() != SMESH::NODE ) )
6054 SMESH::long_array_var anIDs = aGrp->GetIDs();
6055 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6060 //================================================================================
6062 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6063 This method provided for convenience works as DoubleNodes() described above.
6064 \param theElems - list of groups of elements (edges or faces) to be replicated
6065 \param theNodesNot - list of groups of nodes not to replicated
6066 \param theAffectedElems - group of elements to which the replicated nodes
6067 should be associated to.
6068 \return TRUE if operation has been completed successfully, FALSE otherwise
6069 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6071 //================================================================================
6074 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6075 const SMESH::ListOfGroups& theNodesNot,
6076 const SMESH::ListOfGroups& theAffectedElems)
6077 throw (SALOME::SALOME_Exception)
6083 SMESHDS_Mesh* aMeshDS = getMeshDS();
6084 TIDSortedElemSet anElems, aNodes, anAffected;
6085 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6086 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6087 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6089 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6091 // Update Python script
6092 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6093 << &theNodesNot << ", " << &theAffectedElems << " )";
6095 declareMeshModified( /*isReComputeSafe=*/false );
6098 SMESH_CATCH( SMESH::throwCorbaException );
6102 //================================================================================
6104 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6105 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6106 \param theElems - list of groups of elements (edges or faces) to be replicated
6107 \param theNodesNot - list of groups of nodes not to replicated
6108 \param theAffectedElems - group of elements to which the replicated nodes
6109 should be associated to.
6110 * \return a new group with newly created elements
6111 * \sa DoubleNodeElemGroups()
6113 //================================================================================
6115 SMESH::SMESH_Group_ptr
6116 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6117 const SMESH::ListOfGroups& theNodesNot,
6118 const SMESH::ListOfGroups& theAffectedElems)
6119 throw (SALOME::SALOME_Exception)
6122 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6126 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6127 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6129 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6131 << theNodesNot << ", "
6132 << theAffectedElems << " )";
6134 return elemGroup._retn();
6137 //================================================================================
6139 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6140 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6141 \param theElems - list of groups of elements (edges or faces) to be replicated
6142 \param theNodesNot - list of groups of nodes not to replicated
6143 \param theAffectedElems - group of elements to which the replicated nodes
6144 should be associated to.
6145 * \return a new group with newly created elements
6146 * \sa DoubleNodeElemGroups()
6148 //================================================================================
6150 SMESH::ListOfGroups*
6151 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6152 const SMESH::ListOfGroups& theNodesNot,
6153 const SMESH::ListOfGroups& theAffectedElems,
6154 CORBA::Boolean theElemGroupNeeded,
6155 CORBA::Boolean theNodeGroupNeeded)
6156 throw (SALOME::SALOME_Exception)
6159 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6160 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6161 aTwoGroups->length( 2 );
6166 SMESHDS_Mesh* aMeshDS = getMeshDS();
6167 TIDSortedElemSet anElems, aNodes, anAffected;
6168 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6169 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6170 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6172 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6174 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6179 // Create group with newly created elements
6180 CORBA::String_var elemGroupName = theElems[0]->GetName();
6181 std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
6182 if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6184 SMESH::long_array_var anIds = GetLastCreatedElems();
6185 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6186 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6187 aNewElemGroup->Add(anIds);
6189 if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6191 SMESH::long_array_var anIds = GetLastCreatedNodes();
6192 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6193 aNewNodeGroup->Add(anIds);
6197 // Update Python script
6200 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6201 else pyDump << aNewElemGroup << ", ";
6202 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6203 else pyDump << aNewNodeGroup << " ] = ";
6205 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6206 << &theNodesNot << ", "
6207 << &theAffectedElems << ", "
6208 << theElemGroupNeeded << ", "
6209 << theNodeGroupNeeded << " )";
6211 aTwoGroups[0] = aNewElemGroup._retn();
6212 aTwoGroups[1] = aNewNodeGroup._retn();
6213 return aTwoGroups._retn();
6215 SMESH_CATCH( SMESH::throwCorbaException );
6219 //================================================================================
6221 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6222 This method provided for convenience works as DoubleNodes() described above.
6223 \param theElems - list of groups of elements (edges or faces) to be replicated
6224 \param theNodesNot - list of groups of nodes not to replicated
6225 \param theShape - shape to detect affected elements (element which geometric center
6226 located on or inside shape).
6227 The replicated nodes should be associated to affected elements.
6228 \return TRUE if operation has been completed successfully, FALSE otherwise
6229 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6231 //================================================================================
6234 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6235 const SMESH::ListOfGroups& theNodesNot,
6236 GEOM::GEOM_Object_ptr theShape )
6237 throw (SALOME::SALOME_Exception)
6243 SMESHDS_Mesh* aMeshDS = getMeshDS();
6244 TIDSortedElemSet anElems, aNodes;
6245 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6246 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6248 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6249 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6251 // Update Python script
6252 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6253 << &theNodesNot << ", " << theShape << " )";
6255 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6258 SMESH_CATCH( SMESH::throwCorbaException );
6262 //================================================================================
6264 \brief Identify the elements that will be affected by node duplication (actual
6265 duplication is not performed.
6266 This method is the first step of DoubleNodeElemGroupsInRegion.
6267 \param theElems - list of groups of elements (edges or faces) to be replicated
6268 \param theNodesNot - list of groups of nodes not to replicated
6269 \param theShape - shape to detect affected elements (element which geometric center
6270 located on or inside shape).
6271 The replicated nodes should be associated to affected elements.
6272 \return groups of affected elements
6273 \sa DoubleNodeElemGroupsInRegion()
6275 //================================================================================
6276 SMESH::ListOfGroups*
6277 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6278 const SMESH::ListOfGroups& theNodesNot,
6279 GEOM::GEOM_Object_ptr theShape )
6280 throw (SALOME::SALOME_Exception)
6283 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6284 bool isEdgeGroup = false;
6285 bool isFaceGroup = false;
6286 bool isVolumeGroup = false;
6287 SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6288 SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6289 SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6293 ::SMESH_MeshEditor aMeshEditor(myMesh);
6295 SMESHDS_Mesh* aMeshDS = getMeshDS();
6296 TIDSortedElemSet anElems, aNodes;
6297 listOfGroupToSet(theElems, aMeshDS, anElems, false);
6298 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6300 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6301 TIDSortedElemSet anAffected;
6302 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6305 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6310 int lg = anAffected.size();
6311 SMESH::long_array_var volumeIds = new SMESH::long_array;
6312 volumeIds->length(lg);
6313 SMESH::long_array_var faceIds = new SMESH::long_array;
6314 faceIds->length(lg);
6315 SMESH::long_array_var edgeIds = new SMESH::long_array;
6316 edgeIds->length(lg);
6321 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6322 for (; eIt != anAffected.end(); ++eIt)
6324 const SMDS_MeshElement* anElem = *eIt;
6327 int elemId = anElem->GetID();
6328 if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6329 volumeIds[ivol++] = elemId;
6330 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6331 faceIds[iface++] = elemId;
6332 else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6333 edgeIds[iedge++] = elemId;
6335 volumeIds->length(ivol);
6336 faceIds->length(iface);
6337 edgeIds->length(iedge);
6339 aNewVolumeGroup->Add(volumeIds);
6340 aNewFaceGroup->Add(faceIds);
6341 aNewEdgeGroup->Add(edgeIds);
6342 isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6343 isFaceGroup = (aNewFaceGroup->Size() > 0);
6344 isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6348 if (isEdgeGroup) nbGroups++;
6349 if (isFaceGroup) nbGroups++;
6350 if (isVolumeGroup) nbGroups++;
6351 aListOfGroups->length(nbGroups);
6354 if (isEdgeGroup) aListOfGroups[i++] = aNewEdgeGroup._retn();
6355 if (isFaceGroup) aListOfGroups[i++] = aNewFaceGroup._retn();
6356 if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6358 // Update Python script
6361 if (isEdgeGroup) pyDump << aNewEdgeGroup << ", ";
6362 if (isFaceGroup) pyDump << aNewFaceGroup << ", ";
6363 if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6365 pyDump << this << ".AffectedElemGroupsInRegion( "
6366 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6368 return aListOfGroups._retn();
6370 SMESH_CATCH( SMESH::throwCorbaException );
6374 //================================================================================
6376 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6377 The created 2D mesh elements based on nodes of free faces of boundary volumes
6378 \return TRUE if operation has been completed successfully, FALSE otherwise
6380 //================================================================================
6382 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6383 throw (SALOME::SALOME_Exception)
6388 bool aResult = getEditor().Make2DMeshFrom3D();
6390 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6392 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6395 SMESH_CATCH( SMESH::throwCorbaException );
6399 //================================================================================
6401 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6402 * The list of groups must contain at least two groups. The groups have to be disjoint:
6403 * no common element into two different groups.
6404 * The nodes of the internal faces at the boundaries of the groups are doubled.
6405 * Optionally, the internal faces are replaced by flat elements.
6406 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6407 * The flat elements are stored in groups of volumes.
6408 * These groups are named according to the position of the group in the list:
6409 * 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.
6410 * 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.
6411 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6412 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6413 * \param theDomains - list of groups of volumes
6414 * \param createJointElems - if TRUE, create the elements
6415 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6416 * the boundary between \a theDomains and the rest mesh
6417 * \return TRUE if operation has been completed successfully, FALSE otherwise
6419 //================================================================================
6422 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6423 CORBA::Boolean createJointElems,
6424 CORBA::Boolean onAllBoundaries )
6425 throw (SALOME::SALOME_Exception)
6432 SMESHDS_Mesh* aMeshDS = getMeshDS();
6434 // MESSAGE("theDomains.length = "<<theDomains.length());
6435 if ( theDomains.length() <= 1 && !onAllBoundaries )
6436 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6438 vector<TIDSortedElemSet> domains;
6439 domains.resize( theDomains.length() );
6441 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6443 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6444 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6446 // if ( aGrp->GetType() != SMESH::VOLUME )
6447 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6448 SMESH::long_array_var anIDs = aGrp->GetIDs();
6449 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6453 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6454 // TODO publish the groups of flat elements in study
6456 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6458 // Update Python script
6459 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6460 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6462 SMESH_CATCH( SMESH::throwCorbaException );
6464 myMesh_i->CreateGroupServants(); // publish created groups if any
6469 //================================================================================
6471 * \brief Double nodes on some external faces and create flat elements.
6472 * Flat elements are mainly used by some types of mechanic calculations.
6474 * Each group of the list must be constituted of faces.
6475 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6476 * @param theGroupsOfFaces - list of groups of faces
6477 * @return TRUE if operation has been completed successfully, FALSE otherwise
6479 //================================================================================
6482 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6483 throw (SALOME::SALOME_Exception)
6488 SMESHDS_Mesh* aMeshDS = getMeshDS();
6490 vector<TIDSortedElemSet> faceGroups;
6493 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6495 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6496 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6498 TIDSortedElemSet faceGroup;
6500 faceGroups.push_back(faceGroup);
6501 SMESH::long_array_var anIDs = aGrp->GetIDs();
6502 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6506 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6507 // TODO publish the groups of flat elements in study
6509 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6511 // Update Python script
6512 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6515 SMESH_CATCH( SMESH::throwCorbaException );
6519 //================================================================================
6521 * \brief Identify all the elements around a geom shape, get the faces delimiting
6524 * Build groups of volume to remove, groups of faces to replace on the skin of the
6525 * object, groups of faces to remove inside the object, (idem edges).
6526 * Build ordered list of nodes at the border of each group of faces to replace
6527 * (to be used to build a geom subshape).
6529 //================================================================================
6531 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6532 GEOM::GEOM_Object_ptr theShape,
6533 const char* groupName,
6534 const SMESH::double_array& theNodesCoords,
6535 SMESH::array_of_long_array_out GroupsOfNodes)
6536 throw (SALOME::SALOME_Exception)
6541 std::vector<std::vector<int> > aListOfListOfNodes;
6542 ::SMESH_MeshEditor aMeshEditor( myMesh );
6544 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6545 if ( !theNodeSearcher )
6546 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6548 vector<double> nodesCoords;
6549 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6551 nodesCoords.push_back( theNodesCoords[i] );
6554 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6555 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6556 nodesCoords, aListOfListOfNodes);
6558 GroupsOfNodes = new SMESH::array_of_long_array;
6559 GroupsOfNodes->length( aListOfListOfNodes.size() );
6560 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6561 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6563 vector<int>& aListOfNodes = *llIt;
6564 vector<int>::iterator lIt = aListOfNodes.begin();;
6565 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6566 aGroup.length( aListOfNodes.size() );
6567 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6568 aGroup[ j ] = (*lIt);
6570 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6573 << ", '" << groupName << "', "
6574 << theNodesCoords << " )";
6576 SMESH_CATCH( SMESH::throwCorbaException );
6579 // issue 20749 ===================================================================
6581 * \brief Creates missing boundary elements
6582 * \param elements - elements whose boundary is to be checked
6583 * \param dimension - defines type of boundary elements to create
6584 * \param groupName - a name of group to store created boundary elements in,
6585 * "" means not to create the group
6586 * \param meshName - a name of new mesh to store created boundary elements in,
6587 * "" means not to create the new mesh
6588 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6589 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6590 * boundary elements will be copied into the new mesh
6591 * \param group - returns the create group, if any
6592 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6594 // ================================================================================
6596 SMESH::SMESH_Mesh_ptr
6597 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6598 SMESH::Bnd_Dimension dim,
6599 const char* groupName,
6600 const char* meshName,
6601 CORBA::Boolean toCopyElements,
6602 CORBA::Boolean toCopyExistingBondary,
6603 SMESH::SMESH_Group_out group)
6604 throw (SALOME::SALOME_Exception)
6609 if ( dim > SMESH::BND_1DFROM2D )
6610 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6612 SMESHDS_Mesh* aMeshDS = getMeshDS();
6614 SMESH::SMESH_Mesh_var mesh_var;
6615 SMESH::SMESH_Group_var group_var;
6619 TIDSortedElemSet elements;
6620 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
6621 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
6625 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
6626 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6628 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
6630 // group of new boundary elements
6631 SMESH_Group* smesh_group = 0;
6632 if ( strlen(groupName) )
6634 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
6635 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6636 smesh_group = group_i->GetSmeshGroup();
6640 getEditor().MakeBoundaryMesh( elements,
6641 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6645 toCopyExistingBondary);
6648 smesh_mesh->GetMeshDS()->Modified();
6651 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6653 // result of MakeBoundaryMesh() is a tuple (mesh, group)
6654 if ( mesh_var->_is_nil() )
6655 pyDump << myMesh_i->_this() << ", ";
6657 pyDump << mesh_var << ", ";
6658 if ( group_var->_is_nil() )
6659 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6661 pyDump << group_var << " = ";
6662 pyDump << this << ".MakeBoundaryMesh( "
6664 << "SMESH." << dimName[int(dim)] << ", "
6665 << "'" << groupName << "', "
6666 << "'" << meshName<< "', "
6667 << toCopyElements << ", "
6668 << toCopyExistingBondary << ")";
6670 group = group_var._retn();
6671 return mesh_var._retn();
6673 SMESH_CATCH( SMESH::throwCorbaException );
6674 return SMESH::SMESH_Mesh::_nil();
6677 //================================================================================
6679 * \brief Creates missing boundary elements
6680 * \param dimension - defines type of boundary elements to create
6681 * \param groupName - a name of group to store all boundary elements in,
6682 * "" means not to create the group
6683 * \param meshName - a name of a new mesh, which is a copy of the initial
6684 * mesh + created boundary elements; "" means not to create the new mesh
6685 * \param toCopyAll - if true, the whole initial mesh will be copied into
6686 * the new mesh else only boundary elements will be copied into the new mesh
6687 * \param groups - optional groups of elements to make boundary around
6688 * \param mesh - returns the mesh where elements were added to
6689 * \param group - returns the created group, if any
6690 * \retval long - number of added boundary elements
6692 //================================================================================
6694 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6695 const char* groupName,
6696 const char* meshName,
6697 CORBA::Boolean toCopyAll,
6698 const SMESH::ListOfIDSources& groups,
6699 SMESH::SMESH_Mesh_out mesh,
6700 SMESH::SMESH_Group_out group)
6701 throw (SALOME::SALOME_Exception)
6706 if ( dim > SMESH::BND_1DFROM2D )
6707 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6709 // separate groups belonging to this and other mesh
6710 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6711 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6712 groupsOfThisMesh ->length( groups.length() );
6713 groupsOfOtherMesh->length( groups.length() );
6714 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6715 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
6717 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6718 if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6719 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6721 groupsOfThisMesh[ nbGroups++ ] = groups[i];
6722 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6723 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
6725 groupsOfThisMesh->length( nbGroups );
6726 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6731 if ( nbGroupsOfOtherMesh > 0 )
6733 // process groups belonging to another mesh
6734 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
6735 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6736 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6737 groupsOfOtherMesh, mesh, group );
6740 SMESH::SMESH_Mesh_var mesh_var;
6741 SMESH::SMESH_Group_var group_var;
6744 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6745 const bool toCopyMesh = ( strlen( meshName ) > 0 );
6749 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6751 /*toCopyGroups=*/false,
6752 /*toKeepIDs=*/true);
6754 mesh_var = makeMesh(meshName);
6756 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6757 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
6760 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6761 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6763 // group of boundary elements
6764 SMESH_Group* smesh_group = 0;
6765 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6766 if ( strlen(groupName) )
6768 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6769 group_var = mesh_i->CreateGroup( groupType, groupName );
6770 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6771 smesh_group = group_i->GetSmeshGroup();
6774 TIDSortedElemSet elements;
6776 if ( groups.length() > 0 )
6778 for ( int i = 0; i < nbGroups; ++i )
6781 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6783 SMESH::Bnd_Dimension bdim =
6784 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6785 nbAdded += getEditor().MakeBoundaryMesh( elements,
6786 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6789 /*toCopyElements=*/false,
6790 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6791 /*toAddExistingBondary=*/true,
6792 /*aroundElements=*/true);
6798 nbAdded += getEditor().MakeBoundaryMesh( elements,
6799 ::SMESH_MeshEditor::Bnd_Dimension(dim),
6802 /*toCopyElements=*/false,
6803 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6804 /*toAddExistingBondary=*/true);
6806 tgtMesh->GetMeshDS()->Modified();
6808 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6810 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6811 pyDump << "nbAdded, ";
6812 if ( mesh_var->_is_nil() )
6813 pyDump << myMesh_i->_this() << ", ";
6815 pyDump << mesh_var << ", ";
6816 if ( group_var->_is_nil() )
6817 pyDump << "_NoneGroup = "; // assignment to None is forbidden
6819 pyDump << group_var << " = ";
6820 pyDump << this << ".MakeBoundaryElements( "
6821 << "SMESH." << dimName[int(dim)] << ", "
6822 << "'" << groupName << "', "
6823 << "'" << meshName<< "', "
6824 << toCopyAll << ", "
6827 mesh = mesh_var._retn();
6828 group = group_var._retn();
6831 SMESH_CATCH( SMESH::throwCorbaException );
6835 //================================================================================
6837 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
6838 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
6839 * plane passing through pairs of points specified by each PolySegment structure.
6840 * If there are several paths connecting a pair of points, the shortest path is
6841 * selected by the module. Position of the cutting plane is defined by the two
6842 * points and an optional vector lying on the plane specified by a PolySegment.
6843 * By default the vector is defined by Mesh module as following. A middle point
6844 * of the two given points is computed. The middle point is projected to the mesh.
6845 * The vector goes from the middle point to the projection point. In case of planar
6846 * mesh, the vector is normal to the mesh.
6847 * \param [inout] segments - PolySegment's defining positions of cutting planes.
6848 * Return the used vector and position of the middle point.
6849 * \param [in] groupName - optional name of a group where created mesh segments will
6852 //================================================================================
6854 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
6855 const char* theGroupName)
6856 throw (SALOME::SALOME_Exception)
6858 if ( theSegments.length() == 0 )
6859 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
6860 if ( myMesh->NbFaces() == 0 )
6861 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
6864 initData(/*deleteSearchers=*/false);
6866 SMESHDS_Group* groupDS = 0;
6867 if ( myIsPreviewMode ) // copy faces to the tmp mesh
6869 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
6870 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
6871 while ( faceIt->more() )
6872 tmpMesh->Copy( faceIt->next() );
6874 else if ( theGroupName[0] ) // find/create a group of segments
6876 SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
6877 while ( !groupDS && grpIt->more() )
6879 SMESH_Group* group = grpIt->next();
6880 if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
6881 strcmp( group->GetName(), theGroupName ) == 0 )
6883 groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
6888 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
6890 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
6891 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
6895 // convert input polySegments
6896 ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
6897 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
6899 SMESH::PolySegment& segIn = theSegments[ i ];
6900 ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
6901 segOut.myNode1[0] = getMeshDS()->FindNode( segIn.node1ID1 );
6902 segOut.myNode2[0] = getMeshDS()->FindNode( segIn.node1ID2 );
6903 segOut.myNode1[1] = getMeshDS()->FindNode( segIn.node2ID1 );
6904 segOut.myNode2[1] = getMeshDS()->FindNode( segIn.node2ID2 );
6905 segOut.myVector.SetCoord( segIn.vector.PS.x,
6907 segIn.vector.PS.z );
6908 if ( !segOut.myNode1[0] )
6909 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1,
6910 SALOME::BAD_PARAM );
6911 if ( !segOut.myNode1[1] )
6912 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1,
6913 SALOME::BAD_PARAM );
6916 // get a static ElementSearcher
6917 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
6918 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
6919 if ( !theElementSearcher )
6920 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
6923 getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
6926 if ( myIsPreviewMode )
6928 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
6930 SMESH::PolySegment& segOut = theSegments[ i ];
6931 ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
6932 segOut.vector.PS.x = segIn.myVector.X();
6933 segOut.vector.PS.y = segIn.myVector.Y();
6934 segOut.vector.PS.z = segIn.myVector.Z();
6939 TPythonDump() << "_segments = []";
6940 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
6942 SMESH::PolySegment& segIn = theSegments[ i ];
6943 TPythonDump() << "_segments.append( SMESH.PolySegment( "
6944 << segIn.node1ID1 << ", "
6945 << segIn.node1ID2 << ", "
6946 << segIn.node2ID1 << ", "
6947 << segIn.node2ID2 << ", "
6948 << "smeshBuilder.MakeDirStruct( "
6949 << segIn.vector.PS.x << ", "
6950 << segIn.vector.PS.y << ", "
6951 << segIn.vector.PS.z << ")))";
6953 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
6956 SMESH_CATCH( SMESH::throwCorbaException );