1 // Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _meshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< smIdType > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( smIdType i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _meshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) { delete theNodeSearcher; } theNodeSearcher = 0;
197 if ( theElementSearcher ) { delete theElementSearcher; } theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::smIdType_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::smIdType_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
528 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
530 if ( myIsPreviewMode || hasBadElems )
532 list<int> aNodesConnectivity;
533 typedef map<int, int> TNodesMap;
536 SMESHDS_Mesh* aMeshDS;
537 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
539 const list<const SMDS_MeshElement*>& badElems =
540 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
541 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
542 aMeshDS = aMeshPartDS.get();
545 aMeshDS = getEditor().GetMeshDS();
547 myPreviewData = new SMESH::MeshPreviewStruct();
548 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
551 SMDSAbs_ElementType previewType = SMDSAbs_All;
553 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
554 previewType = aPreviewMesh->myPreviewType;
555 switch ( previewType ) {
556 case SMDSAbs_Edge : break;
557 case SMDSAbs_Face : break;
558 case SMDSAbs_Volume: break;
560 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
564 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
566 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
568 while ( itMeshElems->more() ) {
569 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
570 SMDS_NodeIteratorPtr itElemNodes =
571 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
572 aMeshElem->interlacedNodesIterator() :
573 aMeshElem->nodeIterator() );
574 while ( itElemNodes->more() ) {
575 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
576 smIdType aNodeID = aMeshNode->GetID();
577 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
578 if ( anIter == nodesMap.end() ) {
579 // filling the nodes coordinates
580 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
581 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
582 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
583 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
586 aNodesConnectivity.push_back(anIter->second);
589 // filling the elements types
590 SMDSAbs_ElementType aType = aMeshElem->GetType();
591 bool isPoly = aMeshElem->IsPoly();
592 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
593 myPreviewData->elementTypes[i].isPoly = isPoly;
594 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
597 myPreviewData->nodesXYZ.length( j );
599 // filling the elements connectivities
600 list<int>::iterator aConnIter = aNodesConnectivity.begin();
601 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
602 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
603 myPreviewData->elementConnectivities[i] = *aConnIter;
605 return myPreviewData._retn();
607 SMESH_CATCH( SMESH::throwCorbaException );
611 //================================================================================
613 * \brief Returns list of it's IDs of created nodes
614 * \retval SMESH::long_array* - list of node ID
616 //================================================================================
618 SMESH::smIdType_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
621 SMESH::smIdType_array_var myLastCreatedNodes = new SMESH::smIdType_array();
623 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
624 myLastCreatedNodes->length( aSeq.size() );
625 for ( size_t i = 0; i < aSeq.size(); i++)
626 myLastCreatedNodes[i] = aSeq[i]->GetID();
628 return myLastCreatedNodes._retn();
629 SMESH_CATCH( SMESH::throwCorbaException );
633 //================================================================================
635 * \brief Returns list of it's IDs of created elements
636 * \retval SMESH::long_array* - list of elements' ID
638 //================================================================================
640 SMESH::smIdType_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 SMESH::smIdType_array_var myLastCreatedElems = new SMESH::smIdType_array();
645 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
646 myLastCreatedElems->length( aSeq.size() );
647 for ( size_t i = 0; i < aSeq.size(); i++ )
648 myLastCreatedElems[i] = aSeq[i]->GetID();
650 return myLastCreatedElems._retn();
651 SMESH_CATCH( SMESH::throwCorbaException );
655 //=======================================================================
656 //function : ClearLastCreated
657 //purpose : Clears sequences of last created elements and nodes
658 //=======================================================================
660 void SMESH_MeshEditor_i::ClearLastCreated()
663 getEditor().ClearLastCreated();
664 SMESH_CATCH( SMESH::throwCorbaException );
667 //=======================================================================
669 * Returns description of an error/warning occurred during the last operation
670 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
672 //=======================================================================
674 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
677 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
678 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
679 if ( errIn && !errIn->IsOK() )
681 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
682 errOut->comment = errIn->myComment.c_str();
683 errOut->subShapeID = -1;
684 errOut->hasBadMesh = errIn->HasBadElems();
689 errOut->subShapeID = -1;
690 errOut->hasBadMesh = false;
693 return errOut._retn();
694 SMESH_CATCH( SMESH::throwCorbaException );
698 //=======================================================================
699 //function : MakeIDSource
700 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
701 // Call UnRegister() as you fininsh using it!!
702 //=======================================================================
704 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
705 public virtual SALOME::GenericObj_i
707 SMESH::smIdType_array _ids;
708 SMESH::ElementType _type;
709 SMESH::SMESH_Mesh_ptr _mesh;
710 SMESH::smIdType_array* GetIDs() { return new SMESH::smIdType_array( _ids ); }
711 SMESH::smIdType_array* GetMeshInfo() { return 0; }
712 SMESH::smIdType_array* GetNbElementsByType()
714 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
715 aRes->length(SMESH::NB_ELEMENT_TYPES);
716 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
717 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
720 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
721 bool IsMeshInfoCorrect() { return true; }
722 SMESH::array_of_ElementType* GetTypes()
724 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
725 if ( _ids.length() > 0 ) {
729 return types._retn();
731 SALOMEDS::TMPFile* GetVtkUgStream()
733 SALOMEDS::TMPFile_var SeqFile;
734 return SeqFile._retn();
738 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::smIdType_array& ids,
739 SMESH::ElementType type)
741 _IDSource* idSrc = new _IDSource;
742 idSrc->_mesh = myMesh_i->_this();
745 if ( type == SMESH::ALL && ids.length() > 0 )
746 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
748 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
750 return anIDSourceVar._retn();
753 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
755 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
758 SMESH::smIdType* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
759 SMESH::smIdType& nbIds)
761 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
763 nbIds = (SMESH::smIdType) tmpIdSource->_ids.length();
764 return & tmpIdSource->_ids[0];
770 // void SMESH_MeshEditor_i::deleteAuxIDSources()
772 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
773 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
775 // myAuxIDSources.clear();
778 //=============================================================================
782 //=============================================================================
785 SMESH_MeshEditor_i::RemoveElements(const SMESH::smIdType_array & IDsOfElements)
790 list< smIdType > IdList;
792 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
793 IdList.push_back( IDsOfElements[i] );
795 // Update Python script
796 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
799 bool ret = getEditor().Remove( IdList, false );
801 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
804 SMESH_CATCH( SMESH::throwCorbaException );
808 //=============================================================================
812 //=============================================================================
814 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::smIdType_array & IDsOfNodes)
819 list< smIdType > IdList;
820 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
821 IdList.push_back( IDsOfNodes[i] );
823 // Update Python script
824 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
826 bool ret = getEditor().Remove( IdList, true );
828 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
831 SMESH_CATCH( SMESH::throwCorbaException );
835 //=============================================================================
837 * Remove orphan nodes
839 //=============================================================================
841 SMESH::smIdType SMESH_MeshEditor_i::RemoveOrphanNodes()
846 // Update Python script
847 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
849 // Create filter to find all orphan nodes
850 SMESH::Controls::Filter::TIdSequence seq;
851 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
852 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
854 // remove orphan nodes (if there are any)
855 list< smIdType > IdList( seq.begin(), seq.end() );
857 SMESH::smIdType nbNodesBefore = myMesh->NbNodes();
858 getEditor().Remove( IdList, true );
859 SMESH::smIdType nbNodesAfter = myMesh->NbNodes();
861 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
862 return nbNodesBefore - nbNodesAfter;
864 SMESH_CATCH( SMESH::throwCorbaException );
868 //=============================================================================
870 * Remove a node and fill a hole appeared by changing surrounding faces
872 //=============================================================================
874 void SMESH_MeshEditor_i::RemoveNodeWithReconnection( SMESH::smIdType nodeID )
879 const SMDS_MeshNode * node = getMeshDS()->FindNode( nodeID );
881 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID ") << nodeID,
883 if ( node->NbInverseElements( SMDSAbs_Volume ) > 0 )
884 THROW_SALOME_CORBA_EXCEPTION( "RemoveNodeWithReconnection() applies to 2D mesh only",
887 if ( myIsPreviewMode ) // make preview data
889 // in a preview mesh, make edges linked to a node
890 TPreviewMesh& tmpMesh = *getPreviewMesh( SMDSAbs_Edge );
891 TIDSortedElemSet linkedNodes;
892 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
893 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy( node );
894 for ( const SMDS_MeshElement* n : linkedNodes )
896 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( n ));
897 tmpMesh.GetMeshDS()->AddEdge( nodeCpy1, nodeCpy2 );
899 // copy surrounding faces
900 for ( SMDS_ElemIteratorPtr fIt = node->GetInverseElementIterator( SMDSAbs_Face ); fIt->more(); )
901 tmpMesh.Copy ( fIt->next() );
903 // remove copied node
905 getEditor().RemoveNodeWithReconnection( nodeCpy1 );
909 getEditor().RemoveNodeWithReconnection( node );
911 // Update Python script
912 TPythonDump() << this << ".RemoveNodeWithReconnection( " << nodeID << " )";
914 declareMeshModified( /*isReComputeSafe=*/ true );
917 SMESH_CATCH( SMESH::throwCorbaException );
920 //=============================================================================
924 //=============================================================================
926 SMESH::smIdType SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
931 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
933 // Update Python script
934 TPythonDump() << "nodeID = " << this << ".AddNode( "
935 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
937 declareMeshModified( /*isReComputeSafe=*/false );
940 SMESH_CATCH( SMESH::throwCorbaException );
944 //=============================================================================
946 * Create 0D element on the given node.
948 //=============================================================================
950 SMESH::smIdType SMESH_MeshEditor_i::Add0DElement(SMESH::smIdType IDOfNode,
951 CORBA::Boolean DuplicateElements)
956 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
957 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
959 SMDS_MeshElement* elem = 0;
960 if ( DuplicateElements || !it0D->more() )
961 elem = getMeshDS()->Add0DElement(aNode);
963 // Update Python script
964 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
966 declareMeshModified( /*isReComputeSafe=*/false );
968 return elem ? elem->GetID() : 0;
970 SMESH_CATCH( SMESH::throwCorbaException );
974 //=============================================================================
976 * Create a ball element on the given node.
978 //=============================================================================
980 SMESH::smIdType SMESH_MeshEditor_i::AddBall(SMESH::smIdType IDOfNode, CORBA::Double diameter)
985 if ( diameter < std::numeric_limits<double>::min() )
986 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
988 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
989 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
991 // Update Python script
992 TPythonDump() << "ballElem = "
993 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
995 declareMeshModified( /*isReComputeSafe=*/false );
996 return elem ? elem->GetID() : 0;
998 SMESH_CATCH( SMESH::throwCorbaException );
1002 //=============================================================================
1004 * Create an edge, either linear and quadratic (this is determed
1005 * by number of given nodes, two or three)
1007 //=============================================================================
1009 SMESH::smIdType SMESH_MeshEditor_i::AddEdge(const SMESH::smIdType_array & IDsOfNodes)
1014 SMESH::smIdType NbNodes = IDsOfNodes.length();
1015 SMDS_MeshElement* elem = 0;
1018 SMESH::smIdType index1 = IDsOfNodes[0];
1019 SMESH::smIdType index2 = IDsOfNodes[1];
1020 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
1021 getMeshDS()->FindNode(index2));
1023 // Update Python script
1024 TPythonDump() << "edge = " << this << ".AddEdge([ "
1025 << index1 << ", " << index2 <<" ])";
1028 SMESH::smIdType n1 = IDsOfNodes[0];
1029 SMESH::smIdType n2 = IDsOfNodes[1];
1030 SMESH::smIdType n12 = IDsOfNodes[2];
1031 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
1032 getMeshDS()->FindNode(n2),
1033 getMeshDS()->FindNode(n12));
1034 // Update Python script
1035 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
1036 <<n1<<", "<<n2<<", "<<n12<<" ])";
1039 declareMeshModified( /*isReComputeSafe=*/false );
1040 return elem ? elem->GetID() : 0;
1042 SMESH_CATCH( SMESH::throwCorbaException );
1046 //=============================================================================
1050 //=============================================================================
1052 SMESH::smIdType SMESH_MeshEditor_i::AddFace(const SMESH::smIdType_array & IDsOfNodes)
1057 int NbNodes = IDsOfNodes.length();
1063 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1064 for (int i = 0; i < NbNodes; i++)
1065 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1067 SMDS_MeshElement* elem = 0;
1069 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1070 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1071 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1072 nodes[4], nodes[5]); break;
1073 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1074 nodes[4], nodes[5], nodes[6]); break;
1075 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1076 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1077 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1078 nodes[4], nodes[5], nodes[6], nodes[7],
1080 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1083 // Update Python script
1084 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1086 declareMeshModified( /*isReComputeSafe=*/false );
1088 return elem ? elem->GetID() : 0;
1090 SMESH_CATCH( SMESH::throwCorbaException );
1094 //=============================================================================
1098 //=============================================================================
1100 SMESH::smIdType SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::smIdType_array & IDsOfNodes)
1105 int NbNodes = IDsOfNodes.length();
1106 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1107 for (int i = 0; i < NbNodes; i++)
1108 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1113 INFOS("Polygon without nodes is forbidden");
1117 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1119 // Update Python script
1120 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1122 declareMeshModified( /*isReComputeSafe=*/false );
1123 return elem ? elem->GetID() : 0;
1125 SMESH_CATCH( SMESH::throwCorbaException );
1129 //=============================================================================
1131 * AddQuadPolygonalFace
1133 //=============================================================================
1135 SMESH::smIdType SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::smIdType_array & IDsOfNodes)
1140 int NbNodes = IDsOfNodes.length();
1141 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1142 for (int i = 0; i < NbNodes; i++)
1143 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1147 INFOS("Polygon without nodes is forbidden");
1151 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1153 // Update Python script
1154 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1156 declareMeshModified( /*isReComputeSafe=*/false );
1157 return elem ? elem->GetID() : 0;
1159 SMESH_CATCH( SMESH::throwCorbaException );
1163 //=============================================================================
1165 * Create volume, either linear and quadratic (this is determed
1166 * by number of given nodes)
1168 //=============================================================================
1170 SMESH::smIdType SMESH_MeshEditor_i::AddVolume(const SMESH::smIdType_array & IDsOfNodes)
1175 int NbNodes = IDsOfNodes.length();
1176 vector< const SMDS_MeshNode*> n(NbNodes);
1177 for(int i=0;i<NbNodes;i++)
1178 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1180 SMDS_MeshElement* elem = 0;
1183 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1184 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1185 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1186 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1187 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1188 n[6],n[7],n[8],n[9]);
1190 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1191 n[6],n[7],n[8],n[9],n[10],n[11]);
1193 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1194 n[7],n[8],n[9],n[10],n[11],n[12]);
1196 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1197 n[9],n[10],n[11],n[12],n[13],n[14]);
1199 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1200 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1201 n[15],n[16],n[17],n[18],n[19]);
1203 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1204 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1207 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1208 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1209 n[15],n[16],n[17],n[18],n[19],
1210 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1214 // Update Python script
1215 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1217 declareMeshModified( /*isReComputeSafe=*/false );
1218 return elem ? elem->GetID() : 0;
1220 SMESH_CATCH( SMESH::throwCorbaException );
1224 //=============================================================================
1226 * AddPolyhedralVolume
1228 //=============================================================================
1229 SMESH::smIdType SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::smIdType_array & IDsOfNodes,
1230 const SMESH::long_array & Quantities)
1235 int NbNodes = IDsOfNodes.length();
1236 std::vector<const SMDS_MeshNode*> n (NbNodes);
1237 for (int i = 0; i < NbNodes; i++)
1239 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1240 if (!aNode) return 0;
1244 int NbFaces = Quantities.length();
1245 std::vector<int> q (NbFaces);
1246 for (int j = 0; j < NbFaces; j++)
1247 q[j] = Quantities[j];
1249 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1251 // Update Python script
1252 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1253 << IDsOfNodes << ", " << Quantities << " )";
1255 declareMeshModified( /*isReComputeSafe=*/false );
1256 return elem ? elem->GetID() : 0;
1258 SMESH_CATCH( SMESH::throwCorbaException );
1262 //=============================================================================
1264 * AddPolyhedralVolumeByFaces
1266 //=============================================================================
1268 SMESH::smIdType SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::smIdType_array & IdsOfFaces)
1273 int NbFaces = IdsOfFaces.length();
1274 std::vector<const SMDS_MeshNode*> poly_nodes;
1275 std::vector<int> quantities (NbFaces);
1277 for (int i = 0; i < NbFaces; i++) {
1278 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1279 quantities[i] = aFace->NbNodes();
1281 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1282 while (It->more()) {
1283 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1287 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1289 // Update Python script
1290 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1291 << IdsOfFaces << " )";
1293 declareMeshModified( /*isReComputeSafe=*/false );
1294 return elem ? elem->GetID() : 0;
1296 SMESH_CATCH( SMESH::throwCorbaException );
1300 //=============================================================================
1302 // \brief Create 0D elements on all nodes of the given object.
1303 // \param theObject object on whose nodes 0D elements will be created.
1304 // \param theGroupName optional name of a group to add 0D elements created
1305 // and/or found on nodes of \a theObject.
1306 // \param DuplicateElements to add one more 0D element to a node or not.
1307 // \return an object (a new group or a temporary SMESH_IDSource) holding
1308 // ids of new and/or found 0D elements.
1310 //=============================================================================
1312 SMESH::SMESH_IDSource_ptr
1313 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1314 const char* theGroupName,
1315 CORBA::Boolean theDuplicateElements)
1320 SMESH::SMESH_IDSource_var result;
1323 TIDSortedElemSet elements, elems0D;
1324 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1325 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1327 SMESH::smIdType_array_var newElems = new SMESH::smIdType_array;
1328 newElems->length( elems0D.size() );
1329 TIDSortedElemSet::iterator eIt = elems0D.begin();
1330 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1331 newElems[ i ] = (*eIt)->GetID();
1333 SMESH::SMESH_GroupBase_var groupToFill;
1334 if ( theGroupName && strlen( theGroupName ))
1336 // Get existing group named theGroupName
1337 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1338 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1339 SMESH::SMESH_GroupBase_var group = groups[i];
1340 if ( !group->_is_nil() ) {
1341 CORBA::String_var name = group->GetName();
1342 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1343 groupToFill = group;
1348 if ( groupToFill->_is_nil() )
1349 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1350 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1351 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1354 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1356 group_i->Add( newElems );
1357 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1358 pyDump << groupToFill;
1362 result = MakeIDSource( newElems, SMESH::ELEM0D );
1363 pyDump << "elem0DIDs";
1366 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1367 << theObject << ", '" << theGroupName << "' )";
1369 return result._retn();
1371 SMESH_CATCH( SMESH::throwCorbaException );
1375 //=============================================================================
1377 * \brief Bind a node to a vertex
1378 * \param NodeID - node ID
1379 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1380 * \retval boolean - false if NodeID or VertexID is invalid
1382 //=============================================================================
1384 void SMESH_MeshEditor_i::SetNodeOnVertex(SMESH::smIdType NodeID, CORBA::Long VertexID)
1388 SMESHDS_Mesh * mesh = getMeshDS();
1389 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1391 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1393 if ( mesh->MaxShapeIndex() < VertexID )
1394 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1396 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1397 if ( shape.ShapeType() != TopAbs_VERTEX )
1398 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1400 mesh->SetNodeOnVertex( node, VertexID );
1402 myMesh->SetIsModified( true );
1404 SMESH_CATCH( SMESH::throwCorbaException );
1407 //=============================================================================
1409 * \brief Store node position on an edge
1410 * \param NodeID - node ID
1411 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1412 * \param paramOnEdge - parameter on edge where the node is located
1413 * \retval boolean - false if any parameter is invalid
1415 //=============================================================================
1417 void SMESH_MeshEditor_i::SetNodeOnEdge(SMESH::smIdType NodeID, CORBA::Long EdgeID,
1418 CORBA::Double paramOnEdge)
1422 SMESHDS_Mesh * mesh = getMeshDS();
1423 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1425 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1427 if ( mesh->MaxShapeIndex() < EdgeID )
1428 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1430 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1431 if ( shape.ShapeType() != TopAbs_EDGE )
1432 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1435 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1436 if ( paramOnEdge < f || paramOnEdge > l )
1438 SMESH_Comment txt("Invalid paramOnEdge. It must vary in range [ ");
1439 txt << f << ", " << l << " ]";
1440 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1442 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1444 myMesh->SetIsModified( true );
1446 SMESH_CATCH( SMESH::throwCorbaException );
1449 //=============================================================================
1451 * \brief Store node position on a face
1452 * \param NodeID - node ID
1453 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1454 * \param u - U parameter on face where the node is located
1455 * \param v - V parameter on face where the node is located
1456 * \retval boolean - false if any parameter is invalid
1458 //=============================================================================
1460 void SMESH_MeshEditor_i::SetNodeOnFace(SMESH::smIdType NodeID, CORBA::Long FaceID,
1461 CORBA::Double u, CORBA::Double v)
1464 SMESHDS_Mesh * mesh = getMeshDS();
1465 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1467 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1469 if ( mesh->MaxShapeIndex() < FaceID )
1470 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1472 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1473 if ( shape.ShapeType() != TopAbs_FACE )
1474 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1476 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1477 bool isOut = ( u < surf.FirstUParameter() ||
1478 u > surf.LastUParameter() ||
1479 v < surf.FirstVParameter() ||
1480 v > surf.LastVParameter() );
1483 SMESH_Comment txt("Invalid UV. U must vary in range [ ");
1484 txt << surf.FirstUParameter() << ", " << surf.LastUParameter() << " ], ";
1485 txt << "V must vary in range [ ";
1486 txt << surf.FirstVParameter() << ", " << surf.LastVParameter() << " ]";
1487 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1490 mesh->SetNodeOnFace( node, FaceID, u, v );
1491 myMesh->SetIsModified( true );
1493 SMESH_CATCH( SMESH::throwCorbaException );
1496 //=============================================================================
1498 * \brief Bind a node to a solid
1499 * \param NodeID - node ID
1500 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1501 * \retval boolean - false if NodeID or SolidID is invalid
1503 //=============================================================================
1505 void SMESH_MeshEditor_i::SetNodeInVolume(SMESH::smIdType NodeID, CORBA::Long SolidID)
1508 SMESHDS_Mesh * mesh = getMeshDS();
1509 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1511 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1513 if ( mesh->MaxShapeIndex() < SolidID )
1514 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1516 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1517 if ( shape.ShapeType() != TopAbs_SOLID &&
1518 shape.ShapeType() != TopAbs_SHELL)
1519 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1521 mesh->SetNodeInVolume( node, SolidID );
1523 SMESH_CATCH( SMESH::throwCorbaException );
1526 //=============================================================================
1528 * \brief Bind an element to a shape
1529 * \param ElementID - element ID
1530 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1532 //=============================================================================
1534 void SMESH_MeshEditor_i::SetMeshElementOnShape(SMESH::smIdType ElementID,
1535 CORBA::Long ShapeID)
1538 SMESHDS_Mesh * mesh = getMeshDS();
1539 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1541 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1543 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1544 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1546 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1547 if ( shape.ShapeType() != TopAbs_EDGE &&
1548 shape.ShapeType() != TopAbs_FACE &&
1549 shape.ShapeType() != TopAbs_SOLID &&
1550 shape.ShapeType() != TopAbs_SHELL )
1551 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1553 mesh->SetMeshElementOnShape( elem, ShapeID );
1555 myMesh->SetIsModified( true );
1557 SMESH_CATCH( SMESH::throwCorbaException );
1560 //=============================================================================
1564 //=============================================================================
1566 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(SMESH::smIdType NodeID1,
1567 SMESH::smIdType NodeID2)
1572 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1573 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1577 // Update Python script
1578 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1579 << NodeID1 << ", " << NodeID2 << " )";
1581 int ret = getEditor().InverseDiag ( n1, n2 );
1583 declareMeshModified( /*isReComputeSafe=*/false );
1586 SMESH_CATCH( SMESH::throwCorbaException );
1590 //=============================================================================
1594 //=============================================================================
1596 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(SMESH::smIdType NodeID1,
1597 SMESH::smIdType NodeID2)
1602 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1603 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1607 // Update Python script
1608 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1609 << NodeID1 << ", " << NodeID2 << " )";
1612 bool stat = getEditor().DeleteDiag ( n1, n2 );
1614 declareMeshModified( /*isReComputeSafe=*/!stat );
1618 SMESH_CATCH( SMESH::throwCorbaException );
1622 //=============================================================================
1624 * \brief Split a diagonal of a quadrangle formed by two adjacent triangles
1625 * so that four new triangles appear in place of the two triangles
1627 //=============================================================================
1629 void SMESH_MeshEditor_i::AddNodeOnSegment(SMESH::smIdType nodeID1,
1630 SMESH::smIdType nodeID2,
1631 CORBA::Double position)
1636 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( nodeID1 );
1637 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( nodeID2 );
1639 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << nodeID1,
1642 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << nodeID2,
1645 if ( myIsPreviewMode ) // make preview data
1647 TPreviewMesh* tmpMesh = getPreviewMesh();
1648 TIDSortedElemSet elemSet, avoidSet;
1650 while ( const SMDS_MeshElement* face = SMESH_MeshAlgos::FindFaceInSet( n1, n2,
1651 elemSet, avoidSet ))
1653 if ( avoidSet.empty() )
1655 shape = getMeshDS()->IndexToShape( face->GetShapeID() );
1656 if ( !shape.IsNull() )
1658 tmpMesh->ShapeToMesh( TopoDS_Shape() );
1659 tmpMesh->ShapeToMesh( shape );
1662 SMDS_MeshElement* faceCopy = tmpMesh->Copy ( face );
1663 avoidSet.insert( face );
1665 if ( !shape.IsNull() )
1666 tmpMesh->GetMeshDS()->SetMeshElementOnShape( faceCopy, shape );
1668 n1 = tmpMesh->GetMeshDS()->FindNode( nodeID1 );
1669 n2 = tmpMesh->GetMeshDS()->FindNode( nodeID2 );
1671 if ( !shape.IsNull() )
1673 tmpMesh->GetMeshDS()->SetMeshElementOnShape( n1, shape );
1674 tmpMesh->GetMeshDS()->SetMeshElementOnShape( n2, shape );
1678 getEditor().SplitEdge( n1, n2, position );
1680 if ( !myIsPreviewMode )
1682 // Update Python script
1683 TPythonDump() << this << ".AddNodeOnSegment( "
1684 << nodeID1 << ", " << nodeID2 << ", " << position << " )";
1686 declareMeshModified( /*isReComputeSafe=*/true );
1689 SMESH_CATCH( SMESH::throwCorbaException );
1692 //=============================================================================
1694 * \brief Split a face into triangles by adding a new node onto the face
1695 * and connecting the new node with face nodes
1697 //=============================================================================
1699 void SMESH_MeshEditor_i::AddNodeOnFace(SMESH::smIdType theFaceID,
1707 const SMDS_MeshElement * face = getMeshDS()->FindElement( theFaceID );
1709 THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid face ID: ") << theFaceID,
1711 if ( face->GetType() != SMDSAbs_Face )
1712 THROW_SALOME_CORBA_EXCEPTION( "The element is not a face ", SALOME::BAD_PARAM );
1714 if ( myIsPreviewMode ) // make preview data
1716 TPreviewMesh* tmpMesh = getPreviewMesh();
1717 face = tmpMesh->Copy ( face );
1720 getEditor().SplitFace( face, theX, theY, theZ );
1722 if ( !myIsPreviewMode )
1724 // Update Python script
1725 TPythonDump() << this << ".AddNodeOnFace( "
1726 << theFaceID << ", "
1731 declareMeshModified( /*isReComputeSafe=*/true );
1734 SMESH_CATCH( SMESH::throwCorbaException );
1737 //=============================================================================
1741 //=============================================================================
1743 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::smIdType_array & IDsOfElements)
1748 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1750 SMESH::smIdType index = IDsOfElements[i];
1751 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1753 getEditor().Reorient( elem );
1755 // Update Python script
1756 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1758 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1761 SMESH_CATCH( SMESH::throwCorbaException );
1765 //=============================================================================
1769 //=============================================================================
1771 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1776 TPythonDump aTPythonDump; // suppress dump in Reorient()
1778 prepareIdSource( theObject );
1780 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
1781 CORBA::Boolean isDone = Reorient(anElementsId);
1783 // Update Python script
1784 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1786 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1789 SMESH_CATCH( SMESH::throwCorbaException );
1793 //=======================================================================
1794 //function : Reorient2D
1795 //purpose : Reorient faces contained in \a the2Dgroup.
1796 // the2Dgroup - the mesh or its part to reorient
1797 // theDirection - desired direction of normal of \a theFace
1798 // theFace - ID of face whose orientation is checked.
1799 // It can be < 1 then \a thePoint is used to find a face.
1800 // thePoint - is used to find a face if \a theFace < 1.
1801 // return number of reoriented elements.
1802 //=======================================================================
1804 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1805 const SMESH::DirStruct& theDirection,
1806 CORBA::Long theFace,
1807 const SMESH::PointStruct& thePoint)
1810 initData(/*deleteSearchers=*/false);
1812 TIDSortedElemSet elements;
1813 IDSource_Error error;
1814 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1815 if ( error == IDSource_EMPTY )
1817 if ( error == IDSource_INVALID )
1818 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1821 const SMDS_MeshElement* face = 0;
1824 face = getMeshDS()->FindElement( theFace );
1826 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1827 if ( face->GetType() != SMDSAbs_Face )
1828 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1832 // create theElementSearcher if needed
1833 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1834 if ( !theElementSearcher )
1836 if ( elements.empty() ) // search in the whole mesh
1838 if ( myMesh->NbFaces() == 0 )
1839 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1841 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1845 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1846 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1848 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1852 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1853 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1856 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1857 if ( !elements.empty() && !elements.count( face ))
1858 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1861 const SMESH::PointStruct * P = &theDirection.PS;
1862 gp_Vec dirVec( P->x, P->y, P->z );
1863 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1864 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1866 TIDSortedElemSet refFaces = { face };
1867 int nbReori = getEditor().Reorient2D( elements, dirVec, refFaces, /*allowNonManifold=*/true );
1870 declareMeshModified( /*isReComputeSafe=*/false );
1872 TPythonDump() << this << ".Reorient2D( "
1873 << the2Dgroup << ", "
1874 << theDirection << ", "
1876 << thePoint << " )";
1880 SMESH_CATCH( SMESH::throwCorbaException );
1884 //=======================================================================
1885 //function : Reorient2DByNeighbours
1886 //purpose : Reorient faces contained in a list of objectFaces
1887 // equally to faces contained in a list of referenceFaces.
1888 //=======================================================================
1891 SMESH_MeshEditor_i::Reorient2DByNeighbours(const SMESH::ListOfIDSources& theObjectFaces,
1892 const SMESH::ListOfIDSources& theReferenceFaces)
1895 initData(/*deleteSearchers=*/false);
1897 if ( theObjectFaces.length() == 0 )
1901 TIDSortedElemSet objFaces;
1902 bool invalidObjFaces = false;
1903 for ( CORBA::ULong i = 0; i < theObjectFaces.length(); ++i )
1906 if ( !idSourceToSet( theObjectFaces[i], getMeshDS(), objFaces, SMDSAbs_Face,
1907 /*emptyIfIsMesh=*/1, &err ) &&
1908 err == IDSource_INVALID )
1909 invalidObjFaces = true;
1911 if ( objFaces.empty() && invalidObjFaces )
1912 THROW_SALOME_CORBA_EXCEPTION("No valid faces in given groups", SALOME::BAD_PARAM);
1914 // get reference faces
1915 TIDSortedElemSet refFaces;
1916 for ( CORBA::ULong i = 0; i < theReferenceFaces.length(); ++i )
1918 idSourceToSet( theReferenceFaces[i], getMeshDS(), refFaces, SMDSAbs_Face, /*emptyIfIsMesh=*/1 );
1920 if ( refFaces.empty() && theReferenceFaces.length() > 0 )
1921 THROW_SALOME_CORBA_EXCEPTION("Reference faces are invalid", SALOME::BAD_PARAM);
1924 gp_Vec zeroVec( 0,0,0 );
1927 int nbReori = getEditor().Reorient2D( objFaces, zeroVec, refFaces, /*allowNonManifold=*/false );
1930 declareMeshModified( /*isReComputeSafe=*/false );
1932 TPythonDump() << this << ".Reorient2DByNeighbours("
1933 << theObjectFaces << ", "
1934 << theReferenceFaces << ")";
1938 SMESH_CATCH( SMESH::throwCorbaException );
1942 //=======================================================================
1943 //function : Reorient2DBy3D
1944 //purpose : Reorient faces basing on orientation of adjacent volumes.
1945 //=======================================================================
1947 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1948 SMESH::SMESH_IDSource_ptr volumeGroup,
1949 CORBA::Boolean outsideNormal)
1954 TIDSortedElemSet volumes;
1955 IDSource_Error volsError;
1956 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1959 for ( size_t i = 0; i < faceGroups.length(); ++i )
1961 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1963 TIDSortedElemSet faces;
1964 IDSource_Error error;
1965 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1966 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1967 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1968 if ( error == IDSource_OK && volsError != IDSource_OK )
1969 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1971 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1973 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1978 declareMeshModified( /*isReComputeSafe=*/false );
1980 TPythonDump() << this << ".Reorient2DBy3D( "
1981 << faceGroups << ", "
1982 << volumeGroup << ", "
1983 << outsideNormal << " )";
1987 SMESH_CATCH( SMESH::throwCorbaException );
1991 //=============================================================================
1993 * \brief Fuse neighbour triangles into quadrangles.
1995 //=============================================================================
1997 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::smIdType_array & IDsOfElements,
1998 SMESH::NumericalFunctor_ptr Criterion,
1999 CORBA::Double MaxAngle)
2004 SMESHDS_Mesh* aMesh = getMeshDS();
2005 TIDSortedElemSet faces,copyFaces;
2006 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
2007 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
2008 TIDSortedElemSet* workElements = & faces;
2010 if ( myIsPreviewMode ) {
2011 SMDSAbs_ElementType select = SMDSAbs_Face;
2012 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
2013 workElements = & copyFaces;
2016 SMESH::NumericalFunctor_i* aNumericalFunctor =
2017 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
2018 SMESH::Controls::NumericalFunctorPtr aCrit;
2019 if ( !aNumericalFunctor )
2020 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
2022 aCrit = aNumericalFunctor->GetNumericalFunctor();
2024 if ( !myIsPreviewMode ) {
2025 // Update Python script
2026 TPythonDump() << "isDone = " << this << ".TriToQuad( "
2027 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
2030 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
2032 declareMeshModified( /*isReComputeSafe=*/!stat );
2035 SMESH_CATCH( SMESH::throwCorbaException );
2039 //=============================================================================
2041 * \brief Fuse neighbour triangles into quadrangles.
2043 //=============================================================================
2045 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
2046 SMESH::NumericalFunctor_ptr Criterion,
2047 CORBA::Double MaxAngle)
2052 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
2054 prepareIdSource( theObject );
2055 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2056 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
2058 if ( !myIsPreviewMode ) {
2059 SMESH::NumericalFunctor_i* aNumericalFunctor =
2060 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
2062 // Update Python script
2063 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
2064 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
2069 SMESH_CATCH( SMESH::throwCorbaException );
2073 //=============================================================================
2075 * \brief Split quadrangles into triangles.
2077 //=============================================================================
2079 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::smIdType_array & IDsOfElements,
2080 SMESH::NumericalFunctor_ptr Criterion)
2085 SMESHDS_Mesh* aMesh = getMeshDS();
2086 TIDSortedElemSet faces;
2087 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
2089 SMESH::NumericalFunctor_i* aNumericalFunctor =
2090 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
2091 SMESH::Controls::NumericalFunctorPtr aCrit;
2092 if ( !aNumericalFunctor )
2093 aCrit.reset( new SMESH::Controls::AspectRatio() );
2095 aCrit = aNumericalFunctor->GetNumericalFunctor();
2098 // Update Python script
2099 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
2101 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
2103 declareMeshModified( /*isReComputeSafe=*/false );
2106 SMESH_CATCH( SMESH::throwCorbaException );
2110 //=============================================================================
2112 * \brief Split quadrangles into triangles.
2114 //=============================================================================
2116 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
2117 SMESH::NumericalFunctor_ptr Criterion)
2122 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
2124 prepareIdSource( theObject );
2125 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2126 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
2128 SMESH::NumericalFunctor_i* aNumericalFunctor =
2129 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
2131 // Update Python script
2132 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
2134 declareMeshModified( /*isReComputeSafe=*/false );
2137 SMESH_CATCH( SMESH::throwCorbaException );
2141 //================================================================================
2143 * \brief Split each of quadrangles into 4 triangles.
2144 * \param [in] theObject - theQuads Container of quadrangles to split.
2146 //================================================================================
2148 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
2153 TIDSortedElemSet faces;
2154 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
2156 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
2158 getEditor().QuadTo4Tri( faces );
2159 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
2161 declareMeshModified( /*isReComputeSafe=*/false );
2163 SMESH_CATCH( SMESH::throwCorbaException );
2166 //=============================================================================
2168 * \brief Split quadrangles into triangles.
2170 //=============================================================================
2172 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::smIdType_array & IDsOfElements,
2173 CORBA::Boolean Diag13)
2178 SMESHDS_Mesh* aMesh = getMeshDS();
2179 TIDSortedElemSet faces;
2180 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
2182 // Update Python script
2183 TPythonDump() << "isDone = " << this << ".SplitQuad( "
2184 << IDsOfElements << ", " << Diag13 << " )";
2186 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
2188 declareMeshModified( /*isReComputeSafe=*/ !stat );
2191 SMESH_CATCH( SMESH::throwCorbaException );
2195 //=============================================================================
2197 * \brief Split quadrangles into triangles.
2199 //=============================================================================
2201 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
2202 CORBA::Boolean Diag13)
2207 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2209 prepareIdSource( theObject );
2210 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2211 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2213 // Update Python script
2214 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2215 << theObject << ", " << Diag13 << " )";
2217 declareMeshModified( /*isReComputeSafe=*/!isDone );
2220 SMESH_CATCH( SMESH::throwCorbaException );
2225 //=============================================================================
2227 * Find better splitting of the given quadrangle.
2228 * \param IDOfQuad ID of the quadrangle to be split.
2229 * \param Criterion A criterion to choose a diagonal for splitting.
2230 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2231 * diagonal is better, 0 if error occurs.
2233 //=============================================================================
2235 CORBA::Short SMESH_MeshEditor_i::BestSplit (SMESH::smIdType IDOfQuad,
2236 SMESH::NumericalFunctor_ptr Criterion)
2241 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2242 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2244 SMESH::NumericalFunctor_i* aNumericalFunctor =
2245 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2246 SMESH::Controls::NumericalFunctorPtr aCrit;
2247 if (aNumericalFunctor)
2248 aCrit = aNumericalFunctor->GetNumericalFunctor();
2250 aCrit.reset(new SMESH::Controls::AspectRatio());
2252 int id = getEditor().BestSplit(quad, aCrit);
2253 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2257 SMESH_CATCH( SMESH::throwCorbaException );
2261 //================================================================================
2263 * \brief Split volumic elements into tetrahedrons
2265 //================================================================================
2267 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2268 CORBA::Short methodFlags)
2273 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2274 const int noneFacet = -1;
2275 prepareIdSource( elems );
2276 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2277 while ( volIt->more() )
2278 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2280 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2281 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2283 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2284 << elems << ", " << methodFlags << " )";
2286 SMESH_CATCH( SMESH::throwCorbaException );
2289 //================================================================================
2291 * \brief Split hexahedra into triangular prisms
2292 * \param elems - elements to split
2293 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2294 * to split into triangles
2295 * \param methodFlags - flags passing splitting method:
2296 * 1 - split the hexahedron into 2 prisms
2297 * 2 - split the hexahedron into 4 prisms
2299 //================================================================================
2301 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2302 const SMESH::PointStruct & startHexPoint,
2303 const SMESH::DirStruct& facetToSplitNormal,
2304 CORBA::Short methodFlags,
2305 CORBA::Boolean allDomains)
2309 prepareIdSource( elems );
2311 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2314 gp_Dir( facetToSplitNormal.PS.x,
2315 facetToSplitNormal.PS.y,
2316 facetToSplitNormal.PS.z ));
2317 TIDSortedElemSet elemSet;
2318 prepareIdSource( elems );
2319 SMESH::smIdType_array_var anElementsId = elems->GetIDs();
2320 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2321 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2323 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2324 while ( !elemSet.empty() )
2326 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2330 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2331 for ( ; ef != elemFacets.end(); ++ef )
2332 elemSet.erase( ef->first );
2335 if ( methodFlags == 2 )
2336 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2338 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2340 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2341 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2343 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2345 << startHexPoint << ", "
2346 << facetToSplitNormal<< ", "
2347 << methodFlags<< ", "
2348 << allDomains << " )";
2350 SMESH_CATCH( SMESH::throwCorbaException );
2353 //================================================================================
2355 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2356 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2357 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2358 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2359 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2360 * will be split in order to keep the mesh conformal.
2361 * \param elems - elements to split
2363 //================================================================================
2365 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2370 TIDSortedElemSet elemSet;
2371 for ( size_t i = 0; i < theElems.length(); ++i )
2373 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2374 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2375 if ( mesh->GetId() != myMesh_i->GetId() )
2376 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2378 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2380 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2382 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2384 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2385 << theElems << " )";
2387 SMESH_CATCH( SMESH::throwCorbaException );
2390 //=======================================================================
2393 //=======================================================================
2396 SMESH_MeshEditor_i::Smooth(const SMESH::smIdType_array & IDsOfElements,
2397 const SMESH::smIdType_array & IDsOfFixedNodes,
2398 CORBA::Short MaxNbOfIterations,
2399 CORBA::Double MaxAspectRatio,
2400 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2402 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2403 MaxAspectRatio, Method, false );
2407 //=======================================================================
2408 //function : SmoothParametric
2410 //=======================================================================
2413 SMESH_MeshEditor_i::SmoothParametric(const SMESH::smIdType_array & IDsOfElements,
2414 const SMESH::smIdType_array & IDsOfFixedNodes,
2415 CORBA::Short MaxNbOfIterations,
2416 CORBA::Double MaxAspectRatio,
2417 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2419 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2420 MaxAspectRatio, Method, true );
2424 //=======================================================================
2425 //function : SmoothObject
2427 //=======================================================================
2430 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2431 const SMESH::smIdType_array & IDsOfFixedNodes,
2432 CORBA::Short MaxNbOfIterations,
2433 CORBA::Double MaxAspectRatio,
2434 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2436 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2437 MaxAspectRatio, Method, false);
2441 //=======================================================================
2442 //function : SmoothParametricObject
2444 //=======================================================================
2447 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2448 const SMESH::smIdType_array & IDsOfFixedNodes,
2449 CORBA::Short MaxNbOfIterations,
2450 CORBA::Double MaxAspectRatio,
2451 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2453 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2454 MaxAspectRatio, Method, true);
2458 //=============================================================================
2462 //=============================================================================
2465 SMESH_MeshEditor_i::smooth(const SMESH::smIdType_array & IDsOfElements,
2466 const SMESH::smIdType_array & IDsOfFixedNodes,
2467 CORBA::Short MaxNbOfIterations,
2468 CORBA::Double MaxAspectRatio,
2469 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2475 SMESHDS_Mesh* aMesh = getMeshDS();
2477 TIDSortedElemSet elements;
2478 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2480 set<const SMDS_MeshNode*> fixedNodes;
2481 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2482 SMESH::smIdType index = IDsOfFixedNodes[i];
2483 const SMDS_MeshNode * node = aMesh->FindNode(index);
2485 fixedNodes.insert( node );
2487 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2488 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2489 method = ::SMESH_MeshEditor::CENTROIDAL;
2491 getEditor().Smooth(elements, fixedNodes, method,
2492 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2494 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2496 // Update Python script
2497 TPythonDump() << "isDone = " << this << "."
2498 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2499 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2500 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2501 << "SMESH.SMESH_MeshEditor."
2502 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2503 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2507 SMESH_CATCH( SMESH::throwCorbaException );
2511 //=============================================================================
2515 //=============================================================================
2518 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2519 const SMESH::smIdType_array & IDsOfFixedNodes,
2520 CORBA::Short MaxNbOfIterations,
2521 CORBA::Double MaxAspectRatio,
2522 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2528 TPythonDump aTPythonDump; // suppress dump in smooth()
2530 prepareIdSource( theObject );
2531 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2532 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2533 MaxAspectRatio, Method, IsParametric);
2535 // Update Python script
2536 aTPythonDump << "isDone = " << this << "."
2537 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2538 << theObject << ", " << IDsOfFixedNodes << ", "
2539 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2540 << "SMESH.SMESH_MeshEditor."
2541 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2542 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2546 SMESH_CATCH( SMESH::throwCorbaException );
2550 //=============================================================================
2554 //=============================================================================
2556 void SMESH_MeshEditor_i::RenumberNodes()
2559 // Update Python script
2560 TPythonDump() << this << ".RenumberNodes()";
2562 getMeshDS()->Renumber( true );
2564 SMESH_CATCH( SMESH::throwCorbaException );
2567 //=============================================================================
2571 //=============================================================================
2573 void SMESH_MeshEditor_i::RenumberElements()
2576 // Update Python script
2577 TPythonDump() << this << ".RenumberElements()";
2579 getMeshDS()->Renumber( false );
2581 SMESH_CATCH( SMESH::throwCorbaException );
2584 //=======================================================================
2586 * \brief Return groups by their IDs
2588 //=======================================================================
2590 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2595 myMesh_i->CreateGroupServants();
2596 return myMesh_i->GetGroups( *groupIDs );
2598 SMESH_CATCH( SMESH::throwCorbaException );
2602 //=======================================================================
2603 //function : RotationSweepObjects
2605 //=======================================================================
2607 SMESH::ListOfGroups*
2608 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2609 const SMESH::ListOfIDSources & theEdges,
2610 const SMESH::ListOfIDSources & theFaces,
2611 const SMESH::AxisStruct & theAxis,
2612 CORBA::Double theAngleInRadians,
2613 CORBA::Long theNbOfSteps,
2614 CORBA::Double theTolerance,
2615 const bool theMakeGroups)
2620 TIDSortedElemSet elemsNodes[2];
2621 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2622 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2623 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2625 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2626 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2627 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2628 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2630 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2631 bool makeWalls=true;
2632 if ( myIsPreviewMode )
2634 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2635 TPreviewMesh * tmpMesh = getPreviewMesh();
2636 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2637 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2638 workElements = & copyElements[0];
2639 //makeWalls = false; -- faces are needed for preview
2642 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2644 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2645 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2647 ::SMESH_MeshEditor::PGroupIDs groupIds =
2648 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2649 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2651 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2653 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2655 if ( !myIsPreviewMode )
2657 dumpGroupsList( aPythonDump, aGroups );
2658 aPythonDump << this<< ".RotationSweepObjects( "
2663 << TVar( theAngleInRadians ) << ", "
2664 << TVar( theNbOfSteps ) << ", "
2665 << TVar( theTolerance ) << ", "
2666 << theMakeGroups << " )";
2670 getPreviewMesh()->Remove( SMDSAbs_Volume );
2673 return aGroups ? aGroups : new SMESH::ListOfGroups;
2675 SMESH_CATCH( SMESH::throwCorbaException );
2679 namespace MeshEditor_I
2682 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2684 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2686 bool myIsExtrusionByNormal;
2688 static int makeFlags( CORBA::Boolean MakeGroups,
2689 CORBA::Boolean ScaleVariation = false,
2690 CORBA::Boolean AngleVariation = false,
2691 CORBA::Boolean ByAverageNormal = false,
2692 CORBA::Boolean UseInputElemsOnly = false,
2693 CORBA::Long Flags = 0,
2694 CORBA::Boolean MakeBoundary = true )
2696 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2697 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2698 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2699 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2700 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2701 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2705 ExtrusionParams(const SMESH::DirStruct & theDir,
2706 CORBA::Long theNbOfSteps,
2707 const SMESH::double_array & theScaleFactors,
2708 CORBA::Boolean theScaleVariation,
2709 const SMESH::double_array & theAngles,
2710 CORBA::Boolean theAngleVariation,
2711 const SMESH::double_array & theBasePoint,
2712 CORBA::Boolean theMakeGroups):
2713 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2717 toList( theScaleFactors ),
2718 toList( theAngles ),
2719 TBasePoint( theBasePoint ),
2720 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2721 myIsExtrusionByNormal( false )
2725 ExtrusionParams(const SMESH::DirStruct & theDir,
2726 CORBA::Long theNbOfSteps,
2727 CORBA::Boolean theMakeGroups,
2728 CORBA::Long theExtrFlags,
2729 CORBA::Double theSewTolerance):
2730 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2734 std::list<double>(),
2735 std::list<double>(),
2737 makeFlags( theMakeGroups, false, false, false, false,
2738 theExtrFlags, false ),
2740 myIsExtrusionByNormal( false )
2743 // params for extrusion by normal
2744 ExtrusionParams(CORBA::Double theStepSize,
2745 CORBA::Long theNbOfSteps,
2746 CORBA::Short theDim,
2747 CORBA::Boolean theByAverageNormal,
2748 CORBA::Boolean theUseInputElemsOnly,
2749 CORBA::Boolean theMakeGroups ):
2750 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2752 makeFlags( theMakeGroups, false, false,
2753 theByAverageNormal, theUseInputElemsOnly ),
2755 myIsExtrusionByNormal( true )
2761 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2764 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2766 std::list<double> scales;
2767 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2768 scales.push_back( theScaleFactors[i] );
2774 // structure used to convert SMESH::double_array to gp_XYZ*
2778 TBasePoint( const SMESH::double_array & theBasePoint )
2781 if ( theBasePoint.length() == 3 )
2783 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2787 operator const gp_XYZ*() const { return pp; }
2792 //=======================================================================
2794 * \brief Generate dim+1 elements by extrusion of elements along vector
2795 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2796 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2797 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2798 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2799 * \param [in] nbOfSteps - number of elements to generate from one element
2800 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2801 * corresponding to groups the input elements included in.
2802 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2804 //=======================================================================
2806 SMESH::ListOfGroups*
2807 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2808 const SMESH::ListOfIDSources & theEdges,
2809 const SMESH::ListOfIDSources & theFaces,
2810 const SMESH::DirStruct & theStepVector,
2811 CORBA::Long theNbOfSteps,
2812 CORBA::Boolean theToMakeGroups,
2813 const SMESH::double_array & theScaleFactors,
2814 CORBA::Boolean theScalesVariation,
2815 const SMESH::double_array & theBasePoint,
2816 const SMESH::double_array & theAngles,
2817 CORBA::Boolean theAnglesVariation)
2822 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2823 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2825 TIDSortedElemSet elemsNodes[2];
2826 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2827 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2828 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2830 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2831 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2832 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2833 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2835 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2836 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2837 if ( myIsPreviewMode )
2839 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2840 // previewType = SMDSAbs_Edge;
2842 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2843 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2844 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2845 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2846 workElements = & copyElements[0];
2848 params.SetNoGroups();
2850 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2852 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2853 ::SMESH_MeshEditor::PGroupIDs groupIds =
2854 getEditor().ExtrusionSweep( workElements, params, aHistory );
2856 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2858 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2860 if ( !myIsPreviewMode )
2862 dumpGroupsList( aPythonDump, aGroups );
2863 aPythonDump << this<< ".ExtrusionSweepObjects( "
2867 << theStepVector << ", "
2868 << TVar( theNbOfSteps ) << ", "
2869 << theToMakeGroups << ", "
2870 << TVar( theScaleFactors ) << ", "
2871 << theScalesVariation << ", "
2872 << TVar( theBasePoint ) << ", "
2873 << TVar( theAngles ) << ", "
2874 << theAnglesVariation << " )";
2878 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2881 return aGroups ? aGroups : new SMESH::ListOfGroups;
2883 SMESH_CATCH( SMESH::throwCorbaException );
2887 //=======================================================================
2888 //function : ExtrusionByNormal
2890 //=======================================================================
2892 SMESH::ListOfGroups*
2893 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2894 CORBA::Double stepSize,
2895 CORBA::Long nbOfSteps,
2896 CORBA::Boolean byAverageNormal,
2897 CORBA::Boolean useInputElemsOnly,
2898 CORBA::Boolean makeGroups,
2904 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2906 ExtrusionParams params( stepSize, nbOfSteps, dim,
2907 byAverageNormal, useInputElemsOnly, makeGroups );
2909 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2910 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2912 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2913 if (( elemTypes->length() == 1 ) &&
2914 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2915 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2918 TIDSortedElemSet elemsNodes[2];
2919 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2920 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2922 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2923 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2924 if ( myIsPreviewMode )
2926 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2927 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2928 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2929 workElements = & copyElements[0];
2931 params.SetNoGroups();
2934 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2935 ::SMESH_MeshEditor::PGroupIDs groupIds =
2936 getEditor().ExtrusionSweep( workElements, params, aHistory );
2938 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2940 if (!myIsPreviewMode) {
2941 dumpGroupsList(aPythonDump, aGroups);
2942 aPythonDump << this << ".ExtrusionByNormal( " << objects
2943 << ", " << TVar( stepSize )
2944 << ", " << TVar( nbOfSteps )
2945 << ", " << byAverageNormal
2946 << ", " << useInputElemsOnly
2947 << ", " << makeGroups
2953 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2956 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2958 return aGroups ? aGroups : new SMESH::ListOfGroups;
2960 SMESH_CATCH( SMESH::throwCorbaException );
2964 //=======================================================================
2965 //function : AdvancedExtrusion
2967 //=======================================================================
2969 SMESH::ListOfGroups*
2970 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::smIdType_array & theIDsOfElements,
2971 const SMESH::DirStruct & theStepVector,
2972 CORBA::Long theNbOfSteps,
2973 CORBA::Long theExtrFlags,
2974 CORBA::Double theSewTolerance,
2975 CORBA::Boolean theMakeGroups)
2980 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2982 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2983 theExtrFlags, theSewTolerance );
2985 TIDSortedElemSet elemsNodes[2];
2986 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2988 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2989 ::SMESH_MeshEditor::PGroupIDs groupIds =
2990 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2992 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2994 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2996 if ( !myIsPreviewMode ) {
2997 dumpGroupsList(aPythonDump, aGroups);
2998 aPythonDump << this << ".AdvancedExtrusion( "
2999 << theIDsOfElements << ", "
3000 << theStepVector << ", "
3001 << theNbOfSteps << ", "
3002 << theExtrFlags << ", "
3003 << theSewTolerance << ", "
3004 << theMakeGroups << " )";
3008 getPreviewMesh()->Remove( SMDSAbs_Volume );
3011 return aGroups ? aGroups : new SMESH::ListOfGroups;
3013 SMESH_CATCH( SMESH::throwCorbaException );
3017 //================================================================================
3019 * \brief Convert extrusion error to IDL enum
3021 //================================================================================
3025 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
3027 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
3031 RETCASE( EXTR_NO_ELEMENTS );
3032 RETCASE( EXTR_PATH_NOT_EDGE );
3033 RETCASE( EXTR_BAD_PATH_SHAPE );
3034 RETCASE( EXTR_BAD_STARTING_NODE );
3035 RETCASE( EXTR_BAD_ANGLES_NUMBER );
3036 RETCASE( EXTR_CANT_GET_TANGENT );
3038 return SMESH::SMESH_MeshEditor::EXTR_OK;
3042 //=======================================================================
3043 //function : extrusionAlongPath
3045 //=======================================================================
3046 SMESH::ListOfGroups*
3047 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
3048 const SMESH::ListOfIDSources & theEdges,
3049 const SMESH::ListOfIDSources & theFaces,
3050 SMESH::SMESH_IDSource_ptr thePathObject,
3051 GEOM::GEOM_Object_ptr thePathShape,
3052 SMESH::smIdType theNodeStart,
3053 CORBA::Boolean theHasAngles,
3054 const SMESH::double_array & theAngles,
3055 CORBA::Boolean theAnglesVariation,
3056 CORBA::Boolean theHasRefPoint,
3057 const SMESH::PointStruct & theRefPoint,
3059 const SMESH::double_array & theScaleFactors,
3060 CORBA::Boolean theScalesVariation,
3061 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
3066 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
3068 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3069 if ( thePathObject->_is_nil() )
3070 return aGroups._retn();
3073 SMDS_ElemIteratorPtr pathEdgesIterator;
3075 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
3076 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
3078 // get a sub-mesh of thePathShape
3079 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3080 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3082 return aGroups._retn();
3084 if ( !aSubMesh->GetSubMeshDS() )
3086 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
3087 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
3088 if ( !aSubMesh->GetSubMeshDS() )
3089 return aGroups._retn();
3091 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
3092 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
3093 if ( !pathEdgesIterator->more() ||
3094 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
3095 return aGroups._retn();
3097 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
3101 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
3102 prepareIdSource( thePathObject );
3103 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
3104 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
3105 return aGroups._retn();
3110 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
3111 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
3115 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3116 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
3118 return aGroups._retn();
3121 TIDSortedElemSet elemsNodes[2];
3122 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
3123 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
3124 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
3126 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
3127 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
3128 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
3129 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
3131 list<double> angles = ExtrusionParams::toList( theAngles );
3132 list<double> scales = ExtrusionParams::toList( theScaleFactors );
3134 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
3135 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
3137 int nbOldGroups = myMesh->NbGroup();
3139 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
3140 if ( myIsPreviewMode )
3142 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
3143 TPreviewMesh * tmpMesh = getPreviewMesh();
3144 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
3145 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
3146 workElements = & copyElements[0];
3147 theMakeGroups = false;
3150 ::SMESH_MeshEditor::Extrusion_Error error =
3151 getEditor().ExtrusionAlongTrack( workElements,
3152 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
3153 angles, theAnglesVariation,
3154 scales, theScalesVariation,
3155 refPntPtr, theMakeGroups );
3157 declareMeshModified( /*isReComputeSafe=*/true );
3158 theError = convExtrError( error );
3160 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
3161 if ( theMakeGroups ) {
3162 list<int> groupIDs = myMesh->GetGroupIds();
3163 list<int>::iterator newBegin = groupIDs.begin();
3164 std::advance( newBegin, nbOldGroups ); // skip old groups
3165 groupIDs.erase( groupIDs.begin(), newBegin );
3166 aGroups = getGroups( & groupIDs );
3167 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
3170 if ( !myIsPreviewMode ) {
3171 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
3172 else aPythonDump << "(_noGroups, error) = ";
3173 aPythonDump << this << ".ExtrusionAlongPathObjects( "
3177 << thePathObject << ", "
3178 << thePathShape << ", "
3179 << theNodeStart << ", "
3180 << theHasAngles << ", "
3181 << TVar( theAngles ) << ", "
3182 << theAnglesVariation << ", "
3183 << theHasRefPoint << ", "
3184 << "SMESH.PointStruct( "
3185 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3186 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3187 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
3188 << theMakeGroups << ", "
3189 << TVar( theScaleFactors ) << ", "
3190 << theScalesVariation << " )";
3194 getPreviewMesh()->Remove( SMDSAbs_Volume );
3197 return aGroups._retn();
3199 SMESH_CATCH( SMESH::throwCorbaException );
3203 //================================================================================
3205 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3206 * of given angles along path steps
3207 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3208 * which proceeds the extrusion
3209 * \param PathShape is shape(edge); as the mesh can be complex, the edge
3210 * is used to define the sub-mesh for the path
3212 //================================================================================
3214 SMESH::double_array*
3215 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3216 GEOM::GEOM_Object_ptr thePathShape,
3217 const SMESH::double_array & theAngles)
3219 SMESH::double_array_var aResult = new SMESH::double_array();
3220 int nbAngles = theAngles.length();
3221 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3223 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3224 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3225 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3226 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3227 return aResult._retn();
3228 smIdType nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3229 if ( nbSteps == nbAngles )
3231 aResult.inout() = theAngles;
3235 aResult->length( nbSteps );
3236 double rAn2St = double( nbAngles ) / double( nbSteps );
3237 double angPrev = 0, angle;
3238 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3240 double angCur = rAn2St * ( iSt+1 );
3241 double angCurFloor = floor( angCur );
3242 double angPrevFloor = floor( angPrev );
3243 if ( angPrevFloor == angCurFloor )
3244 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3247 int iP = int( angPrevFloor );
3248 double angPrevCeil = ceil(angPrev);
3249 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3251 int iC = int( angCurFloor );
3252 if ( iC < nbAngles )
3253 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3255 iP = int( angPrevCeil );
3257 angle += theAngles[ iC ];
3259 aResult[ iSt ] = angle;
3264 // Update Python script
3265 TPythonDump() << "rotAngles = " << theAngles;
3266 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3267 << thePathMesh << ", "
3268 << thePathShape << ", "
3271 return aResult._retn();
3274 //=======================================================================
3277 //=======================================================================
3279 SMESH::ListOfGroups*
3280 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3281 const SMESH::AxisStruct & theAxis,
3282 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3283 CORBA::Boolean theCopy,
3285 ::SMESH_Mesh* theTargetMesh)
3290 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3291 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3293 if ( theTargetMesh )
3297 switch ( theMirrorType ) {
3298 case SMESH::SMESH_MeshEditor::POINT:
3299 aTrsf.SetMirror( P );
3301 case SMESH::SMESH_MeshEditor::AXIS:
3302 aTrsf.SetMirror( gp_Ax1( P, V ));
3305 aTrsf.SetMirror( gp_Ax2( P, V ));
3308 TIDSortedElemSet copyElements;
3309 TIDSortedElemSet* workElements = & theElements;
3311 if ( myIsPreviewMode )
3313 TPreviewMesh * tmpMesh = getPreviewMesh();
3314 tmpMesh->Copy( theElements, copyElements);
3315 if ( !theCopy && !theTargetMesh )
3317 TIDSortedElemSet elemsAround, elemsAroundCopy;
3318 getElementsAround( theElements, getMeshDS(), elemsAround );
3319 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3321 workElements = & copyElements;
3322 theMakeGroups = false;
3325 ::SMESH_MeshEditor::PGroupIDs groupIds =
3326 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3328 if ( !myIsPreviewMode )
3330 if ( theTargetMesh )
3331 theTargetMesh->GetMeshDS()->Modified();
3333 declareMeshModified( /*isReComputeSafe=*/false );
3336 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3338 SMESH_CATCH( SMESH::throwCorbaException );
3342 //=======================================================================
3345 //=======================================================================
3347 void SMESH_MeshEditor_i::Mirror(const SMESH::smIdType_array & theIDsOfElements,
3348 const SMESH::AxisStruct & theAxis,
3349 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3350 CORBA::Boolean theCopy)
3352 if ( !myIsPreviewMode ) {
3353 TPythonDump() << this << ".Mirror( "
3354 << theIDsOfElements << ", "
3356 << mirrorTypeName(theMirrorType) << ", "
3359 if ( theIDsOfElements.length() > 0 )
3361 TIDSortedElemSet elements;
3362 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3363 mirror(elements, theAxis, theMirrorType, theCopy, false);
3368 //=======================================================================
3369 //function : MirrorObject
3371 //=======================================================================
3373 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3374 const SMESH::AxisStruct & theAxis,
3375 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3376 CORBA::Boolean theCopy)
3378 if ( !myIsPreviewMode ) {
3379 TPythonDump() << this << ".MirrorObject( "
3380 << theObject << ", "
3382 << mirrorTypeName(theMirrorType) << ", "
3385 TIDSortedElemSet elements;
3387 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3389 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3390 mirror(elements, theAxis, theMirrorType, theCopy, false);
3393 //=======================================================================
3394 //function : MirrorMakeGroups
3396 //=======================================================================
3398 SMESH::ListOfGroups*
3399 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3400 const SMESH::AxisStruct& theMirror,
3401 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3403 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3405 SMESH::ListOfGroups * aGroups = 0;
3406 if ( theIDsOfElements.length() > 0 )
3408 TIDSortedElemSet elements;
3409 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3410 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3412 if (!myIsPreviewMode) {
3413 dumpGroupsList(aPythonDump, aGroups);
3414 aPythonDump << this << ".MirrorMakeGroups( "
3415 << theIDsOfElements << ", "
3416 << theMirror << ", "
3417 << mirrorTypeName(theMirrorType) << " )";
3422 //=======================================================================
3423 //function : MirrorObjectMakeGroups
3425 //=======================================================================
3427 SMESH::ListOfGroups*
3428 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3429 const SMESH::AxisStruct& theMirror,
3430 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3432 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3434 SMESH::ListOfGroups * aGroups = 0;
3435 TIDSortedElemSet elements;
3436 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3437 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3439 if (!myIsPreviewMode)
3441 dumpGroupsList(aPythonDump,aGroups);
3442 aPythonDump << this << ".MirrorObjectMakeGroups( "
3443 << theObject << ", "
3444 << theMirror << ", "
3445 << mirrorTypeName(theMirrorType) << " )";
3450 //=======================================================================
3451 //function : MirrorMakeMesh
3453 //=======================================================================
3455 SMESH::SMESH_Mesh_ptr
3456 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3457 const SMESH::AxisStruct& theMirror,
3458 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3459 CORBA::Boolean theCopyGroups,
3460 const char* theMeshName)
3462 SMESH_Mesh_i* mesh_i;
3463 SMESH::SMESH_Mesh_var mesh;
3464 { // open new scope to dump "MakeMesh" command
3465 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3467 TPythonDump pydump; // to prevent dump at mesh creation
3469 mesh = makeMesh( theMeshName );
3470 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3471 if (mesh_i && theIDsOfElements.length() > 0 )
3473 TIDSortedElemSet elements;
3474 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3475 mirror(elements, theMirror, theMirrorType,
3476 false, theCopyGroups, & mesh_i->GetImpl());
3477 mesh_i->CreateGroupServants();
3480 if (!myIsPreviewMode) {
3481 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3482 << theIDsOfElements << ", "
3483 << theMirror << ", "
3484 << mirrorTypeName(theMirrorType) << ", "
3485 << theCopyGroups << ", '"
3486 << theMeshName << "' )";
3491 if (!myIsPreviewMode && mesh_i)
3492 mesh_i->GetGroups();
3494 return mesh._retn();
3497 //=======================================================================
3498 //function : MirrorObjectMakeMesh
3500 //=======================================================================
3502 SMESH::SMESH_Mesh_ptr
3503 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3504 const SMESH::AxisStruct& theMirror,
3505 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3506 CORBA::Boolean theCopyGroups,
3507 const char* theMeshName)
3509 SMESH_Mesh_i* mesh_i;
3510 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 );
3518 TIDSortedElemSet elements;
3520 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3522 mirror(elements, theMirror, theMirrorType,
3523 false, theCopyGroups, & mesh_i->GetImpl());
3524 mesh_i->CreateGroupServants();
3526 if (!myIsPreviewMode) {
3527 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3528 << theObject << ", "
3529 << theMirror << ", "
3530 << mirrorTypeName(theMirrorType) << ", "
3531 << theCopyGroups << ", '"
3532 << theMeshName << "' )";
3537 if (!myIsPreviewMode && mesh_i)
3538 mesh_i->GetGroups();
3540 return mesh._retn();
3543 //=======================================================================
3544 //function : translate
3546 //=======================================================================
3548 SMESH::ListOfGroups*
3549 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3550 const SMESH::DirStruct & theVector,
3551 CORBA::Boolean theCopy,
3553 ::SMESH_Mesh* theTargetMesh)
3558 if ( theTargetMesh )
3562 const SMESH::PointStruct * P = &theVector.PS;
3563 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3565 TIDSortedElemSet copyElements;
3566 TIDSortedElemSet* workElements = &theElements;
3568 if ( myIsPreviewMode )
3570 TPreviewMesh * tmpMesh = getPreviewMesh();
3571 tmpMesh->Copy( theElements, copyElements);
3572 if ( !theCopy && !theTargetMesh )
3574 TIDSortedElemSet elemsAround, elemsAroundCopy;
3575 getElementsAround( theElements, getMeshDS(), elemsAround );
3576 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3578 workElements = & copyElements;
3579 theMakeGroups = false;
3582 ::SMESH_MeshEditor::PGroupIDs groupIds =
3583 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3585 if ( !myIsPreviewMode )
3587 if ( theTargetMesh )
3588 theTargetMesh->GetMeshDS()->Modified();
3590 declareMeshModified( /*isReComputeSafe=*/false );
3593 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3595 SMESH_CATCH( SMESH::throwCorbaException );
3599 //=======================================================================
3600 //function : Translate
3602 //=======================================================================
3604 void SMESH_MeshEditor_i::Translate(const SMESH::smIdType_array & theIDsOfElements,
3605 const SMESH::DirStruct & theVector,
3606 CORBA::Boolean theCopy)
3608 if (!myIsPreviewMode) {
3609 TPythonDump() << this << ".Translate( "
3610 << theIDsOfElements << ", "
3611 << theVector << ", "
3614 if (theIDsOfElements.length()) {
3615 TIDSortedElemSet elements;
3616 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3617 translate(elements, theVector, theCopy, false);
3621 //=======================================================================
3622 //function : TranslateObject
3624 //=======================================================================
3626 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3627 const SMESH::DirStruct & theVector,
3628 CORBA::Boolean theCopy)
3630 if (!myIsPreviewMode) {
3631 TPythonDump() << this << ".TranslateObject( "
3632 << theObject << ", "
3633 << theVector << ", "
3636 TIDSortedElemSet elements;
3638 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3640 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3641 translate(elements, theVector, theCopy, false);
3644 //=======================================================================
3645 //function : TranslateMakeGroups
3647 //=======================================================================
3649 SMESH::ListOfGroups*
3650 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3651 const SMESH::DirStruct& theVector)
3653 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3655 SMESH::ListOfGroups * aGroups = 0;
3656 if (theIDsOfElements.length()) {
3657 TIDSortedElemSet elements;
3658 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3659 aGroups = translate(elements,theVector,true,true);
3661 if (!myIsPreviewMode) {
3662 dumpGroupsList(aPythonDump, aGroups);
3663 aPythonDump << this << ".TranslateMakeGroups( "
3664 << theIDsOfElements << ", "
3665 << theVector << " )";
3667 return aGroups ? aGroups : new SMESH::ListOfGroups();
3670 //=======================================================================
3671 //function : TranslateObjectMakeGroups
3673 //=======================================================================
3675 SMESH::ListOfGroups*
3676 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3677 const SMESH::DirStruct& theVector)
3679 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3681 SMESH::ListOfGroups * aGroups = 0;
3682 TIDSortedElemSet elements;
3683 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3684 aGroups = translate(elements, theVector, true, true);
3686 if (!myIsPreviewMode) {
3687 dumpGroupsList(aPythonDump, aGroups);
3688 aPythonDump << this << ".TranslateObjectMakeGroups( "
3689 << theObject << ", "
3690 << theVector << " )";
3692 return aGroups ? aGroups : new SMESH::ListOfGroups();
3695 //=======================================================================
3696 //function : TranslateMakeMesh
3698 //=======================================================================
3700 SMESH::SMESH_Mesh_ptr
3701 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3702 const SMESH::DirStruct& theVector,
3703 CORBA::Boolean theCopyGroups,
3704 const char* theMeshName)
3706 SMESH_Mesh_i* mesh_i;
3707 SMESH::SMESH_Mesh_var mesh;
3709 { // open new scope to dump "MakeMesh" command
3710 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3712 TPythonDump pydump; // to prevent dump at mesh creation
3714 mesh = makeMesh( theMeshName );
3715 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3717 if ( mesh_i && theIDsOfElements.length() )
3719 TIDSortedElemSet elements;
3720 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3721 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3722 mesh_i->CreateGroupServants();
3725 if ( !myIsPreviewMode ) {
3726 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3727 << theIDsOfElements << ", "
3728 << theVector << ", "
3729 << theCopyGroups << ", '"
3730 << theMeshName << "' )";
3735 if (!myIsPreviewMode && mesh_i)
3736 mesh_i->GetGroups();
3738 return mesh._retn();
3741 //=======================================================================
3742 //function : TranslateObjectMakeMesh
3744 //=======================================================================
3746 SMESH::SMESH_Mesh_ptr
3747 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3748 const SMESH::DirStruct& theVector,
3749 CORBA::Boolean theCopyGroups,
3750 const char* theMeshName)
3753 SMESH_Mesh_i* mesh_i;
3754 SMESH::SMESH_Mesh_var mesh;
3755 { // open new scope to dump "MakeMesh" command
3756 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3758 TPythonDump pydump; // to prevent dump at mesh creation
3759 mesh = makeMesh( theMeshName );
3760 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3762 TIDSortedElemSet elements;
3764 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3766 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3767 mesh_i->CreateGroupServants();
3769 if ( !myIsPreviewMode ) {
3770 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3771 << theObject << ", "
3772 << theVector << ", "
3773 << theCopyGroups << ", '"
3774 << theMeshName << "' )";
3779 if (!myIsPreviewMode && mesh_i)
3780 mesh_i->GetGroups();
3782 return mesh._retn();
3784 SMESH_CATCH( SMESH::throwCorbaException );
3788 //=======================================================================
3791 //=======================================================================
3793 SMESH::ListOfGroups*
3794 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3795 const SMESH::AxisStruct & theAxis,
3796 CORBA::Double theAngle,
3797 CORBA::Boolean theCopy,
3799 ::SMESH_Mesh* theTargetMesh)
3804 if ( theTargetMesh )
3807 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3808 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3811 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3813 TIDSortedElemSet copyElements;
3814 TIDSortedElemSet* workElements = &theElements;
3815 if ( myIsPreviewMode ) {
3816 TPreviewMesh * tmpMesh = getPreviewMesh();
3817 tmpMesh->Copy( theElements, copyElements );
3818 if ( !theCopy && !theTargetMesh )
3820 TIDSortedElemSet elemsAround, elemsAroundCopy;
3821 getElementsAround( theElements, getMeshDS(), elemsAround );
3822 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3824 workElements = ©Elements;
3825 theMakeGroups = false;
3828 ::SMESH_MeshEditor::PGroupIDs groupIds =
3829 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3831 if ( !myIsPreviewMode)
3833 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3834 else declareMeshModified( /*isReComputeSafe=*/false );
3837 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3839 SMESH_CATCH( SMESH::throwCorbaException );
3843 //=======================================================================
3846 //=======================================================================
3848 void SMESH_MeshEditor_i::Rotate(const SMESH::smIdType_array & theIDsOfElements,
3849 const SMESH::AxisStruct & theAxis,
3850 CORBA::Double theAngle,
3851 CORBA::Boolean theCopy)
3853 if (!myIsPreviewMode) {
3854 TPythonDump() << this << ".Rotate( "
3855 << theIDsOfElements << ", "
3857 << TVar( theAngle ) << ", "
3860 if (theIDsOfElements.length() > 0)
3862 TIDSortedElemSet elements;
3863 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3864 rotate(elements,theAxis,theAngle,theCopy,false);
3868 //=======================================================================
3869 //function : RotateObject
3871 //=======================================================================
3873 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3874 const SMESH::AxisStruct & theAxis,
3875 CORBA::Double theAngle,
3876 CORBA::Boolean theCopy)
3878 if ( !myIsPreviewMode ) {
3879 TPythonDump() << this << ".RotateObject( "
3880 << theObject << ", "
3882 << TVar( theAngle ) << ", "
3885 TIDSortedElemSet elements;
3886 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3887 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3888 rotate(elements,theAxis,theAngle,theCopy,false);
3891 //=======================================================================
3892 //function : RotateMakeGroups
3894 //=======================================================================
3896 SMESH::ListOfGroups*
3897 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3898 const SMESH::AxisStruct& theAxis,
3899 CORBA::Double theAngle)
3901 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3903 SMESH::ListOfGroups * aGroups = 0;
3904 if (theIDsOfElements.length() > 0)
3906 TIDSortedElemSet elements;
3907 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3908 aGroups = rotate(elements,theAxis,theAngle,true,true);
3910 if (!myIsPreviewMode) {
3911 dumpGroupsList(aPythonDump, aGroups);
3912 aPythonDump << this << ".RotateMakeGroups( "
3913 << theIDsOfElements << ", "
3915 << TVar( theAngle ) << " )";
3917 return aGroups ? aGroups : new SMESH::ListOfGroups();
3920 //=======================================================================
3921 //function : RotateObjectMakeGroups
3923 //=======================================================================
3925 SMESH::ListOfGroups*
3926 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3927 const SMESH::AxisStruct& theAxis,
3928 CORBA::Double theAngle)
3930 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3932 SMESH::ListOfGroups * aGroups = 0;
3933 TIDSortedElemSet elements;
3934 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3935 aGroups = rotate(elements, theAxis, theAngle, true, true);
3937 if (!myIsPreviewMode) {
3938 dumpGroupsList(aPythonDump, aGroups);
3939 aPythonDump << this << ".RotateObjectMakeGroups( "
3940 << theObject << ", "
3942 << TVar( theAngle ) << " )";
3944 return aGroups ? aGroups : new SMESH::ListOfGroups();
3947 //=======================================================================
3948 //function : RotateMakeMesh
3950 //=======================================================================
3952 SMESH::SMESH_Mesh_ptr
3953 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3954 const SMESH::AxisStruct& theAxis,
3955 CORBA::Double theAngleInRadians,
3956 CORBA::Boolean theCopyGroups,
3957 const char* theMeshName)
3960 SMESH::SMESH_Mesh_var mesh;
3961 SMESH_Mesh_i* mesh_i;
3963 { // open new scope to dump "MakeMesh" command
3964 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3966 TPythonDump pydump; // to prevent dump at mesh creation
3968 mesh = makeMesh( theMeshName );
3969 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3971 if ( mesh_i && theIDsOfElements.length() > 0 )
3973 TIDSortedElemSet elements;
3974 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3975 rotate(elements, theAxis, theAngleInRadians,
3976 false, theCopyGroups, & mesh_i->GetImpl());
3977 mesh_i->CreateGroupServants();
3979 if ( !myIsPreviewMode ) {
3980 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3981 << theIDsOfElements << ", "
3983 << TVar( theAngleInRadians ) << ", "
3984 << theCopyGroups << ", '"
3985 << theMeshName << "' )";
3990 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3991 mesh_i->GetGroups();
3993 return mesh._retn();
3995 SMESH_CATCH( SMESH::throwCorbaException );
3999 //=======================================================================
4000 //function : RotateObjectMakeMesh
4002 //=======================================================================
4004 SMESH::SMESH_Mesh_ptr
4005 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4006 const SMESH::AxisStruct& theAxis,
4007 CORBA::Double theAngleInRadians,
4008 CORBA::Boolean theCopyGroups,
4009 const char* theMeshName)
4012 SMESH::SMESH_Mesh_var mesh;
4013 SMESH_Mesh_i* mesh_i;
4015 {// open new scope to dump "MakeMesh" command
4016 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4018 TPythonDump pydump; // to prevent dump at mesh creation
4019 mesh = makeMesh( theMeshName );
4020 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4022 TIDSortedElemSet elements;
4024 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4026 rotate(elements, theAxis, theAngleInRadians,
4027 false, theCopyGroups, & mesh_i->GetImpl());
4028 mesh_i->CreateGroupServants();
4030 if ( !myIsPreviewMode ) {
4031 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
4032 << theObject << ", "
4034 << TVar( theAngleInRadians ) << ", "
4035 << theCopyGroups << ", '"
4036 << theMeshName << "' )";
4041 if (!myIsPreviewMode && mesh_i)
4042 mesh_i->GetGroups();
4044 return mesh._retn();
4046 SMESH_CATCH( SMESH::throwCorbaException );
4050 //=======================================================================
4053 //=======================================================================
4055 SMESH::ListOfGroups*
4056 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
4057 const SMESH::PointStruct& thePoint,
4058 const SMESH::double_array& theScaleFact,
4059 CORBA::Boolean theCopy,
4061 ::SMESH_Mesh* theTargetMesh)
4065 if ( theScaleFact.length() < 1 )
4066 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
4067 if ( theScaleFact.length() == 2 )
4068 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
4070 if ( theTargetMesh )
4073 TIDSortedElemSet elements;
4074 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4075 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4080 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
4081 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
4085 // fight against orthogonalization
4086 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
4087 // 0, S[1], 0, thePoint.y * (1-S[1]),
4088 // 0, 0, S[2], thePoint.z * (1-S[2]) );
4089 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
4090 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
4091 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
4092 loc.SetCoord( thePoint.x * (1-S[0]),
4093 thePoint.y * (1-S[1]),
4094 thePoint.z * (1-S[2]));
4095 M.SetDiagonal( S[0], S[1], S[2] );
4097 TIDSortedElemSet copyElements;
4098 TIDSortedElemSet* workElements = &elements;
4099 if ( myIsPreviewMode )
4101 TPreviewMesh * tmpMesh = getPreviewMesh();
4102 tmpMesh->Copy( elements, copyElements);
4103 if ( !theCopy && !theTargetMesh )
4105 TIDSortedElemSet elemsAround, elemsAroundCopy;
4106 getElementsAround( elements, getMeshDS(), elemsAround );
4107 tmpMesh->Copy( elemsAround, elemsAroundCopy);
4109 workElements = & copyElements;
4110 theMakeGroups = false;
4113 ::SMESH_MeshEditor::PGroupIDs groupIds =
4114 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4116 if ( !myIsPreviewMode )
4118 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
4119 else declareMeshModified( /*isReComputeSafe=*/false );
4121 return theMakeGroups ? getGroups(groupIds.get()) : 0;
4123 SMESH_CATCH( SMESH::throwCorbaException );
4127 //=======================================================================
4130 //=======================================================================
4132 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
4133 const SMESH::PointStruct& thePoint,
4134 const SMESH::double_array& theScaleFact,
4135 CORBA::Boolean theCopy)
4137 if ( !myIsPreviewMode ) {
4138 TPythonDump() << this << ".Scale( "
4139 << theObject << ", "
4141 << TVar( theScaleFact ) << ", "
4144 scale(theObject, thePoint, theScaleFact, theCopy, false);
4148 //=======================================================================
4149 //function : ScaleMakeGroups
4151 //=======================================================================
4153 SMESH::ListOfGroups*
4154 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4155 const SMESH::PointStruct& thePoint,
4156 const SMESH::double_array& theScaleFact)
4158 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4160 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
4161 if (!myIsPreviewMode) {
4162 dumpGroupsList(aPythonDump, aGroups);
4163 aPythonDump << this << ".Scale("
4166 << TVar( theScaleFact ) << ",True,True)";
4172 //=======================================================================
4173 //function : ScaleMakeMesh
4175 //=======================================================================
4177 SMESH::SMESH_Mesh_ptr
4178 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4179 const SMESH::PointStruct& thePoint,
4180 const SMESH::double_array& theScaleFact,
4181 CORBA::Boolean theCopyGroups,
4182 const char* theMeshName)
4184 SMESH_Mesh_i* mesh_i;
4185 SMESH::SMESH_Mesh_var mesh;
4186 { // open new scope to dump "MakeMesh" command
4187 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4189 TPythonDump pydump; // to prevent dump at mesh creation
4190 mesh = makeMesh( theMeshName );
4191 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4195 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4196 mesh_i->CreateGroupServants();
4198 if ( !myIsPreviewMode )
4199 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4200 << theObject << ", "
4202 << TVar( theScaleFact ) << ", "
4203 << theCopyGroups << ", '"
4204 << theMeshName << "' )";
4208 if (!myIsPreviewMode && mesh_i)
4209 mesh_i->GetGroups();
4211 return mesh._retn();
4214 //================================================================================
4216 * \brief Make an offset mesh from a source 2D mesh
4217 * \param [inout] theObject - source mesh. New elements are added to this mesh
4218 * if \a theMeshName is empty.
4219 * \param [in] theValue - offset value
4220 * \param [in] theCopyGroups - to generate groups
4221 * \param [in] theMeshName - optional name of a new mesh
4222 * \param [out] theGroups - new groups
4223 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4225 //================================================================================
4227 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4228 CORBA::Double theValue,
4229 CORBA::Boolean theCopyGroups,
4230 CORBA::Boolean theCopyElements,
4231 const char* theMeshName,
4232 SMESH::ListOfGroups_out theGroups)
4237 SMESHDS_Mesh* aMeshDS = getMeshDS();
4239 SMESH::SMESH_Mesh_var mesh_var;
4240 ::SMESH_MeshEditor::PGroupIDs groupIds;
4244 TIDSortedElemSet elements, copyElements;
4245 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4246 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4249 SMESH_Mesh* tgtMesh = 0;
4250 if ( myIsPreviewMode )
4252 TPreviewMesh * tmpMesh = getPreviewMesh();
4254 tmpMesh->Copy( elements, copyElements );
4255 elements.swap( copyElements );
4256 theCopyGroups = false;
4257 theCopyElements = false;
4262 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4263 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4264 tgtMesh = & mesh_i->GetImpl();
4266 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4267 theCopyGroups, theCopyElements, !myIsPreviewMode );
4269 tgtMesh->GetMeshDS()->Modified();
4272 if ( myIsPreviewMode )
4274 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4278 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4280 // new mesh empty, remove it
4281 SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
4282 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4283 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::GetSMESHGen()->ObjectToSObject( mesh_var );
4284 builder->RemoveObjectWithChildren( meshSO );
4285 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4287 if ( !groupIds ) // nothing changed in the current mesh
4288 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4290 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4292 // result of Offset() is a tuple (mesh, groups)
4293 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4294 else pyDump << mesh_var << ", ";
4295 pyDump << theGroups << " = " << this << ".Offset( "
4296 << theObject << ", "
4298 << theCopyGroups << ", "
4299 << theCopyElements << ", "
4300 << "'" << theMeshName<< "')";
4303 return mesh_var._retn();
4305 SMESH_CATCH( SMESH::throwCorbaException );
4306 return SMESH::SMESH_Mesh::_nil();
4309 //=======================================================================
4310 //function : findCoincidentNodes
4312 //=======================================================================
4314 void SMESH_MeshEditor_i::
4315 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4316 CORBA::Double Tolerance,
4317 SMESH::array_of_long_array_out GroupsOfNodes,
4318 CORBA::Boolean SeparateCornersAndMedium)
4320 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4321 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4323 GroupsOfNodes = new SMESH::array_of_long_array;
4324 GroupsOfNodes->length( aListOfListOfNodes.size() );
4325 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4326 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4328 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4329 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4330 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4331 aGroup.length( aListOfNodes.size() );
4332 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4333 aGroup[ j ] = (*lIt)->GetID();
4337 //=======================================================================
4338 //function : FindCoincidentNodes
4340 //=======================================================================
4342 void SMESH_MeshEditor_i::
4343 FindCoincidentNodes (CORBA::Double Tolerance,
4344 SMESH::array_of_long_array_out GroupsOfNodes,
4345 CORBA::Boolean SeparateCornersAndMedium)
4350 TIDSortedNodeSet nodes; // no input nodes
4351 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4353 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4354 << Tolerance << ", "
4355 << SeparateCornersAndMedium << " )";
4357 SMESH_CATCH( SMESH::throwCorbaException );
4360 //=======================================================================
4361 //function : FindCoincidentNodesOnPart
4363 //=======================================================================
4365 void SMESH_MeshEditor_i::
4366 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4367 CORBA::Double Tolerance,
4368 SMESH::array_of_long_array_out GroupsOfNodes,
4369 CORBA::Boolean SeparateCornersAndMedium)
4374 TIDSortedNodeSet nodes;
4375 prepareIdSource( theObject );
4376 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4378 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4380 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4382 << Tolerance << ", "
4383 << SeparateCornersAndMedium << " )";
4385 SMESH_CATCH( SMESH::throwCorbaException );
4388 //================================================================================
4390 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4391 * ExceptSubMeshOrGroups
4393 //================================================================================
4395 void SMESH_MeshEditor_i::
4396 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4397 CORBA::Double theTolerance,
4398 SMESH::array_of_long_array_out theGroupsOfNodes,
4399 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4400 CORBA::Boolean theSeparateCornersAndMedium)
4405 TIDSortedNodeSet nodes;
4406 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4408 prepareIdSource( theObjects[i] );
4409 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4411 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4413 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4415 while ( nodeIt->more() )
4416 nodes.erase( cast2Node( nodeIt->next() ));
4418 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4420 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4421 << theObjects <<", "
4422 << theTolerance << ", "
4423 << theExceptSubMeshOrGroups << ", "
4424 << theSeparateCornersAndMedium << " )";
4426 SMESH_CATCH( SMESH::throwCorbaException );
4429 //=======================================================================
4430 //function : MergeNodes
4432 //=======================================================================
4434 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4435 const SMESH::ListOfIDSources& NodesToKeep,
4436 CORBA::Boolean AvoidMakingHoles)
4441 SMESHDS_Mesh* aMesh = getMeshDS();
4443 TPythonDump aTPythonDump;
4444 aTPythonDump << this << ".MergeNodes([";
4446 TIDSortedNodeSet setOfNodesToKeep;
4447 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4449 prepareIdSource( NodesToKeep[i] );
4450 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4451 while ( nodeIt->more() )
4452 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4455 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4456 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4458 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4459 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4460 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4461 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4463 CORBA::Long index = aNodeGroup[ j ];
4464 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4466 if ( setOfNodesToKeep.count( node ))
4467 aListOfNodes.push_front( node );
4469 aListOfNodes.push_back( node );
4472 if ( aListOfNodes.size() < 2 )
4473 aListOfListOfNodes.pop_back();
4475 if ( i > 0 ) aTPythonDump << ", ";
4476 aTPythonDump << aNodeGroup;
4479 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4481 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4483 declareMeshModified( /*isReComputeSafe=*/false );
4485 SMESH_CATCH( SMESH::throwCorbaException );
4488 //=======================================================================
4489 //function : FindEqualElements
4491 //=======================================================================
4493 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4494 const SMESH::ListOfIDSources& theExceptObjects,
4495 SMESH::array_of_long_array_out theGroupsOfElementsID)
4500 theGroupsOfElementsID = new SMESH::array_of_long_array;
4502 TIDSortedElemSet elems;
4503 bool hasOkObject = false;
4504 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4506 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4508 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4509 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4510 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4516 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4518 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4519 while ( elemIt->more() )
4520 elems.erase( elemIt->next() );
4523 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4524 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4526 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4528 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4529 aListOfListOfElementsID.begin();
4530 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4532 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4533 list<smIdType>& listOfIDs = *arraysIt;
4534 aGroup.length( listOfIDs.size() );
4535 list<smIdType>::iterator idIt = listOfIDs.begin();
4536 for (smIdType k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4537 aGroup[ k ] = *idIt;
4540 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4541 << theObjects << ", "
4542 << theExceptObjects << " )";
4545 SMESH_CATCH( SMESH::throwCorbaException );
4548 //=======================================================================
4549 //function : MergeElements
4551 //=======================================================================
4553 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4554 const SMESH::ListOfIDSources& theElementsToKeep)
4559 TPythonDump aTPythonDump;
4560 aTPythonDump << this << ".MergeElements( [";
4562 NCollection_Map< int > idsToKeep;
4563 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4565 if ( CORBA::is_nil( theElementsToKeep[i] ))
4567 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4568 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4570 SMESH::smIdType_array_var elementsId = theElementsToKeep[i]->GetIDs();
4571 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4572 idsToKeep.Add( elementsId[ j ]);
4575 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4577 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4579 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4580 aListOfListOfElementsID.push_back( list< smIdType >() );
4581 list< smIdType >& aListOfElemsID = aListOfListOfElementsID.back();
4582 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4584 SMESH::smIdType id = anElemsIDGroup[ j ];
4585 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4586 else aListOfElemsID.push_back( id );
4588 if ( aListOfElemsID.size() < 2 )
4589 aListOfListOfElementsID.pop_back();
4590 if ( i > 0 ) aTPythonDump << ", ";
4591 aTPythonDump << anElemsIDGroup;
4594 getEditor().MergeElements(aListOfListOfElementsID);
4596 declareMeshModified( /*isReComputeSafe=*/true );
4598 aTPythonDump << "], " << theElementsToKeep << " )";
4600 SMESH_CATCH( SMESH::throwCorbaException );
4603 //=======================================================================
4604 //function : MergeEqualElements
4606 //=======================================================================
4608 void SMESH_MeshEditor_i::MergeEqualElements()
4613 getEditor().MergeEqualElements();
4615 declareMeshModified( /*isReComputeSafe=*/true );
4617 TPythonDump() << this << ".MergeEqualElements()";
4619 SMESH_CATCH( SMESH::throwCorbaException );
4622 //=============================================================================
4624 * Move the node to a given point
4626 //=============================================================================
4628 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(SMESH::smIdType NodeID,
4634 initData(/*deleteSearchers=*/false);
4636 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4640 if ( theNodeSearcher )
4641 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4643 if ( myIsPreviewMode ) // make preview data
4645 // in a preview mesh, make edges linked to a node
4646 TPreviewMesh& tmpMesh = *getPreviewMesh();
4647 TIDSortedElemSet linkedNodes;
4648 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4649 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4650 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4651 for ( ; nIt != linkedNodes.end(); ++nIt )
4653 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4654 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4658 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4660 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4661 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4663 getMeshDS()->MoveNode(node, x, y, z);
4665 if ( !myIsPreviewMode )
4667 // Update Python script
4668 TPythonDump() << "isDone = " << this << ".MoveNode( "
4669 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4670 declareMeshModified( /*isReComputeSafe=*/false );
4673 SMESH_CATCH( SMESH::throwCorbaException );
4678 //================================================================================
4680 * \brief Return ID of node closest to a given point
4682 //================================================================================
4684 SMESH::smIdType SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4689 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4691 if ( !theNodeSearcher ) {
4692 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4695 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4696 return node->GetID();
4698 SMESH_CATCH( SMESH::throwCorbaException );
4702 //================================================================================
4704 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4705 * move the node closest to the point to point's location and return ID of the node
4707 //================================================================================
4709 SMESH::smIdType SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4712 SMESH::smIdType theNodeID)
4715 // We keep theNodeSearcher until any mesh modification:
4716 // 1) initData() deletes theNodeSearcher at any edition,
4717 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4719 initData(/*deleteSearchers=*/false);
4721 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4723 smIdType nodeID = theNodeID;
4724 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4725 if ( !node ) // preview moving node
4727 if ( !theNodeSearcher ) {
4728 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4731 node = theNodeSearcher->FindClosestTo( p );
4734 nodeID = node->GetID();
4735 if ( myIsPreviewMode ) // make preview data
4737 // in a preview mesh, make edges linked to a node
4738 TPreviewMesh tmpMesh = *getPreviewMesh();
4739 TIDSortedElemSet linkedNodes;
4740 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4741 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4742 for ( ; nIt != linkedNodes.end(); ++nIt )
4744 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4745 tmpMesh.Copy( &edge );
4748 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4750 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4751 // fill preview data
4753 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4755 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4759 getMeshDS()->MoveNode(node, x, y, z);
4763 if ( !myIsPreviewMode )
4765 TPythonDump() << "nodeID = " << this
4766 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4767 << ", " << nodeID << " )";
4769 declareMeshModified( /*isReComputeSafe=*/false );
4774 SMESH_CATCH( SMESH::throwCorbaException );
4778 //=======================================================================
4780 * Return elements of given type where the given point is IN or ON.
4782 * 'ALL' type means elements of any type excluding nodes
4784 //=======================================================================
4786 SMESH::smIdType_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4789 SMESH::ElementType type)
4792 SMESH::smIdType_array_var res = new SMESH::smIdType_array;
4793 vector< const SMDS_MeshElement* > foundElems;
4795 theSearchersDeleter.Set( myMesh );
4796 if ( !theElementSearcher ) {
4797 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4799 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4800 SMDSAbs_ElementType( type ),
4802 res->length( foundElems.size() );
4803 for ( size_t i = 0; i < foundElems.size(); ++i )
4804 res[i] = foundElems[i]->GetID();
4808 SMESH_CATCH( SMESH::throwCorbaException );
4812 //=======================================================================
4813 //function : FindAmongElementsByPoint
4814 //purpose : Searching among the given elements, return elements of given type
4815 // where the given point is IN or ON.
4816 // 'ALL' type means elements of any type excluding nodes
4817 //=======================================================================
4819 SMESH::smIdType_array*
4820 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4824 SMESH::ElementType type)
4827 SMESH::smIdType_array_var res = new SMESH::smIdType_array;
4829 prepareIdSource( elementIDs );
4830 if ( type != SMESH::NODE )
4832 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4833 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4834 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4835 type != types[0] ) // but search of elements of dim > 0
4839 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4840 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4841 if ( mesh_i != myMesh_i )
4843 SMESH::SMESH_MeshEditor_var editor=
4844 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4845 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4848 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4849 return FindElementsByPoint( x,y,z, type );
4851 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4853 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4854 if ( !theElementSearcher )
4856 // create a searcher from elementIDs
4857 SMDS_ElemIteratorPtr elemIt;
4858 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4860 //prepareIdSource( elementIDs );
4861 elemIt = myMesh_i->GetElements( elementIDs, type );
4865 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4868 vector< const SMDS_MeshElement* > foundElems;
4870 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4871 SMDSAbs_ElementType( type ),
4873 res->length( foundElems.size() );
4874 for ( size_t i = 0; i < foundElems.size(); ++i )
4875 res[i] = foundElems[i]->GetID();
4879 SMESH_CATCH( SMESH::throwCorbaException );
4883 //=======================================================================
4884 //function : ProjectPoint
4885 //purpose : Project a point to a mesh object.
4886 // Return ID of an element of given type where the given point is projected
4887 // and coordinates of the projection point.
4888 // In the case if nothing found, return -1 and []
4889 //=======================================================================
4891 SMESH::smIdType SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4894 SMESH::ElementType type,
4895 SMESH::SMESH_IDSource_ptr meshObject,
4896 SMESH::double_array_out projecton)
4898 if ( CORBA::is_nil( meshObject ))
4899 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4903 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4904 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4905 if ( mesh_i != myMesh_i )
4907 SMESH::SMESH_MeshEditor_var editor=
4908 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4909 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4913 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4914 if ( !theElementSearcher )
4916 // create a searcher from meshObject
4918 SMDS_ElemIteratorPtr elemIt;
4919 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4921 prepareIdSource( meshObject );
4922 elemIt = myMesh_i->GetElements( meshObject, type );
4926 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4929 const SMDS_MeshElement* elem = 0;
4930 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4931 SMDSAbs_ElementType( type ),
4934 projecton = new SMESH::double_array();
4935 if ( elem && !elem->IsNull() )
4937 projecton->length( 3 );
4938 projecton[0] = pProj.X();
4939 projecton[1] = pProj.Y();
4940 projecton[2] = pProj.Z();
4941 return elem->GetID();
4944 SMESH_CATCH( SMESH::throwCorbaException );
4948 //=======================================================================
4949 //function : GetPointState
4950 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4951 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4952 //=======================================================================
4954 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4959 theSearchersDeleter.Set( myMesh );
4960 if ( !theElementSearcher ) {
4961 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4963 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4965 SMESH_CATCH( SMESH::throwCorbaException );
4969 //=======================================================================
4970 //function : IsManifold
4971 //purpose : Check if a 2D mesh is manifold
4972 //=======================================================================
4974 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4976 bool isManifold = true;
4979 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4980 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4982 /*closedOnly=*/true,
4984 SMESH_CATCH( SMESH::throwCorbaException );
4989 //=======================================================================
4990 //function : IsCoherentOrientation2D
4991 //purpose : Check if orientation of 2D elements is coherent
4992 //=======================================================================
4994 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4996 bool isGoodOri = true;
4999 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
5000 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
5002 /*closedOnly=*/true,
5005 SMESH_CATCH( SMESH::throwCorbaException );
5010 //=======================================================================
5011 //function : Get1DBranches
5012 //purpose : Partition given 1D elements into groups of contiguous edges.
5013 // A node where number of meeting edges != 2 is a group end.
5014 // An optional startNode is used to orient groups it belongs to.
5015 //return : a list of edge groups and a list of corresponding node groups.
5016 // If a group is closed, the first and last nodes of the group are same.
5017 //=======================================================================
5019 SMESH::array_of_long_array*
5020 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
5021 SMESH::smIdType theStartNode,
5022 SMESH::array_of_long_array_out theNodeGroups )
5024 if ( CORBA::is_nil( theEdges ))
5025 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
5027 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
5028 theNodeGroups = new SMESH::array_of_long_array;
5032 prepareIdSource( theEdges );
5034 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
5035 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
5036 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
5039 getMeshDS()->FindNode( theStartNode ));
5041 edgeGroupArray->length( edgeBranches.size() );
5042 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
5044 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
5045 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
5046 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
5049 theNodeGroups->length( nodeBranches.size() );
5050 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
5052 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
5053 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
5054 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
5057 SMESH_CATCH( SMESH::throwCorbaException );
5059 return edgeGroupArray._retn();
5062 //=======================================================================
5063 //function : FindSharpEdges
5064 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
5065 //=======================================================================
5067 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
5068 CORBA::Boolean theAddExisting)
5070 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
5075 std::vector< SMESH_MeshAlgos::Edge > edges =
5076 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
5078 if ( myIsPreviewMode ) // fill a preview mesh with edges
5080 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
5081 SMDS_Mesh* meshDS = mesh->GetMeshDS();
5082 for ( size_t i = 0; i < edges.size(); ++i )
5084 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
5085 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
5086 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
5087 if ( edges[i]._medium )
5089 xyz1.Set( edges[i]._medium );
5090 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
5091 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
5095 mesh->GetMeshDS()->AddEdge( n1, n2 );
5101 resultEdges->length( edges.size() );
5102 for ( size_t i = 0; i < edges.size(); ++i )
5104 resultEdges[ i ].node1 = edges[i]._node1->GetID();
5105 resultEdges[ i ].node2 = edges[i]._node2->GetID();
5106 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
5109 SMESH_CATCH( SMESH::throwCorbaException );
5110 return resultEdges._retn();
5113 //=======================================================================
5114 //function : FindFreeBorders
5115 //purpose : Returns all or only closed FreeBorder's.
5116 //=======================================================================
5118 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
5120 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
5123 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
5124 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
5126 resBorders->length( foundFreeBordes.size() );
5127 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
5129 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
5130 SMESH::FreeBorder& bordOut = resBorders[i];
5131 bordOut.nodeIDs.length( bordNodes.size() );
5132 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
5133 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
5136 SMESH_CATCH( SMESH::throwCorbaException );
5138 return resBorders._retn();
5141 //=======================================================================
5142 //function : FillHole
5143 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
5144 //=======================================================================
5146 SMESH::SMESH_Group_ptr
5147 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
5148 const char* theGroupName)
5152 if ( theHole.nodeIDs.length() < 4 )
5153 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
5154 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
5155 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
5156 "First and last nodes must be same", SALOME::BAD_PARAM);
5158 SMESH_MeshAlgos::TFreeBorder bordNodes;
5159 bordNodes.resize( theHole.nodeIDs.length() );
5160 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
5162 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
5163 if ( !bordNodes[ iN ] )
5164 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
5165 << " does not exist", SALOME::BAD_PARAM);
5170 // prepare a preview mesh
5171 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5172 SMDS_Mesh* meshDS = getMeshDS();
5173 if ( myIsPreviewMode )
5175 // copy faces sharing nodes of theHole
5176 TIDSortedElemSet holeFaces;
5177 previewMesh = getPreviewMesh( SMDSAbs_Face );
5178 for ( size_t i = 0; i < bordNodes.size(); ++i )
5180 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5181 while ( fIt->more() )
5183 const SMDS_MeshElement* face = fIt->next();
5184 if ( holeFaces.insert( face ).second )
5185 previewMesh->Copy( face );
5187 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5188 ASSERT( bordNodes[i] );
5190 meshDS = previewMesh->GetMeshDS();
5194 std::vector<const SMDS_MeshElement*> newFaces;
5195 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5197 if ( myIsPreviewMode )
5200 previewMesh->Clear();
5201 for ( size_t i = 0; i < newFaces.size(); ++i )
5202 previewMesh->Copy( newFaces[i] );
5206 // return new faces via a group
5207 SMESH::SMESH_Group_var group;
5208 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5210 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5211 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5213 SMESH::SMESH_GroupBase_var g = groups[ i ];
5214 if ( g->GetType() != SMESH::FACE ) continue;
5215 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5216 if ( standalone->_is_nil() ) continue;
5217 CORBA::String_var name = g->GetName();
5218 if ( strcmp( theGroupName, name.in() ) == 0 )
5224 if ( group->_is_nil() )
5225 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5227 if ( !group->_is_nil() )
5229 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5230 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5231 for ( size_t i = 0; i < newFaces.size(); ++i )
5232 grpDS->Add( newFaces[ i ]);
5237 getEditor().ClearLastCreated();
5238 SMESH_SequenceOfElemPtr& aSeq =
5239 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5240 aSeq.swap( newFaces );
5243 if ( group->_is_nil() ) pyDump << "_group = ";
5244 else pyDump << group << " = ";
5245 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5247 return group._retn();
5250 SMESH_CATCH( SMESH::throwCorbaException );
5252 return SMESH::SMESH_Group::_nil();
5255 //=======================================================================
5256 //function : convError
5258 //=======================================================================
5260 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5262 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5266 RETCASE( SEW_BORDER1_NOT_FOUND );
5267 RETCASE( SEW_BORDER2_NOT_FOUND );
5268 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5269 RETCASE( SEW_BAD_SIDE_NODES );
5270 RETCASE( SEW_VOLUMES_TO_SPLIT );
5271 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5272 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5273 RETCASE( SEW_BAD_SIDE1_NODES );
5274 RETCASE( SEW_BAD_SIDE2_NODES );
5275 RETCASE( SEW_INTERNAL_ERROR );
5277 return SMESH::SMESH_MeshEditor::SEW_OK;
5280 //=======================================================================
5282 * Returns groups of FreeBorder's coincident within the given tolerance.
5283 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5284 * to free borders being compared is used.
5286 //=======================================================================
5288 SMESH::CoincidentFreeBorders*
5289 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5291 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5295 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5296 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5298 // copy free borders
5299 aCFB->borders.length( cfb._borders.size() );
5300 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5302 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5303 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5304 aBRD.nodeIDs.length( nodes.size() );
5305 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5306 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5309 // copy coincident parts
5310 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5311 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5313 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5314 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5315 aGRP.length( grp.size() );
5316 for ( size_t iP = 0; iP < grp.size(); ++iP )
5318 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5319 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5320 aPART.border = part._border;
5321 aPART.node1 = part._node1;
5322 aPART.node2 = part._node2;
5323 aPART.nodeLast = part._nodeLast;
5326 SMESH_CATCH( SMESH::doNothing );
5328 TPythonDump() << "CoincidentFreeBorders = "
5329 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5331 return aCFB._retn();
5334 //=======================================================================
5336 * Sew FreeBorder's of each group
5338 //=======================================================================
5340 CORBA::Short SMESH_MeshEditor_i::
5341 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5342 CORBA::Boolean createPolygons,
5343 CORBA::Boolean createPolyhedra)
5345 CORBA::Short nbSewed = 0;
5347 SMESH_MeshAlgos::TFreeBorderVec groups;
5348 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5350 // check the input and collect nodes
5351 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5353 borderNodes.clear();
5354 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5355 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5357 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5358 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5359 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5361 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5363 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5364 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5365 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5366 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5367 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5368 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5370 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5371 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5372 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5373 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5375 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5377 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5379 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5381 borderNodes.push_back( n1 );
5382 borderNodes.push_back( n2 );
5383 borderNodes.push_back( n3 );
5385 groups.push_back( borderNodes );
5388 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5389 // to get nodes that replace other nodes during merge we create 0D elements
5390 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5393 vector< const SMDS_MeshElement* > tmp0Delems;
5394 for ( size_t i = 0; i < groups.size(); ++i )
5396 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5397 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5399 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5401 tmp0Delems.push_back( it0D->next() );
5403 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5407 // cout << endl << "INIT" << endl;
5408 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5410 // cout << i << " ";
5411 // if ( i % 3 == 0 ) cout << "^ ";
5412 // tmp0Delems[i]->GetNode(0)->Print( cout );
5417 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5419 for ( size_t i = 0; i < groups.size(); ++i )
5421 bool isBordToBord = true;
5422 bool groupSewed = false;
5423 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5424 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5426 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5427 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5428 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5430 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5431 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5432 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5434 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5437 // TIDSortedElemSet emptySet, avoidSet;
5438 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5440 // cout << "WRONG 2nd 1" << endl;
5441 // n0->Print( cout );
5442 // n1->Print( cout );
5444 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5446 // cout << "WRONG 2nd 2" << endl;
5447 // n3->Print( cout );
5448 // n4->Print( cout );
5451 if ( !isBordToBord )
5453 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5454 n2 = 0; // and n2 is not used
5456 // 1st border moves to 2nd
5457 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5459 /*2ndIsFreeBorder=*/ isBordToBord,
5460 createPolygons, createPolyhedra);
5461 groupSewed = ( res == ok );
5463 isBordToBord = false;
5464 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5465 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5467 // cout << t << " ";
5468 // if ( t % 3 == 0 ) cout << "^ ";
5469 // tmp0Delems[t]->GetNode(0)->Print( cout );
5472 i0D += nodes.size();
5473 nbSewed += groupSewed;
5476 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5477 << freeBorders << ", "
5478 << createPolygons << ", "
5479 << createPolyhedra << " )";
5481 SMESH_CATCH( SMESH::doNothing );
5483 declareMeshModified( /*isReComputeSafe=*/false );
5485 // remove tmp 0D elements
5487 set< const SMDS_MeshElement* > removed0D;
5488 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5490 if ( removed0D.insert( tmp0Delems[i] ).second )
5491 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5493 SMESH_CATCH( SMESH::throwCorbaException );
5498 //=======================================================================
5499 //function : SewFreeBorders
5501 //=======================================================================
5503 SMESH::SMESH_MeshEditor::Sew_Error
5504 SMESH_MeshEditor_i::SewFreeBorders(SMESH::smIdType FirstNodeID1,
5505 SMESH::smIdType SecondNodeID1,
5506 SMESH::smIdType LastNodeID1,
5507 SMESH::smIdType FirstNodeID2,
5508 SMESH::smIdType SecondNodeID2,
5509 SMESH::smIdType LastNodeID2,
5510 CORBA::Boolean CreatePolygons,
5511 CORBA::Boolean CreatePolyedrs)
5516 SMESHDS_Mesh* aMesh = getMeshDS();
5518 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5519 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5520 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5521 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5522 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5523 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5525 if (!aBorderFirstNode ||
5526 !aBorderSecondNode||
5528 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5529 if (!aSide2FirstNode ||
5530 !aSide2SecondNode ||
5532 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5534 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5535 << FirstNodeID1 << ", "
5536 << SecondNodeID1 << ", "
5537 << LastNodeID1 << ", "
5538 << FirstNodeID2 << ", "
5539 << SecondNodeID2 << ", "
5540 << LastNodeID2 << ", "
5541 << CreatePolygons<< ", "
5542 << CreatePolyedrs<< " )";
5544 SMESH::SMESH_MeshEditor::Sew_Error error =
5545 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5556 declareMeshModified( /*isReComputeSafe=*/false );
5559 SMESH_CATCH( SMESH::throwCorbaException );
5560 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5564 //=======================================================================
5565 //function : SewConformFreeBorders
5567 //=======================================================================
5569 SMESH::SMESH_MeshEditor::Sew_Error
5570 SMESH_MeshEditor_i::SewConformFreeBorders(SMESH::smIdType FirstNodeID1,
5571 SMESH::smIdType SecondNodeID1,
5572 SMESH::smIdType LastNodeID1,
5573 SMESH::smIdType FirstNodeID2,
5574 SMESH::smIdType SecondNodeID2)
5579 SMESHDS_Mesh* aMesh = getMeshDS();
5581 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5582 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5583 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5584 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5585 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5586 const SMDS_MeshNode* aSide2ThirdNode = 0;
5588 if (!aBorderFirstNode ||
5589 !aBorderSecondNode||
5591 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5592 if (!aSide2FirstNode ||
5594 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5596 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5597 << FirstNodeID1 << ", "
5598 << SecondNodeID1 << ", "
5599 << LastNodeID1 << ", "
5600 << FirstNodeID2 << ", "
5601 << SecondNodeID2 << " )";
5603 SMESH::SMESH_MeshEditor::Sew_Error error =
5604 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5613 declareMeshModified( /*isReComputeSafe=*/false );
5616 SMESH_CATCH( SMESH::throwCorbaException );
5617 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5621 //=======================================================================
5622 //function : SewBorderToSide
5624 //=======================================================================
5626 SMESH::SMESH_MeshEditor::Sew_Error
5627 SMESH_MeshEditor_i::SewBorderToSide(SMESH::smIdType FirstNodeIDOnFreeBorder,
5628 SMESH::smIdType SecondNodeIDOnFreeBorder,
5629 SMESH::smIdType LastNodeIDOnFreeBorder,
5630 SMESH::smIdType FirstNodeIDOnSide,
5631 SMESH::smIdType LastNodeIDOnSide,
5632 CORBA::Boolean CreatePolygons,
5633 CORBA::Boolean CreatePolyedrs)
5638 SMESHDS_Mesh* aMesh = getMeshDS();
5640 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5641 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5642 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5643 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5644 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5645 const SMDS_MeshNode* aSide2ThirdNode = 0;
5647 if (!aBorderFirstNode ||
5648 !aBorderSecondNode||
5650 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5651 if (!aSide2FirstNode ||
5653 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5655 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5656 << FirstNodeIDOnFreeBorder << ", "
5657 << SecondNodeIDOnFreeBorder << ", "
5658 << LastNodeIDOnFreeBorder << ", "
5659 << FirstNodeIDOnSide << ", "
5660 << LastNodeIDOnSide << ", "
5661 << CreatePolygons << ", "
5662 << CreatePolyedrs << ") ";
5664 SMESH::SMESH_MeshEditor::Sew_Error error =
5665 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5675 declareMeshModified( /*isReComputeSafe=*/false );
5678 SMESH_CATCH( SMESH::throwCorbaException );
5679 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5683 //=======================================================================
5684 //function : SewSideElements
5686 //=======================================================================
5688 SMESH::SMESH_MeshEditor::Sew_Error
5689 SMESH_MeshEditor_i::SewSideElements(const SMESH::smIdType_array& IDsOfSide1Elements,
5690 const SMESH::smIdType_array& IDsOfSide2Elements,
5691 SMESH::smIdType NodeID1OfSide1ToMerge,
5692 SMESH::smIdType NodeID1OfSide2ToMerge,
5693 SMESH::smIdType NodeID2OfSide1ToMerge,
5694 SMESH::smIdType NodeID2OfSide2ToMerge)
5699 SMESHDS_Mesh* aMesh = getMeshDS();
5701 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5702 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5703 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5704 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5706 if (!aFirstNode1ToMerge ||
5707 !aFirstNode2ToMerge )
5708 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5709 if (!aSecondNode1ToMerge||
5710 !aSecondNode2ToMerge)
5711 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5713 TIDSortedElemSet aSide1Elems, aSide2Elems;
5714 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5715 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5717 TPythonDump() << "error = " << this << ".SewSideElements( "
5718 << IDsOfSide1Elements << ", "
5719 << IDsOfSide2Elements << ", "
5720 << NodeID1OfSide1ToMerge << ", "
5721 << NodeID1OfSide2ToMerge << ", "
5722 << NodeID2OfSide1ToMerge << ", "
5723 << NodeID2OfSide2ToMerge << ")";
5725 SMESH::SMESH_MeshEditor::Sew_Error error =
5726 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5729 aSecondNode1ToMerge,
5730 aSecondNode2ToMerge));
5732 declareMeshModified( /*isReComputeSafe=*/false );
5735 SMESH_CATCH( SMESH::throwCorbaException );
5736 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5739 //================================================================================
5741 * \brief Set new nodes for given element
5742 * \param ide - element id
5743 * \param newIDs - new node ids
5744 * \retval CORBA::Boolean - true if result is OK
5746 //================================================================================
5748 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(SMESH::smIdType ide,
5749 const SMESH::smIdType_array& newIDs)
5754 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5755 if ( !elem ) return false;
5757 int nbn = newIDs.length();
5758 vector<const SMDS_MeshNode*> aNodes(nbn);
5759 for ( int i = 0; i < nbn; i++ ) {
5760 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5763 aNodes[ i ] = aNode;
5765 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5766 << ide << ", " << newIDs << " )";
5768 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5770 declareMeshModified( /*isReComputeSafe=*/ !res );
5774 SMESH_CATCH( SMESH::throwCorbaException );
5778 //=======================================================================
5780 * \brief Makes a part of the mesh quadratic or bi-quadratic
5782 //=======================================================================
5784 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5785 CORBA::Boolean theToBiQuad,
5786 SMESH::SMESH_IDSource_ptr theObject)
5791 TIDSortedElemSet elems;
5793 if ( !( elemsOK = CORBA::is_nil( theObject )))
5795 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5796 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5800 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5801 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5803 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5804 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5806 declareMeshModified( /*isReComputeSafe=*/false );
5809 SMESH_CATCH( SMESH::throwCorbaException );
5812 //=======================================================================
5813 //function : ConvertFromQuadratic
5815 //=======================================================================
5817 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5822 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5823 TPythonDump() << this << ".ConvertFromQuadratic()";
5824 declareMeshModified( /*isReComputeSafe=*/!isDone );
5827 SMESH_CATCH( SMESH::throwCorbaException );
5831 //=======================================================================
5832 //function : ConvertToQuadratic
5834 //=======================================================================
5836 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5838 convertToQuadratic( theForce3d, false );
5839 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5842 //================================================================================
5844 * \brief Makes a part of the mesh quadratic
5846 //================================================================================
5848 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5849 SMESH::SMESH_IDSource_ptr theObject)
5851 convertToQuadratic( theForce3d, false, theObject );
5852 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5855 //================================================================================
5857 * \brief Makes a part of the mesh bi-quadratic
5859 //================================================================================
5861 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5862 SMESH::SMESH_IDSource_ptr theObject)
5864 convertToQuadratic( theForce3d, true, theObject );
5865 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5868 //================================================================================
5870 * \brief Makes a part of the mesh linear
5872 //================================================================================
5874 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5881 TIDSortedElemSet elems;
5882 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5884 if ( elems.empty() )
5886 ConvertFromQuadratic();
5888 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5890 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5894 getEditor().ConvertFromQuadratic(elems);
5897 declareMeshModified( /*isReComputeSafe=*/false );
5899 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5901 SMESH_CATCH( SMESH::throwCorbaException );
5904 //=======================================================================
5905 //function : makeMesh
5906 //purpose : create a named imported mesh
5907 //=======================================================================
5909 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5911 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5912 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5913 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5914 gen->SetName( meshSO, theMeshName, "Mesh" );
5915 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5917 return mesh._retn();
5920 //=======================================================================
5921 //function : dumpGroupsList
5923 //=======================================================================
5925 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5926 const SMESH::ListOfGroups * theGroupList)
5928 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5929 if ( isDumpGroupList )
5930 theDumpPython << theGroupList << " = ";
5933 //================================================================================
5935 \brief Generates the unique group name.
5936 \param thePrefix name prefix
5939 //================================================================================
5941 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5943 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5944 set<std::string> groupNames;
5946 // Get existing group names
5947 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5948 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5949 if (CORBA::is_nil(aGroup))
5952 CORBA::String_var name = aGroup->GetName();
5953 groupNames.insert( name.in() );
5957 std::string name = thePrefix;
5960 while (!groupNames.insert(name).second)
5961 name = SMESH_Comment( thePrefix ) << "_" << index++;
5966 //================================================================================
5968 * \brief Prepare SMESH_IDSource for work
5970 //================================================================================
5972 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5974 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5976 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5977 filter->SetMesh( mesh );
5980 //================================================================================
5982 * \brief Retrieve elements of given type from SMESH_IDSource
5984 //================================================================================
5986 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5987 const SMESHDS_Mesh* theMeshDS,
5988 TIDSortedElemSet& theElemSet,
5989 const SMDSAbs_ElementType theType,
5990 const bool emptyIfIsMesh,
5991 IDSource_Error* error)
5994 if ( error ) *error = IDSource_OK;
5996 if ( CORBA::is_nil( theIDSource ))
5998 if ( error ) *error = IDSource_INVALID;
6001 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
6003 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
6004 *error = IDSource_EMPTY;
6007 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
6009 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
6010 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
6011 if ( mesh_i && mesh_i != myMesh_i )
6014 *error = IDSource_INVALID;
6018 prepareIdSource( theIDSource );
6019 SMESH::smIdType_array_var anIDs = theIDSource->GetIDs();
6020 if ( anIDs->length() == 0 )
6022 if ( error ) *error = IDSource_EMPTY;
6025 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
6026 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
6028 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
6030 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
6034 if ( error ) *error = IDSource_INVALID;
6040 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
6041 if ( bool(anIDs->length()) != bool(theElemSet.size()))
6043 if ( error ) *error = IDSource_INVALID;
6050 //================================================================================
6052 * \brief Duplicates given elements, i.e. creates new elements based on the
6053 * same nodes as the given ones.
6054 * \param theElements - container of elements to duplicate.
6055 * \param theGroupName - a name of group to contain the generated elements.
6056 * If a group with such a name already exists, the new elements
6057 * are added to the existing group, else a new group is created.
6058 * If \a theGroupName is empty, new elements are not added
6060 * \return a group where the new elements are added. NULL if theGroupName == "".
6063 //================================================================================
6065 SMESH::SMESH_Group_ptr
6066 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
6067 const char* theGroupName)
6069 SMESH::SMESH_Group_var newGroup;
6076 TIDSortedElemSet elems;
6077 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
6079 getEditor().DoubleElements( elems );
6081 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
6084 SMESH::ElementType type =
6085 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
6086 // find existing group
6087 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
6088 for ( size_t i = 0; i < groups->length(); ++i )
6089 if ( groups[i]->GetType() == type )
6091 CORBA::String_var name = groups[i]->GetName();
6092 if ( strcmp( name, theGroupName ) == 0 ) {
6093 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
6097 // create a new group
6098 if ( newGroup->_is_nil() )
6099 newGroup = myMesh_i->CreateGroup( type, theGroupName );
6101 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
6103 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
6104 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
6105 for ( size_t i = 0; i < aSeq.size(); i++ )
6106 groupDS->SMDSGroup().Add( aSeq[i] );
6111 if ( !newGroup->_is_nil() )
6112 pyDump << newGroup << " = ";
6113 pyDump << this << ".DoubleElements( "
6114 << theElements << ", " << "'" << theGroupName <<"')";
6116 SMESH_CATCH( SMESH::throwCorbaException );
6118 return newGroup._retn();
6121 //================================================================================
6123 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6124 \param theNodes - identifiers of nodes to be doubled
6125 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
6126 nodes. If list of element identifiers is empty then nodes are doubled but
6127 they not assigned to elements
6128 \return TRUE if operation has been completed successfully, FALSE otherwise
6129 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6131 //================================================================================
6133 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::smIdType_array& theNodes,
6134 const SMESH::smIdType_array& theModifiedElems )
6139 list< int > aListOfNodes;
6141 for ( i = 0, n = theNodes.length(); i < n; i++ )
6142 aListOfNodes.push_back( theNodes[ i ] );
6144 list< int > aListOfElems;
6145 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6146 aListOfElems.push_back( theModifiedElems[ i ] );
6148 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6150 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6152 // Update Python script
6153 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6157 SMESH_CATCH( SMESH::throwCorbaException );
6161 //================================================================================
6163 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6164 This method provided for convenience works as DoubleNodes() described above.
6165 \param theNodeId - identifier of node to be doubled.
6166 \param theModifiedElems - identifiers of elements to be updated.
6167 \return TRUE if operation has been completed successfully, FALSE otherwise
6168 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6170 //================================================================================
6172 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( SMESH::smIdType theNodeId,
6173 const SMESH::smIdType_array& theModifiedElems )
6176 SMESH::smIdType_array_var aNodes = new SMESH::smIdType_array;
6177 aNodes->length( 1 );
6178 aNodes[ 0 ] = theNodeId;
6180 TPythonDump pyDump; // suppress dump by the next line
6182 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6184 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6188 SMESH_CATCH( SMESH::throwCorbaException );
6192 //================================================================================
6194 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6195 This method provided for convenience works as DoubleNodes() described above.
6196 \param theNodes - group of nodes to be doubled.
6197 \param theModifiedElems - group of elements to be updated.
6198 \return TRUE if operation has been completed successfully, FALSE otherwise
6199 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6201 //================================================================================
6203 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6204 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6207 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6210 SMESH::smIdType_array_var aNodes = theNodes->GetListOfID();
6211 SMESH::smIdType_array_var aModifiedElems;
6212 if ( !CORBA::is_nil( theModifiedElems ) )
6213 aModifiedElems = theModifiedElems->GetListOfID();
6215 aModifiedElems = new SMESH::smIdType_array;
6217 TPythonDump pyDump; // suppress dump by the next line
6219 bool done = DoubleNodes( aNodes, aModifiedElems );
6221 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6225 SMESH_CATCH( SMESH::throwCorbaException );
6229 //================================================================================
6231 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6232 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6233 * \param theNodes - group of nodes to be doubled.
6234 * \param theModifiedElems - group of elements to be updated.
6235 * \return a new group with newly created nodes
6236 * \sa DoubleNodeGroup()
6238 //================================================================================
6240 SMESH::SMESH_Group_ptr
6241 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6242 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6245 SMESH::SMESH_Group_var aNewGroup;
6247 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6248 return aNewGroup._retn();
6251 SMESH::smIdType_array_var aNodes = theNodes->GetListOfID();
6252 SMESH::smIdType_array_var aModifiedElems;
6253 if ( !CORBA::is_nil( theModifiedElems ) )
6254 aModifiedElems = theModifiedElems->GetListOfID();
6256 aModifiedElems = new SMESH::smIdType_array;
6257 aModifiedElems->length( 0 );
6260 TPythonDump pyDump; // suppress dump by the next line
6262 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6265 // Create group with newly created nodes
6266 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6267 if (anIds->length() > 0) {
6268 std::string anUnindexedName (theNodes->GetName());
6269 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6270 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6271 aNewGroup->Add(anIds);
6272 pyDump << aNewGroup << " = ";
6276 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6277 << theModifiedElems << " )";
6279 return aNewGroup._retn();
6281 SMESH_CATCH( SMESH::throwCorbaException );
6285 //================================================================================
6287 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6288 This method provided for convenience works as DoubleNodes() described above.
6289 \param theNodes - list of groups of nodes to be doubled
6290 \param theModifiedElems - list of groups of elements to be updated.
6291 \return TRUE if operation has been completed successfully, FALSE otherwise
6292 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6294 //================================================================================
6296 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6297 const SMESH::ListOfGroups& theModifiedElems )
6302 std::list< int > aNodes;
6303 smIdType i, n, j, m;
6304 for ( i = 0, n = theNodes.length(); i < n; i++ )
6306 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6307 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6309 SMESH::smIdType_array_var aCurr = aGrp->GetListOfID();
6310 for ( j = 0, m = aCurr->length(); j < m; j++ )
6311 aNodes.push_back( aCurr[ j ] );
6315 std::list< int > anElems;
6316 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6318 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6319 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6321 SMESH::smIdType_array_var aCurr = aGrp->GetListOfID();
6322 for ( j = 0, m = aCurr->length(); j < m; j++ )
6323 anElems.push_back( aCurr[ j ] );
6327 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6329 declareMeshModified( /*isReComputeSafe=*/false );
6331 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6335 SMESH_CATCH( SMESH::throwCorbaException );
6339 //================================================================================
6341 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6342 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6343 * \param theNodes - group of nodes to be doubled.
6344 * \param theModifiedElems - group of elements to be updated.
6345 * \return a new group with newly created nodes
6346 * \sa DoubleNodeGroups()
6348 //================================================================================
6350 SMESH::SMESH_Group_ptr
6351 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6352 const SMESH::ListOfGroups& theModifiedElems )
6354 SMESH::SMESH_Group_var aNewGroup;
6356 TPythonDump pyDump; // suppress dump by the next line
6358 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6362 // Create group with newly created nodes
6363 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6364 if (anIds->length() > 0) {
6365 std::string anUnindexedName (theNodes[0]->GetName());
6366 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6367 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6368 aNewGroup->Add(anIds);
6369 pyDump << aNewGroup << " = ";
6373 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6374 << theModifiedElems << " )";
6376 return aNewGroup._retn();
6380 //================================================================================
6382 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6383 \param theElems - the list of elements (edges or faces) to be replicated
6384 The nodes for duplication could be found from these elements
6385 \param theNodesNot - list of nodes to NOT replicate
6386 \param theAffectedElems - the list of elements (cells and edges) to which the
6387 replicated nodes should be associated to.
6388 \return TRUE if operation has been completed successfully, FALSE otherwise
6389 \sa DoubleNodeGroup(), DoubleNodeGroups()
6391 //================================================================================
6393 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::smIdType_array& theElems,
6394 const SMESH::smIdType_array& theNodesNot,
6395 const SMESH::smIdType_array& theAffectedElems )
6400 SMESHDS_Mesh* aMeshDS = getMeshDS();
6401 TIDSortedElemSet anElems, aNodes, anAffected;
6402 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6403 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6404 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6406 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6408 // Update Python script
6409 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6410 << theNodesNot << ", " << theAffectedElems << " )";
6412 declareMeshModified( /*isReComputeSafe=*/false );
6415 SMESH_CATCH( SMESH::throwCorbaException );
6419 //================================================================================
6421 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6422 \param theElems - the list of elements (edges or faces) to be replicated
6423 The nodes for duplication could be found from these elements
6424 \param theNodesNot - list of nodes to NOT replicate
6425 \param theShape - shape to detect affected elements (element which geometric center
6426 located on or inside shape).
6427 The replicated nodes should be associated to affected elements.
6428 \return TRUE if operation has been completed successfully, FALSE otherwise
6429 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6431 //================================================================================
6433 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::smIdType_array& theElems,
6434 const SMESH::smIdType_array& theNodesNot,
6435 GEOM::GEOM_Object_ptr theShape )
6441 SMESHDS_Mesh* aMeshDS = getMeshDS();
6442 TIDSortedElemSet anElems, aNodes;
6443 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6444 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6446 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6447 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6449 // Update Python script
6450 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6451 << theNodesNot << ", " << theShape << " )";
6453 declareMeshModified( /*isReComputeSafe=*/false );
6456 SMESH_CATCH( SMESH::throwCorbaException );
6460 //================================================================================
6462 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6463 \param theElems - group of of elements (edges or faces) to be replicated
6464 \param theNodesNot - group of nodes not to replicated
6465 \param theAffectedElems - group of elements to which the replicated nodes
6466 should be associated to.
6467 \return TRUE if operation has been completed successfully, FALSE otherwise
6468 \sa DoubleNodes(), DoubleNodeGroups()
6470 //================================================================================
6473 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6474 SMESH::SMESH_GroupBase_ptr theNodesNot,
6475 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6478 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6484 SMESHDS_Mesh* aMeshDS = getMeshDS();
6485 TIDSortedElemSet anElems, aNodes, anAffected;
6486 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6487 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6488 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6490 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6492 // Update Python script
6493 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6494 << theNodesNot << ", " << theAffectedElems << " )";
6496 declareMeshModified( /*isReComputeSafe=*/false );
6499 SMESH_CATCH( SMESH::throwCorbaException );
6503 //================================================================================
6505 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6506 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6507 * \param theElems - group of of elements (edges or faces) to be replicated
6508 * \param theNodesNot - group of nodes not to replicated
6509 * \param theAffectedElems - group of elements to which the replicated nodes
6510 * should be associated to.
6511 * \return a new group with newly created elements
6512 * \sa DoubleNodeElemGroup()
6514 //================================================================================
6516 SMESH::SMESH_Group_ptr
6517 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6518 SMESH::SMESH_GroupBase_ptr theNodesNot,
6519 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6522 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6526 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6527 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6529 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6531 << theNodesNot << ", "
6532 << theAffectedElems << " )";
6534 return elemGroup._retn();
6537 //================================================================================
6539 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6540 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6541 * \param theElems - group of of elements (edges or faces) to be replicated
6542 * \param theNodesNot - group of nodes not to replicated
6543 * \param theAffectedElems - group of elements to which the replicated nodes
6544 * should be associated to.
6545 * \return a new group with newly created elements
6546 * \sa DoubleNodeElemGroup()
6548 //================================================================================
6550 SMESH::ListOfGroups*
6551 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6552 SMESH::SMESH_GroupBase_ptr theNodesNot,
6553 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6554 CORBA::Boolean theElemGroupNeeded,
6555 CORBA::Boolean theNodeGroupNeeded)
6558 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6559 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6560 aTwoGroups->length( 2 );
6562 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6563 return aTwoGroups._retn();
6568 SMESHDS_Mesh* aMeshDS = getMeshDS();
6569 TIDSortedElemSet anElems, aNodes, anAffected;
6570 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6571 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6572 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6575 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6577 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6583 // Create group with newly created elements
6584 CORBA::String_var elemGroupName = theElems->GetName();
6585 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6586 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6588 SMESH::smIdType_array_var anIds = GetLastCreatedElems();
6589 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6590 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6591 aNewElemGroup->Add(anIds);
6593 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6595 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6596 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6597 aNewNodeGroup->Add(anIds);
6601 // Update Python script
6604 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6605 else pyDump << aNewElemGroup << ", ";
6606 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6607 else pyDump << aNewNodeGroup << " ] = ";
6609 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6610 << theNodesNot << ", "
6611 << theAffectedElems << ", "
6612 << theElemGroupNeeded << ", "
6613 << theNodeGroupNeeded <<" )";
6615 aTwoGroups[0] = aNewElemGroup._retn();
6616 aTwoGroups[1] = aNewNodeGroup._retn();
6617 return aTwoGroups._retn();
6619 SMESH_CATCH( SMESH::throwCorbaException );
6623 //================================================================================
6625 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6626 \param theElems - group of of elements (edges or faces) to be replicated
6627 \param theNodesNot - group of nodes not to replicated
6628 \param theShape - shape to detect affected elements (element which geometric center
6629 located on or inside shape).
6630 The replicated nodes should be associated to affected elements.
6631 \return TRUE if operation has been completed successfully, FALSE otherwise
6632 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6634 //================================================================================
6637 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6638 SMESH::SMESH_GroupBase_ptr theNodesNot,
6639 GEOM::GEOM_Object_ptr theShape )
6642 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6648 SMESHDS_Mesh* aMeshDS = getMeshDS();
6649 TIDSortedElemSet anElems, aNodes, anAffected;
6650 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6651 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6653 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6654 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6657 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6659 // Update Python script
6660 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6661 << theNodesNot << ", " << theShape << " )";
6664 SMESH_CATCH( SMESH::throwCorbaException );
6668 //================================================================================
6670 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6671 * \param [in] theGrpList - groups
6672 * \param [in] theMeshDS - mesh
6673 * \param [out] theElemSet - set of elements
6674 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6676 //================================================================================
6678 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6679 SMESHDS_Mesh* theMeshDS,
6680 TIDSortedElemSet& theElemSet,
6681 const bool theIsNodeGrp)
6683 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6685 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6686 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6687 : aGrp->GetType() != SMESH::NODE ) )
6689 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6690 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6695 //================================================================================
6697 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6698 This method provided for convenience works as DoubleNodes() described above.
6699 \param theElems - list of groups of elements (edges or faces) to be replicated
6700 \param theNodesNot - list of groups of nodes not to replicated
6701 \param theAffectedElems - group of elements to which the replicated nodes
6702 should be associated to.
6703 \return TRUE if operation has been completed successfully, FALSE otherwise
6704 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6706 //================================================================================
6709 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6710 const SMESH::ListOfGroups& theNodesNot,
6711 const SMESH::ListOfGroups& theAffectedElems)
6717 SMESHDS_Mesh* aMeshDS = getMeshDS();
6718 TIDSortedElemSet anElems, aNodes, anAffected;
6719 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6720 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6721 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6723 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6725 // Update Python script
6726 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6727 << &theNodesNot << ", " << &theAffectedElems << " )";
6729 declareMeshModified( /*isReComputeSafe=*/false );
6732 SMESH_CATCH( SMESH::throwCorbaException );
6736 //================================================================================
6738 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6739 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6740 \param theElems - list of groups of elements (edges or faces) to be replicated
6741 \param theNodesNot - list of groups of nodes not to replicated
6742 \param theAffectedElems - group of elements to which the replicated nodes
6743 should be associated to.
6744 * \return a new group with newly created elements
6745 * \sa DoubleNodeElemGroups()
6747 //================================================================================
6749 SMESH::SMESH_Group_ptr
6750 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6751 const SMESH::ListOfGroups& theNodesNot,
6752 const SMESH::ListOfGroups& theAffectedElems)
6755 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6759 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6760 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6762 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6764 << theNodesNot << ", "
6765 << theAffectedElems << " )";
6767 return elemGroup._retn();
6770 //================================================================================
6772 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6773 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6774 \param theElems - list of groups of elements (edges or faces) to be replicated
6775 \param theNodesNot - list of groups of nodes not to replicated
6776 \param theAffectedElems - group of elements to which the replicated nodes
6777 should be associated to.
6778 * \return a new group with newly created elements
6779 * \sa DoubleNodeElemGroups()
6781 //================================================================================
6783 SMESH::ListOfGroups*
6784 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6785 const SMESH::ListOfGroups& theNodesNot,
6786 const SMESH::ListOfGroups& theAffectedElems,
6787 CORBA::Boolean theElemGroupNeeded,
6788 CORBA::Boolean theNodeGroupNeeded)
6791 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6792 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6793 aTwoGroups->length( 2 );
6798 SMESHDS_Mesh* aMeshDS = getMeshDS();
6799 TIDSortedElemSet anElems, aNodes, anAffected;
6800 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6801 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6802 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6804 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6806 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6811 // Create group with newly created elements
6812 CORBA::String_var elemGroupName = theElems[0]->GetName();
6813 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6814 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6816 SMESH::smIdType_array_var anIds = GetLastCreatedElems();
6817 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6818 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6819 aNewElemGroup->Add(anIds);
6821 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6823 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6824 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6825 aNewNodeGroup->Add(anIds);
6829 // Update Python script
6832 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6833 else pyDump << aNewElemGroup << ", ";
6834 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6835 else pyDump << aNewNodeGroup << " ] = ";
6837 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6838 << &theNodesNot << ", "
6839 << &theAffectedElems << ", "
6840 << theElemGroupNeeded << ", "
6841 << theNodeGroupNeeded << " )";
6843 aTwoGroups[0] = aNewElemGroup._retn();
6844 aTwoGroups[1] = aNewNodeGroup._retn();
6845 return aTwoGroups._retn();
6847 SMESH_CATCH( SMESH::throwCorbaException );
6851 //================================================================================
6853 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6854 This method provided for convenience works as DoubleNodes() described above.
6855 \param theElems - list of groups of elements (edges or faces) to be replicated
6856 \param theNodesNot - list of groups of nodes not to replicated
6857 \param theShape - shape to detect affected elements (element which geometric center
6858 located on or inside shape).
6859 The replicated nodes should be associated to affected elements.
6860 \return TRUE if operation has been completed successfully, FALSE otherwise
6861 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6863 //================================================================================
6866 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6867 const SMESH::ListOfGroups& theNodesNot,
6868 GEOM::GEOM_Object_ptr theShape )
6874 SMESHDS_Mesh* aMeshDS = getMeshDS();
6875 TIDSortedElemSet anElems, aNodes;
6876 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6877 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6879 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6880 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6882 // Update Python script
6883 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6884 << &theNodesNot << ", " << theShape << " )";
6886 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6889 SMESH_CATCH( SMESH::throwCorbaException );
6893 //================================================================================
6895 \brief Identify the elements that will be affected by node duplication (actual
6896 duplication is not performed.
6897 This method is the first step of DoubleNodeElemGroupsInRegion.
6898 \param theElems - list of groups of elements (edges or faces) to be replicated
6899 \param theNodesNot - list of groups of nodes not to replicate
6900 \param theShape - shape to detect affected elements (element which geometric center
6901 located on or inside shape).
6902 The replicated nodes should be associated to affected elements.
6903 \return groups of affected elements
6904 \sa DoubleNodeElemGroupsInRegion()
6906 //================================================================================
6907 SMESH::ListOfGroups*
6908 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6909 const SMESH::ListOfGroups& theNodesNot,
6910 GEOM::GEOM_Object_ptr theShape )
6913 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6914 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6915 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6916 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6920 ::SMESH_MeshEditor aMeshEditor(myMesh);
6922 SMESHDS_Mesh* aMeshDS = getMeshDS();
6923 TIDSortedElemSet anElems, aNodes;
6924 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6925 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6926 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6928 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6929 TIDSortedElemSet anAffected;
6930 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6932 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6935 if ( aResult && anAffected.size() > 0 )
6937 SMESH::smIdType_array_var volumeIds = new SMESH::smIdType_array;
6938 SMESH::smIdType_array_var faceIds = new SMESH::smIdType_array;
6939 SMESH::smIdType_array_var edgeIds = new SMESH::smIdType_array;
6940 volumeIds->length( anAffected.size() );
6941 faceIds ->length( anAffected.size() );
6942 edgeIds ->length( anAffected.size() );
6947 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6948 for (; eIt != anAffected.end(); ++eIt)
6950 const SMDS_MeshElement* anElem = *eIt;
6951 smIdType elemId = anElem->GetID();
6952 switch ( anElem->GetType() ) {
6953 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6954 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6955 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6959 volumeIds->length(ivol);
6960 faceIds->length(iface);
6961 edgeIds->length(iedge);
6966 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6967 GenerateGroupName("affectedVolumes").c_str());
6968 aNewVolumeGroup->Add(volumeIds);
6969 aListOfGroups->length( nbGroups+1 );
6970 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6974 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6975 GenerateGroupName("affectedFaces").c_str());
6976 aNewFaceGroup->Add(faceIds);
6977 aListOfGroups->length( nbGroups+1 );
6978 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6982 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6983 GenerateGroupName("affectedEdges").c_str());
6984 aNewEdgeGroup->Add(edgeIds);
6985 aListOfGroups->length( nbGroups+1 );
6986 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6990 // Update Python script
6992 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6993 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6995 return aListOfGroups._retn();
6997 SMESH_CATCH( SMESH::throwCorbaException );
7001 //================================================================================
7003 \brief Generated skin mesh (containing 2D cells) from 3D mesh
7004 The created 2D mesh elements based on nodes of free faces of boundary volumes
7005 \return TRUE if operation has been completed successfully, FALSE otherwise
7007 //================================================================================
7009 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
7014 bool aResult = getEditor().Make2DMeshFrom3D();
7016 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
7018 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7021 SMESH_CATCH( SMESH::throwCorbaException );
7025 //================================================================================
7027 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
7028 * The list of groups must contain at least two groups. The groups have to be disjoint:
7029 * no common element into two different groups.
7030 * The nodes of the internal faces at the boundaries of the groups are doubled.
7031 * Optionally, the internal faces are replaced by flat elements.
7032 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
7033 * The flat elements are stored in groups of volumes.
7034 * These groups are named according to the position of the group in the list:
7035 * 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.
7036 * 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.
7037 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
7038 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
7039 * \param theDomains - list of groups of volumes
7040 * \param createJointElems - if TRUE, create the elements
7041 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
7042 * the boundary between \a theDomains and the rest mesh
7043 * \return TRUE if operation has been completed successfully, FALSE otherwise
7045 //================================================================================
7048 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
7049 CORBA::Boolean createJointElems,
7050 CORBA::Boolean onAllBoundaries )
7057 SMESHDS_Mesh* aMeshDS = getMeshDS();
7059 // MESSAGE("theDomains.length = "<<theDomains.length());
7060 if ( theDomains.length() <= 1 && !onAllBoundaries )
7061 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
7063 vector<TIDSortedElemSet> domains;
7064 domains.resize( theDomains.length() );
7066 for ( int i = 0, n = theDomains.length(); i < n; i++ )
7068 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
7069 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
7071 // if ( aGrp->GetType() != SMESH::VOLUME )
7072 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
7073 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
7074 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
7078 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
7079 // TODO publish the groups of flat elements in study
7081 declareMeshModified( /*isReComputeSafe=*/ !isOK );
7083 // Update Python script
7084 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
7085 << ", " << createJointElems << ", " << onAllBoundaries << " )";
7087 SMESH_CATCH( SMESH::throwCorbaException );
7089 myMesh_i->CreateGroupServants(); // publish created groups if any
7094 //================================================================================
7096 * \brief Double nodes on some external faces and create flat elements.
7097 * Flat elements are mainly used by some types of mechanic calculations.
7099 * Each group of the list must be constituted of faces.
7100 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
7101 * @param theGroupsOfFaces - list of groups of faces
7102 * @return TRUE if operation has been completed successfully, FALSE otherwise
7104 //================================================================================
7107 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
7112 SMESHDS_Mesh* aMeshDS = getMeshDS();
7114 vector<TIDSortedElemSet> faceGroups;
7117 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7119 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7120 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7122 TIDSortedElemSet faceGroup;
7124 faceGroups.push_back(faceGroup);
7125 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
7126 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7130 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7131 // TODO publish the groups of flat elements in study
7133 declareMeshModified( /*isReComputeSafe=*/ !aResult );
7135 // Update Python script
7136 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7139 SMESH_CATCH( SMESH::throwCorbaException );
7143 //================================================================================
7145 * \brief Identify all the elements around a geom shape, get the faces delimiting
7148 * Build groups of volume to remove, groups of faces to replace on the skin of the
7149 * object, groups of faces to remove inside the object, (idem edges).
7150 * Build ordered list of nodes at the border of each group of faces to replace
7151 * (to be used to build a geom subshape).
7153 //================================================================================
7155 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
7156 GEOM::GEOM_Object_ptr theShape,
7157 const char* groupName,
7158 const SMESH::double_array& theNodesCoords,
7159 SMESH::array_of_long_array_out GroupsOfNodes)
7164 std::vector<std::vector<int> > aListOfListOfNodes;
7165 ::SMESH_MeshEditor aMeshEditor( myMesh );
7167 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7168 if ( !theNodeSearcher )
7169 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7171 vector<double> nodesCoords;
7172 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7174 nodesCoords.push_back( theNodesCoords[i] );
7177 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7178 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7179 nodesCoords, aListOfListOfNodes);
7181 GroupsOfNodes = new SMESH::array_of_long_array;
7182 GroupsOfNodes->length( aListOfListOfNodes.size() );
7183 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7184 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7186 vector<int>& aListOfNodes = *llIt;
7187 vector<int>::iterator lIt = aListOfNodes.begin();;
7188 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7189 aGroup.length( aListOfNodes.size() );
7190 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7191 aGroup[ j ] = (*lIt);
7193 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7196 << ", '" << groupName << "', "
7197 << theNodesCoords << " )";
7199 SMESH_CATCH( SMESH::throwCorbaException );
7202 // issue 20749 ===================================================================
7204 * \brief Creates missing boundary elements
7205 * \param elements - elements whose boundary is to be checked
7206 * \param dimension - defines type of boundary elements to create
7207 * \param groupName - a name of group to store created boundary elements in,
7208 * "" means not to create the group
7209 * \param meshName - a name of new mesh to store created boundary elements in,
7210 * "" means not to create the new mesh
7211 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7212 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7213 * boundary elements will be copied into the new mesh
7214 * \param group - returns the create group, if any
7215 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7217 // ================================================================================
7219 SMESH::SMESH_Mesh_ptr
7220 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7221 SMESH::Bnd_Dimension dim,
7222 const char* groupName,
7223 const char* meshName,
7224 CORBA::Boolean toCopyElements,
7225 CORBA::Boolean toCopyExistingBondary,
7226 SMESH::SMESH_Group_out group)
7231 if ( dim > SMESH::BND_1DFROM2D )
7232 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7234 SMESHDS_Mesh* aMeshDS = getMeshDS();
7236 SMESH::SMESH_Mesh_var mesh_var;
7237 SMESH::SMESH_Group_var group_var;
7241 TIDSortedElemSet elements;
7242 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7243 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7247 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7248 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7250 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7252 // group of new boundary elements
7253 SMESH_Group* smesh_group = 0;
7254 if ( strlen(groupName) )
7256 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7257 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7258 smesh_group = group_i->GetSmeshGroup();
7262 getEditor().MakeBoundaryMesh( elements,
7263 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7267 toCopyExistingBondary);
7270 smesh_mesh->GetMeshDS()->Modified();
7273 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7275 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7276 if ( mesh_var->_is_nil() )
7277 pyDump << myMesh_i->_this() << ", ";
7279 pyDump << mesh_var << ", ";
7280 if ( group_var->_is_nil() )
7281 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7283 pyDump << group_var << " = ";
7284 pyDump << this << ".MakeBoundaryMesh( "
7286 << "SMESH." << dimName[int(dim)] << ", "
7287 << "'" << groupName << "', "
7288 << "'" << meshName<< "', "
7289 << toCopyElements << ", "
7290 << toCopyExistingBondary << ")";
7292 group = group_var._retn();
7293 return mesh_var._retn();
7295 SMESH_CATCH( SMESH::throwCorbaException );
7296 return SMESH::SMESH_Mesh::_nil();
7299 //================================================================================
7301 * \brief Creates missing boundary elements
7302 * \param dimension - defines type of boundary elements to create
7303 * \param groupName - a name of group to store all boundary elements in,
7304 * "" means not to create the group
7305 * \param meshName - a name of a new mesh, which is a copy of the initial
7306 * mesh + created boundary elements; "" means not to create the new mesh
7307 * \param toCopyAll - if true, the whole initial mesh will be copied into
7308 * the new mesh else only boundary elements will be copied into the new mesh
7309 * \param groups - optional groups of elements to make boundary around
7310 * \param mesh - returns the mesh where elements were added to
7311 * \param group - returns the created group, if any
7312 * \retval long - number of added boundary elements
7314 //================================================================================
7316 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7317 const char* groupName,
7318 const char* meshName,
7319 CORBA::Boolean toCopyAll,
7320 const SMESH::ListOfIDSources& groups,
7321 SMESH::SMESH_Mesh_out mesh,
7322 SMESH::SMESH_Group_out group)
7327 if ( dim > SMESH::BND_1DFROM2D )
7328 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7330 // separate groups belonging to this and other mesh
7331 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7332 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7333 groupsOfThisMesh ->length( groups.length() );
7334 groupsOfOtherMesh->length( groups.length() );
7335 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7336 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7338 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7339 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7340 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7342 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7343 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7344 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7346 groupsOfThisMesh->length( nbGroups );
7347 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7352 if ( nbGroupsOfOtherMesh > 0 )
7354 // process groups belonging to another mesh
7355 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7356 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7357 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7358 groupsOfOtherMesh, mesh, group );
7361 SMESH::SMESH_Mesh_var mesh_var;
7362 SMESH::SMESH_Group_var group_var;
7365 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7366 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7370 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7372 /*toCopyGroups=*/false,
7373 /*toKeepIDs=*/true);
7375 mesh_var = makeMesh(meshName);
7377 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7378 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7381 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7382 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7384 // group of boundary elements
7385 SMESH_Group* smesh_group = 0;
7386 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7387 if ( strlen( groupName ))
7389 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7390 group_var = mesh_i->CreateGroup( groupType, groupName );
7391 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7392 smesh_group = group_i->GetSmeshGroup();
7395 TIDSortedElemSet elements;
7397 if ( groups.length() > 0 )
7399 for ( int i = 0; i < nbGroups; ++i )
7402 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7404 SMESH::Bnd_Dimension bdim =
7405 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7406 nbAdded += getEditor().MakeBoundaryMesh( elements,
7407 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7410 /*toCopyElements=*/false,
7411 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7412 /*toAddExistingBondary=*/true,
7413 /*aroundElements=*/true);
7419 nbAdded += getEditor().MakeBoundaryMesh( elements,
7420 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7423 /*toCopyElements=*/false,
7424 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7425 /*toAddExistingBondary=*/true);
7427 tgtMesh->GetMeshDS()->Modified();
7429 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7431 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7432 pyDump << "nbAdded, ";
7433 if ( mesh_var->_is_nil() )
7434 pyDump << myMesh_i->_this() << ", ";
7436 pyDump << mesh_var << ", ";
7437 if ( group_var->_is_nil() )
7438 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7440 pyDump << group_var << " = ";
7441 pyDump << this << ".MakeBoundaryElements( "
7442 << "SMESH." << dimName[int(dim)] << ", "
7443 << "'" << groupName << "', "
7444 << "'" << meshName<< "', "
7445 << toCopyAll << ", "
7448 mesh = mesh_var._retn();
7449 group = group_var._retn();
7452 SMESH_CATCH( SMESH::throwCorbaException );
7456 //================================================================================
7458 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7459 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7460 * plane passing through pairs of points specified by each PolySegment structure.
7461 * If there are several paths connecting a pair of points, the shortest path is
7462 * selected by the module. Position of the cutting plane is defined by the two
7463 * points and an optional vector lying on the plane specified by a PolySegment.
7464 * By default the vector is defined by Mesh module as following. A middle point
7465 * of the two given points is computed. The middle point is projected to the mesh.
7466 * The vector goes from the middle point to the projection point. In case of planar
7467 * mesh, the vector is normal to the mesh.
7468 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7469 * Return the used vector and position of the middle point.
7470 * \param [in] groupName - optional name of a group where created mesh segments will
7473 //================================================================================
7475 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7476 const char* theGroupName)
7478 if ( theSegments.length() == 0 )
7479 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7480 if ( myMesh->NbFaces() == 0 )
7481 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7484 initData(/*deleteSearchers=*/false);
7486 SMESHDS_Group* groupDS = 0;
7487 SMESHDS_Mesh* meshDS = getMeshDS();
7488 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7490 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7491 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7492 while ( faceIt->more() )
7493 tmpMesh->Copy( faceIt->next() );
7494 meshDS = tmpMesh->GetMeshDS();
7496 else if ( theGroupName[0] ) // find/create a group of segments
7498 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7499 // while ( !groupDS && grpIt->more() )
7501 // SMESH_Group* group = grpIt->next();
7502 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7503 // strcmp( group->GetName(), theGroupName ) == 0 )
7505 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7510 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7512 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7513 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7517 // convert input polySegments
7518 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7519 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7521 SMESH::PolySegment& segIn = theSegments[ i ];
7522 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7523 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7524 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7525 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7526 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7527 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7530 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7533 segOut.myVector.SetCoord( segIn.vector.PS.x,
7535 segIn.vector.PS.z );
7538 // get a static ElementSearcher
7539 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7540 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7541 if ( !theElementSearcher )
7542 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7545 std::vector<const SMDS_MeshElement*> newEdges;
7546 std::vector<const SMDS_MeshNode*> newNodes;
7547 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7548 groupDS ? &groupDS->SMDSGroup() : 0,
7549 theElementSearcher );
7551 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7553 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7554 assign( newNodes.begin(), newNodes.end() );
7557 if ( myIsPreviewMode )
7559 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7561 SMESH::PolySegment& segOut = theSegments[ i ];
7562 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7563 segOut.vector.PS.x = segIn.myVector.X();
7564 segOut.vector.PS.y = segIn.myVector.Y();
7565 segOut.vector.PS.z = segIn.myVector.Z();
7570 TPythonDump() << "_segments = []";
7571 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7573 SMESH::PolySegment& segIn = theSegments[ i ];
7574 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7575 << segIn.node1ID1 << ", "
7576 << segIn.node1ID2 << ", "
7577 << segIn.node2ID1 << ", "
7578 << segIn.node2ID2 << ", "
7579 << "smeshBuilder.MakeDirStruct( "
7580 << segIn.vector.PS.x << ", "
7581 << segIn.vector.PS.y << ", "
7582 << segIn.vector.PS.z << ")))";
7584 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7587 SMESH_CATCH( SMESH::throwCorbaException );
7591 //================================================================================
7593 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7594 * The slot is constructed by cutting faces by cylindrical surfaces made
7595 * around each segment. Segments are expected to be created by MakePolyLine().
7596 * \return Edges located at the slot boundary
7598 //================================================================================
7600 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7601 CORBA::Double theWidth)
7603 if ( CORBA::is_nil( theSegments ) ||
7604 theSegments->GetType() != SMESH::EDGE )
7605 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7606 if ( myMesh->NbFaces() == 0 )
7607 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7609 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7612 initData(/*deleteSearchers=*/false);
7614 SMESHDS_Mesh* meshDS = getMeshDS();
7616 // get standalone face groups to be updated
7617 std::vector< SMDS_MeshGroup* > faceGroups;
7618 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7619 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7620 for ( ; grIt != allGroups.end(); ++grIt )
7621 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7622 if ( gr->GetType() == SMDSAbs_Face )
7623 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7625 std::vector< SMESH_MeshAlgos::Edge > edges =
7626 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7627 theWidth, meshDS, faceGroups );
7629 resultEdges->length( edges.size() );
7630 for ( size_t i = 0; i < edges.size(); ++i )
7632 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7633 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7634 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7638 SMESH_CATCH( SMESH::throwCorbaException );
7640 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7642 return resultEdges._retn();