1 // Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _myMeshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< int > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( int i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) delete theNodeSearcher; theNodeSearcher = 0;
197 if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::long_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::long_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
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 int 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::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
621 SMESH::long_array_var myLastCreatedNodes = new SMESH::long_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::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 SMESH::long_array_var myLastCreatedElems = new SMESH::long_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::long_array _ids;
708 SMESH::ElementType _type;
709 SMESH::SMESH_Mesh_ptr _mesh;
710 SMESH::long_array* GetIDs() { return new SMESH::long_array( _ids ); }
711 SMESH::long_array* GetMeshInfo() { return 0; }
712 SMESH::long_array* GetNbElementsByType()
714 SMESH::long_array_var aRes = new SMESH::long_array();
715 aRes->length(SMESH::NB_ELEMENT_TYPES);
716 for (int 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::long_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 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
761 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
763 nbIds = (int) 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::long_array & IDsOfElements)
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::long_array & IDsOfNodes)
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 //=============================================================================
839 //=============================================================================
841 CORBA::Long 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< int > IdList( seq.begin(), seq.end() );
857 int nbNodesBefore = myMesh->NbNodes();
858 getEditor().Remove( IdList, true );
859 int nbNodesAfter = myMesh->NbNodes();
861 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
862 return nbNodesBefore - nbNodesAfter;
864 SMESH_CATCH( SMESH::throwCorbaException );
868 //=============================================================================
872 //=============================================================================
874 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
879 const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
881 // Update Python script
882 TPythonDump() << "nodeID = " << this << ".AddNode( "
883 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
885 declareMeshModified( /*isReComputeSafe=*/false );
888 SMESH_CATCH( SMESH::throwCorbaException );
892 //=============================================================================
894 * Create 0D element on the given node.
896 //=============================================================================
898 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode,
899 CORBA::Boolean DuplicateElements)
904 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
905 SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
907 SMDS_MeshElement* elem = 0;
908 if ( DuplicateElements || !it0D->more() )
909 elem = getMeshDS()->Add0DElement(aNode);
911 // Update Python script
912 TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
914 declareMeshModified( /*isReComputeSafe=*/false );
916 return elem ? elem->GetID() : 0;
918 SMESH_CATCH( SMESH::throwCorbaException );
922 //=============================================================================
924 * Create a ball element on the given node.
926 //=============================================================================
928 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
933 if ( diameter < std::numeric_limits<double>::min() )
934 THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
936 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
937 SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
939 // Update Python script
940 TPythonDump() << "ballElem = "
941 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
943 declareMeshModified( /*isReComputeSafe=*/false );
944 return elem ? elem->GetID() : 0;
946 SMESH_CATCH( SMESH::throwCorbaException );
950 //=============================================================================
952 * Create an edge, either linear and quadratic (this is determed
953 * by number of given nodes, two or three)
955 //=============================================================================
957 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
962 int NbNodes = IDsOfNodes.length();
963 SMDS_MeshElement* elem = 0;
966 CORBA::Long index1 = IDsOfNodes[0];
967 CORBA::Long index2 = IDsOfNodes[1];
968 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
969 getMeshDS()->FindNode(index2));
971 // Update Python script
972 TPythonDump() << "edge = " << this << ".AddEdge([ "
973 << index1 << ", " << index2 <<" ])";
976 CORBA::Long n1 = IDsOfNodes[0];
977 CORBA::Long n2 = IDsOfNodes[1];
978 CORBA::Long n12 = IDsOfNodes[2];
979 elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
980 getMeshDS()->FindNode(n2),
981 getMeshDS()->FindNode(n12));
982 // Update Python script
983 TPythonDump() << "edgeID = " << this << ".AddEdge([ "
984 <<n1<<", "<<n2<<", "<<n12<<" ])";
987 declareMeshModified( /*isReComputeSafe=*/false );
988 return elem ? elem->GetID() : 0;
990 SMESH_CATCH( SMESH::throwCorbaException );
994 //=============================================================================
998 //=============================================================================
1000 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1005 int NbNodes = IDsOfNodes.length();
1011 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1012 for (int i = 0; i < NbNodes; i++)
1013 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1015 SMDS_MeshElement* elem = 0;
1017 case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1018 case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1019 case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1020 nodes[4], nodes[5]); break;
1021 case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1022 nodes[4], nodes[5], nodes[6]); break;
1023 case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1024 nodes[4], nodes[5], nodes[6], nodes[7]); break;
1025 case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1026 nodes[4], nodes[5], nodes[6], nodes[7],
1028 default: elem = getMeshDS()->AddPolygonalFace(nodes);
1031 // Update Python script
1032 TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1034 declareMeshModified( /*isReComputeSafe=*/false );
1036 return elem ? elem->GetID() : 0;
1038 SMESH_CATCH( SMESH::throwCorbaException );
1042 //=============================================================================
1046 //=============================================================================
1048 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1053 int NbNodes = IDsOfNodes.length();
1054 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1055 for (int i = 0; i < NbNodes; i++)
1056 if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] )))
1061 INFOS("Polygon without nodes is forbidden");
1065 const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1067 // Update Python script
1068 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1070 declareMeshModified( /*isReComputeSafe=*/false );
1071 return elem ? elem->GetID() : 0;
1073 SMESH_CATCH( SMESH::throwCorbaException );
1077 //=============================================================================
1079 * AddQuadPolygonalFace
1081 //=============================================================================
1083 CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & IDsOfNodes)
1088 int NbNodes = IDsOfNodes.length();
1089 std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1090 for (int i = 0; i < NbNodes; i++)
1091 nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1095 INFOS("Polygon without nodes is forbidden");
1099 const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes);
1101 // Update Python script
1102 TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1104 declareMeshModified( /*isReComputeSafe=*/false );
1105 return elem ? elem->GetID() : 0;
1107 SMESH_CATCH( SMESH::throwCorbaException );
1111 //=============================================================================
1113 * Create volume, either linear and quadratic (this is determed
1114 * by number of given nodes)
1116 //=============================================================================
1118 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1123 int NbNodes = IDsOfNodes.length();
1124 vector< const SMDS_MeshNode*> n(NbNodes);
1125 for(int i=0;i<NbNodes;i++)
1126 n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1128 SMDS_MeshElement* elem = 0;
1131 case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1132 case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1133 case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1134 case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1135 case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1136 n[6],n[7],n[8],n[9]);
1138 case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1139 n[6],n[7],n[8],n[9],n[10],n[11]);
1141 case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1142 n[7],n[8],n[9],n[10],n[11],n[12]);
1144 case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1145 n[9],n[10],n[11],n[12],n[13],n[14]);
1147 case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1148 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1149 n[15],n[16],n[17],n[18],n[19]);
1151 case 18:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1152 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1155 case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1156 n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1157 n[15],n[16],n[17],n[18],n[19],
1158 n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1162 // Update Python script
1163 TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1165 declareMeshModified( /*isReComputeSafe=*/false );
1166 return elem ? elem->GetID() : 0;
1168 SMESH_CATCH( SMESH::throwCorbaException );
1172 //=============================================================================
1174 * AddPolyhedralVolume
1176 //=============================================================================
1177 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1178 const SMESH::long_array & Quantities)
1183 int NbNodes = IDsOfNodes.length();
1184 std::vector<const SMDS_MeshNode*> n (NbNodes);
1185 for (int i = 0; i < NbNodes; i++)
1187 const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1188 if (!aNode) return 0;
1192 int NbFaces = Quantities.length();
1193 std::vector<int> q (NbFaces);
1194 for (int j = 0; j < NbFaces; j++)
1195 q[j] = Quantities[j];
1197 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1199 // Update Python script
1200 TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1201 << IDsOfNodes << ", " << Quantities << " )";
1203 declareMeshModified( /*isReComputeSafe=*/false );
1204 return elem ? elem->GetID() : 0;
1206 SMESH_CATCH( SMESH::throwCorbaException );
1210 //=============================================================================
1212 * AddPolyhedralVolumeByFaces
1214 //=============================================================================
1216 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1221 int NbFaces = IdsOfFaces.length();
1222 std::vector<const SMDS_MeshNode*> poly_nodes;
1223 std::vector<int> quantities (NbFaces);
1225 for (int i = 0; i < NbFaces; i++) {
1226 const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1227 quantities[i] = aFace->NbNodes();
1229 SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1230 while (It->more()) {
1231 poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1235 const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1237 // Update Python script
1238 TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1239 << IdsOfFaces << " )";
1241 declareMeshModified( /*isReComputeSafe=*/false );
1242 return elem ? elem->GetID() : 0;
1244 SMESH_CATCH( SMESH::throwCorbaException );
1248 //=============================================================================
1250 // \brief Create 0D elements on all nodes of the given object.
1251 // \param theObject object on whose nodes 0D elements will be created.
1252 // \param theGroupName optional name of a group to add 0D elements created
1253 // and/or found on nodes of \a theObject.
1254 // \param DuplicateElements to add one more 0D element to a node or not.
1255 // \return an object (a new group or a temporary SMESH_IDSource) holding
1256 // ids of new and/or found 0D elements.
1258 //=============================================================================
1260 SMESH::SMESH_IDSource_ptr
1261 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1262 const char* theGroupName,
1263 CORBA::Boolean theDuplicateElements)
1268 SMESH::SMESH_IDSource_var result;
1271 TIDSortedElemSet elements, elems0D;
1272 if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1273 getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
1275 SMESH::long_array_var newElems = new SMESH::long_array;
1276 newElems->length( elems0D.size() );
1277 TIDSortedElemSet::iterator eIt = elems0D.begin();
1278 for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1279 newElems[ i ] = (*eIt)->GetID();
1281 SMESH::SMESH_GroupBase_var groupToFill;
1282 if ( theGroupName && strlen( theGroupName ))
1284 // Get existing group named theGroupName
1285 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1286 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1287 SMESH::SMESH_GroupBase_var group = groups[i];
1288 if ( !group->_is_nil() ) {
1289 CORBA::String_var name = group->GetName();
1290 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1291 groupToFill = group;
1296 if ( groupToFill->_is_nil() )
1297 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1298 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1299 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1302 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1304 group_i->Add( newElems );
1305 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1306 pyDump << groupToFill;
1310 result = MakeIDSource( newElems, SMESH::ELEM0D );
1311 pyDump << "elem0DIDs";
1314 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1315 << theObject << ", '" << theGroupName << "' )";
1317 return result._retn();
1319 SMESH_CATCH( SMESH::throwCorbaException );
1323 //=============================================================================
1325 * \brief Bind a node to a vertex
1326 * \param NodeID - node ID
1327 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1328 * \retval boolean - false if NodeID or VertexID is invalid
1330 //=============================================================================
1332 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1336 SMESHDS_Mesh * mesh = getMeshDS();
1337 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1339 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1341 if ( mesh->MaxShapeIndex() < VertexID )
1342 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1344 TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1345 if ( shape.ShapeType() != TopAbs_VERTEX )
1346 THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1348 mesh->SetNodeOnVertex( node, VertexID );
1350 myMesh->SetIsModified( true );
1352 SMESH_CATCH( SMESH::throwCorbaException );
1355 //=============================================================================
1357 * \brief Store node position on an edge
1358 * \param NodeID - node ID
1359 * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1360 * \param paramOnEdge - parameter on edge where the node is located
1361 * \retval boolean - false if any parameter is invalid
1363 //=============================================================================
1365 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1366 CORBA::Double paramOnEdge)
1370 SMESHDS_Mesh * mesh = getMeshDS();
1371 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1373 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1375 if ( mesh->MaxShapeIndex() < EdgeID )
1376 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1378 TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1379 if ( shape.ShapeType() != TopAbs_EDGE )
1380 THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1383 BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1384 if ( paramOnEdge < f || paramOnEdge > l )
1386 SMESH_Comment txt("Invalid paramOnEdge. It must vary in range [ ");
1387 txt << f << ", " << l << " ]";
1388 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1390 mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1392 myMesh->SetIsModified( true );
1394 SMESH_CATCH( SMESH::throwCorbaException );
1397 //=============================================================================
1399 * \brief Store node position on a face
1400 * \param NodeID - node ID
1401 * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1402 * \param u - U parameter on face where the node is located
1403 * \param v - V parameter on face where the node is located
1404 * \retval boolean - false if any parameter is invalid
1406 //=============================================================================
1408 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1409 CORBA::Double u, CORBA::Double v)
1412 SMESHDS_Mesh * mesh = getMeshDS();
1413 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1415 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1417 if ( mesh->MaxShapeIndex() < FaceID )
1418 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1420 TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1421 if ( shape.ShapeType() != TopAbs_FACE )
1422 THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1424 BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1425 bool isOut = ( u < surf.FirstUParameter() ||
1426 u > surf.LastUParameter() ||
1427 v < surf.FirstVParameter() ||
1428 v > surf.LastVParameter() );
1431 SMESH_Comment txt("Invalid UV. U must vary in range [ ");
1432 txt << surf.FirstUParameter() << ", " << surf.LastUParameter() << " ], ";
1433 txt << "V must vary in range [ ";
1434 txt << surf.FirstVParameter() << ", " << surf.LastVParameter() << " ]";
1435 THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
1438 mesh->SetNodeOnFace( node, FaceID, u, v );
1439 myMesh->SetIsModified( true );
1441 SMESH_CATCH( SMESH::throwCorbaException );
1444 //=============================================================================
1446 * \brief Bind a node to a solid
1447 * \param NodeID - node ID
1448 * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1449 * \retval boolean - false if NodeID or SolidID is invalid
1451 //=============================================================================
1453 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1456 SMESHDS_Mesh * mesh = getMeshDS();
1457 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1459 THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1461 if ( mesh->MaxShapeIndex() < SolidID )
1462 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1464 TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1465 if ( shape.ShapeType() != TopAbs_SOLID &&
1466 shape.ShapeType() != TopAbs_SHELL)
1467 THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1469 mesh->SetNodeInVolume( node, SolidID );
1471 SMESH_CATCH( SMESH::throwCorbaException );
1474 //=============================================================================
1476 * \brief Bind an element to a shape
1477 * \param ElementID - element ID
1478 * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1480 //=============================================================================
1482 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1483 CORBA::Long ShapeID)
1486 SMESHDS_Mesh * mesh = getMeshDS();
1487 SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1489 THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1491 if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1492 THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1494 TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1495 if ( shape.ShapeType() != TopAbs_EDGE &&
1496 shape.ShapeType() != TopAbs_FACE &&
1497 shape.ShapeType() != TopAbs_SOLID &&
1498 shape.ShapeType() != TopAbs_SHELL )
1499 THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1501 mesh->SetMeshElementOnShape( elem, ShapeID );
1503 myMesh->SetIsModified( true );
1505 SMESH_CATCH( SMESH::throwCorbaException );
1508 //=============================================================================
1512 //=============================================================================
1514 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1515 CORBA::Long NodeID2)
1520 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1521 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1525 // Update Python script
1526 TPythonDump() << "isDone = " << this << ".InverseDiag( "
1527 << NodeID1 << ", " << NodeID2 << " )";
1529 int ret = getEditor().InverseDiag ( n1, n2 );
1531 declareMeshModified( /*isReComputeSafe=*/false );
1534 SMESH_CATCH( SMESH::throwCorbaException );
1538 //=============================================================================
1542 //=============================================================================
1544 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1545 CORBA::Long NodeID2)
1550 const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1551 const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1555 // Update Python script
1556 TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1557 << NodeID1 << ", " << NodeID2 << " )";
1560 bool stat = getEditor().DeleteDiag ( n1, n2 );
1562 declareMeshModified( /*isReComputeSafe=*/!stat );
1566 SMESH_CATCH( SMESH::throwCorbaException );
1570 //=============================================================================
1574 //=============================================================================
1576 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1581 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
1583 CORBA::Long index = IDsOfElements[i];
1584 const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1586 getEditor().Reorient( elem );
1588 // Update Python script
1589 TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1591 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1594 SMESH_CATCH( SMESH::throwCorbaException );
1598 //=============================================================================
1602 //=============================================================================
1604 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1609 TPythonDump aTPythonDump; // suppress dump in Reorient()
1611 prepareIdSource( theObject );
1613 SMESH::long_array_var anElementsId = theObject->GetIDs();
1614 CORBA::Boolean isDone = Reorient(anElementsId);
1616 // Update Python script
1617 aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1619 declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1622 SMESH_CATCH( SMESH::throwCorbaException );
1626 //=======================================================================
1627 //function : Reorient2D
1628 //purpose : Reorient faces contained in \a the2Dgroup.
1629 // the2Dgroup - the mesh or its part to reorient
1630 // theDirection - desired direction of normal of \a theFace
1631 // theFace - ID of face whose orientation is checked.
1632 // It can be < 1 then \a thePoint is used to find a face.
1633 // thePoint - is used to find a face if \a theFace < 1.
1634 // return number of reoriented elements.
1635 //=======================================================================
1637 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1638 const SMESH::DirStruct& theDirection,
1639 CORBA::Long theFace,
1640 const SMESH::PointStruct& thePoint)
1643 initData(/*deleteSearchers=*/false);
1645 TIDSortedElemSet elements;
1646 IDSource_Error error;
1647 idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1648 if ( error == IDSource_EMPTY )
1650 if ( error == IDSource_INVALID )
1651 THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1654 const SMDS_MeshElement* face = 0;
1657 face = getMeshDS()->FindElement( theFace );
1659 THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1660 if ( face->GetType() != SMDSAbs_Face )
1661 THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1665 // create theElementSearcher if needed
1666 theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1667 if ( !theElementSearcher )
1669 if ( elements.empty() ) // search in the whole mesh
1671 if ( myMesh->NbFaces() == 0 )
1672 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1674 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1678 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1679 SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1681 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1685 gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1686 face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1689 THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1690 if ( !elements.empty() && !elements.count( face ))
1691 THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1694 const SMESH::PointStruct * P = &theDirection.PS;
1695 gp_Vec dirVec( P->x, P->y, P->z );
1696 if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1697 THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1699 int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1702 declareMeshModified( /*isReComputeSafe=*/false );
1704 TPythonDump() << this << ".Reorient2D( "
1705 << the2Dgroup << ", "
1706 << theDirection << ", "
1708 << thePoint << " )";
1712 SMESH_CATCH( SMESH::throwCorbaException );
1716 //=======================================================================
1717 //function : Reorient2DBy3D
1718 //purpose : Reorient faces basing on orientation of adjacent volumes.
1719 //=======================================================================
1721 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1722 SMESH::SMESH_IDSource_ptr volumeGroup,
1723 CORBA::Boolean outsideNormal)
1728 TIDSortedElemSet volumes;
1729 IDSource_Error volsError;
1730 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1733 for ( size_t i = 0; i < faceGroups.length(); ++i )
1735 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1737 TIDSortedElemSet faces;
1738 IDSource_Error error;
1739 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1740 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1741 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1742 if ( error == IDSource_OK && volsError != IDSource_OK )
1743 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1745 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1747 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1752 declareMeshModified( /*isReComputeSafe=*/false );
1754 TPythonDump() << this << ".Reorient2DBy3D( "
1755 << faceGroups << ", "
1756 << volumeGroup << ", "
1757 << outsideNormal << " )";
1761 SMESH_CATCH( SMESH::throwCorbaException );
1765 //=============================================================================
1767 * \brief Fuse neighbour triangles into quadrangles.
1769 //=============================================================================
1771 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array & IDsOfElements,
1772 SMESH::NumericalFunctor_ptr Criterion,
1773 CORBA::Double MaxAngle)
1778 SMESHDS_Mesh* aMesh = getMeshDS();
1779 TIDSortedElemSet faces,copyFaces;
1780 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1781 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1782 TIDSortedElemSet* workElements = & faces;
1784 if ( myIsPreviewMode ) {
1785 SMDSAbs_ElementType select = SMDSAbs_Face;
1786 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1787 workElements = & copyFaces;
1790 SMESH::NumericalFunctor_i* aNumericalFunctor =
1791 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1792 SMESH::Controls::NumericalFunctorPtr aCrit;
1793 if ( !aNumericalFunctor )
1794 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1796 aCrit = aNumericalFunctor->GetNumericalFunctor();
1798 if ( !myIsPreviewMode ) {
1799 // Update Python script
1800 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1801 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1804 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1806 declareMeshModified( /*isReComputeSafe=*/!stat );
1809 SMESH_CATCH( SMESH::throwCorbaException );
1813 //=============================================================================
1815 * \brief Fuse neighbour triangles into quadrangles.
1817 //=============================================================================
1819 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1820 SMESH::NumericalFunctor_ptr Criterion,
1821 CORBA::Double MaxAngle)
1826 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1828 prepareIdSource( theObject );
1829 SMESH::long_array_var anElementsId = theObject->GetIDs();
1830 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1832 if ( !myIsPreviewMode ) {
1833 SMESH::NumericalFunctor_i* aNumericalFunctor =
1834 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1836 // Update Python script
1837 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1838 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1843 SMESH_CATCH( SMESH::throwCorbaException );
1847 //=============================================================================
1849 * \brief Split quadrangles into triangles.
1851 //=============================================================================
1853 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array & IDsOfElements,
1854 SMESH::NumericalFunctor_ptr Criterion)
1859 SMESHDS_Mesh* aMesh = getMeshDS();
1860 TIDSortedElemSet faces;
1861 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1863 SMESH::NumericalFunctor_i* aNumericalFunctor =
1864 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1865 SMESH::Controls::NumericalFunctorPtr aCrit;
1866 if ( !aNumericalFunctor )
1867 aCrit.reset( new SMESH::Controls::AspectRatio() );
1869 aCrit = aNumericalFunctor->GetNumericalFunctor();
1872 // Update Python script
1873 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1875 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1877 declareMeshModified( /*isReComputeSafe=*/false );
1880 SMESH_CATCH( SMESH::throwCorbaException );
1884 //=============================================================================
1886 * \brief Split quadrangles into triangles.
1888 //=============================================================================
1890 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1891 SMESH::NumericalFunctor_ptr Criterion)
1896 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1898 prepareIdSource( theObject );
1899 SMESH::long_array_var anElementsId = theObject->GetIDs();
1900 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1902 SMESH::NumericalFunctor_i* aNumericalFunctor =
1903 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1905 // Update Python script
1906 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1908 declareMeshModified( /*isReComputeSafe=*/false );
1911 SMESH_CATCH( SMESH::throwCorbaException );
1915 //================================================================================
1917 * \brief Split each of quadrangles into 4 triangles.
1918 * \param [in] theObject - theQuads Container of quadrangles to split.
1920 //================================================================================
1922 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1927 TIDSortedElemSet faces;
1928 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1930 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1932 getEditor().QuadTo4Tri( faces );
1933 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1935 SMESH_CATCH( SMESH::throwCorbaException );
1938 //=============================================================================
1940 * \brief Split quadrangles into triangles.
1942 //=============================================================================
1944 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1945 CORBA::Boolean Diag13)
1950 SMESHDS_Mesh* aMesh = getMeshDS();
1951 TIDSortedElemSet faces;
1952 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1954 // Update Python script
1955 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1956 << IDsOfElements << ", " << Diag13 << " )";
1958 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1960 declareMeshModified( /*isReComputeSafe=*/ !stat );
1963 SMESH_CATCH( SMESH::throwCorbaException );
1967 //=============================================================================
1969 * \brief Split quadrangles into triangles.
1971 //=============================================================================
1973 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1974 CORBA::Boolean Diag13)
1979 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1981 prepareIdSource( theObject );
1982 SMESH::long_array_var anElementsId = theObject->GetIDs();
1983 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1985 // Update Python script
1986 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1987 << theObject << ", " << Diag13 << " )";
1989 declareMeshModified( /*isReComputeSafe=*/!isDone );
1992 SMESH_CATCH( SMESH::throwCorbaException );
1997 //=============================================================================
1999 * Find better splitting of the given quadrangle.
2000 * \param IDOfQuad ID of the quadrangle to be split.
2001 * \param Criterion A criterion to choose a diagonal for splitting.
2002 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2003 * diagonal is better, 0 if error occurs.
2005 //=============================================================================
2007 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2008 SMESH::NumericalFunctor_ptr Criterion)
2013 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2014 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
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 = aNumericalFunctor->GetNumericalFunctor();
2022 aCrit.reset(new SMESH::Controls::AspectRatio());
2024 int id = getEditor().BestSplit(quad, aCrit);
2025 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2029 SMESH_CATCH( SMESH::throwCorbaException );
2033 //================================================================================
2035 * \brief Split volumic elements into tetrahedrons
2037 //================================================================================
2039 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2040 CORBA::Short methodFlags)
2045 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2046 const int noneFacet = -1;
2047 prepareIdSource( elems );
2048 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2049 while ( volIt->more() )
2050 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2052 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2053 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2055 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2056 << elems << ", " << methodFlags << " )";
2058 SMESH_CATCH( SMESH::throwCorbaException );
2061 //================================================================================
2063 * \brief Split hexahedra into triangular prisms
2064 * \param elems - elements to split
2065 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2066 * to split into triangles
2067 * \param methodFlags - flags passing splitting method:
2068 * 1 - split the hexahedron into 2 prisms
2069 * 2 - split the hexahedron into 4 prisms
2071 //================================================================================
2073 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2074 const SMESH::PointStruct & startHexPoint,
2075 const SMESH::DirStruct& facetToSplitNormal,
2076 CORBA::Short methodFlags,
2077 CORBA::Boolean allDomains)
2081 prepareIdSource( elems );
2083 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2086 gp_Dir( facetToSplitNormal.PS.x,
2087 facetToSplitNormal.PS.y,
2088 facetToSplitNormal.PS.z ));
2089 TIDSortedElemSet elemSet;
2090 prepareIdSource( elems );
2091 SMESH::long_array_var anElementsId = elems->GetIDs();
2092 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2093 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2095 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2096 while ( !elemSet.empty() )
2098 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2102 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2103 for ( ; ef != elemFacets.end(); ++ef )
2104 elemSet.erase( ef->first );
2107 if ( methodFlags == 2 )
2108 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2110 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2112 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2113 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2115 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2117 << startHexPoint << ", "
2118 << facetToSplitNormal<< ", "
2119 << methodFlags<< ", "
2120 << allDomains << " )";
2122 SMESH_CATCH( SMESH::throwCorbaException );
2125 //================================================================================
2127 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2128 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2129 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2130 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2131 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2132 * will be split in order to keep the mesh conformal.
2133 * \param elems - elements to split
2135 //================================================================================
2137 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2142 TIDSortedElemSet elemSet;
2143 for ( size_t i = 0; i < theElems.length(); ++i )
2145 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2146 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2147 if ( mesh->GetId() != myMesh_i->GetId() )
2148 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2150 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2152 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2154 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2156 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2157 << theElems << " )";
2159 SMESH_CATCH( SMESH::throwCorbaException );
2162 //=======================================================================
2165 //=======================================================================
2168 SMESH_MeshEditor_i::Smooth(const SMESH::long_array & IDsOfElements,
2169 const SMESH::long_array & IDsOfFixedNodes,
2170 CORBA::Long MaxNbOfIterations,
2171 CORBA::Double MaxAspectRatio,
2172 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2174 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2175 MaxAspectRatio, Method, false );
2179 //=======================================================================
2180 //function : SmoothParametric
2182 //=======================================================================
2185 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array & IDsOfElements,
2186 const SMESH::long_array & IDsOfFixedNodes,
2187 CORBA::Long MaxNbOfIterations,
2188 CORBA::Double MaxAspectRatio,
2189 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2191 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2192 MaxAspectRatio, Method, true );
2196 //=======================================================================
2197 //function : SmoothObject
2199 //=======================================================================
2202 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2203 const SMESH::long_array & IDsOfFixedNodes,
2204 CORBA::Long MaxNbOfIterations,
2205 CORBA::Double MaxAspectRatio,
2206 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2208 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2209 MaxAspectRatio, Method, false);
2213 //=======================================================================
2214 //function : SmoothParametricObject
2216 //=======================================================================
2219 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2220 const SMESH::long_array & IDsOfFixedNodes,
2221 CORBA::Long MaxNbOfIterations,
2222 CORBA::Double MaxAspectRatio,
2223 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2225 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2226 MaxAspectRatio, Method, true);
2230 //=============================================================================
2234 //=============================================================================
2237 SMESH_MeshEditor_i::smooth(const SMESH::long_array & IDsOfElements,
2238 const SMESH::long_array & IDsOfFixedNodes,
2239 CORBA::Long MaxNbOfIterations,
2240 CORBA::Double MaxAspectRatio,
2241 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2247 SMESHDS_Mesh* aMesh = getMeshDS();
2249 TIDSortedElemSet elements;
2250 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2252 set<const SMDS_MeshNode*> fixedNodes;
2253 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2254 CORBA::Long index = IDsOfFixedNodes[i];
2255 const SMDS_MeshNode * node = aMesh->FindNode(index);
2257 fixedNodes.insert( node );
2259 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2260 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2261 method = ::SMESH_MeshEditor::CENTROIDAL;
2263 getEditor().Smooth(elements, fixedNodes, method,
2264 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2266 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2268 // Update Python script
2269 TPythonDump() << "isDone = " << this << "."
2270 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2271 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2272 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2273 << "SMESH.SMESH_MeshEditor."
2274 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2275 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2279 SMESH_CATCH( SMESH::throwCorbaException );
2283 //=============================================================================
2287 //=============================================================================
2290 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2291 const SMESH::long_array & IDsOfFixedNodes,
2292 CORBA::Long MaxNbOfIterations,
2293 CORBA::Double MaxAspectRatio,
2294 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2300 TPythonDump aTPythonDump; // suppress dump in smooth()
2302 prepareIdSource( theObject );
2303 SMESH::long_array_var anElementsId = theObject->GetIDs();
2304 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2305 MaxAspectRatio, Method, IsParametric);
2307 // Update Python script
2308 aTPythonDump << "isDone = " << this << "."
2309 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2310 << theObject << ", " << IDsOfFixedNodes << ", "
2311 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2312 << "SMESH.SMESH_MeshEditor."
2313 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2314 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2318 SMESH_CATCH( SMESH::throwCorbaException );
2322 //=============================================================================
2326 //=============================================================================
2328 void SMESH_MeshEditor_i::RenumberNodes()
2331 // Update Python script
2332 TPythonDump() << this << ".RenumberNodes()";
2334 getMeshDS()->Renumber( true );
2336 SMESH_CATCH( SMESH::throwCorbaException );
2339 //=============================================================================
2343 //=============================================================================
2345 void SMESH_MeshEditor_i::RenumberElements()
2348 // Update Python script
2349 TPythonDump() << this << ".RenumberElements()";
2351 getMeshDS()->Renumber( false );
2353 SMESH_CATCH( SMESH::throwCorbaException );
2356 //=======================================================================
2358 * \brief Return groups by their IDs
2360 //=======================================================================
2362 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2367 myMesh_i->CreateGroupServants();
2368 return myMesh_i->GetGroups( *groupIDs );
2370 SMESH_CATCH( SMESH::throwCorbaException );
2374 //=======================================================================
2375 //function : RotationSweepObjects
2377 //=======================================================================
2379 SMESH::ListOfGroups*
2380 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2381 const SMESH::ListOfIDSources & theEdges,
2382 const SMESH::ListOfIDSources & theFaces,
2383 const SMESH::AxisStruct & theAxis,
2384 CORBA::Double theAngleInRadians,
2385 CORBA::Long theNbOfSteps,
2386 CORBA::Double theTolerance,
2387 const bool theMakeGroups)
2392 TIDSortedElemSet elemsNodes[2];
2393 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2394 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2395 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2397 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2398 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2399 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2400 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2402 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2403 bool makeWalls=true;
2404 if ( myIsPreviewMode )
2406 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2407 TPreviewMesh * tmpMesh = getPreviewMesh();
2408 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2409 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2410 workElements = & copyElements[0];
2411 //makeWalls = false; -- faces are needed for preview
2414 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2416 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2417 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2419 ::SMESH_MeshEditor::PGroupIDs groupIds =
2420 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2421 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2423 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2425 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2427 if ( !myIsPreviewMode )
2429 dumpGroupsList( aPythonDump, aGroups );
2430 aPythonDump << this<< ".RotationSweepObjects( "
2435 << TVar( theAngleInRadians ) << ", "
2436 << TVar( theNbOfSteps ) << ", "
2437 << TVar( theTolerance ) << ", "
2438 << theMakeGroups << " )";
2442 getPreviewMesh()->Remove( SMDSAbs_Volume );
2445 return aGroups ? aGroups : new SMESH::ListOfGroups;
2447 SMESH_CATCH( SMESH::throwCorbaException );
2451 namespace MeshEditor_I
2454 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2456 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2458 bool myIsExtrusionByNormal;
2460 static int makeFlags( CORBA::Boolean MakeGroups,
2461 CORBA::Boolean ScaleVariation = false,
2462 CORBA::Boolean AngleVariation = false,
2463 CORBA::Boolean ByAverageNormal = false,
2464 CORBA::Boolean UseInputElemsOnly = false,
2465 CORBA::Long Flags = 0,
2466 CORBA::Boolean MakeBoundary = true )
2468 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2469 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2470 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2471 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2472 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2473 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2477 ExtrusionParams(const SMESH::DirStruct & theDir,
2478 CORBA::Long theNbOfSteps,
2479 const SMESH::double_array & theScaleFactors,
2480 CORBA::Boolean theScaleVariation,
2481 const SMESH::double_array & theAngles,
2482 CORBA::Boolean theAngleVariation,
2483 const SMESH::double_array & theBasePoint,
2484 CORBA::Boolean theMakeGroups):
2485 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2489 toList( theScaleFactors ),
2490 toList( theAngles ),
2491 TBasePoint( theBasePoint ),
2492 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2493 myIsExtrusionByNormal( false )
2497 ExtrusionParams(const SMESH::DirStruct & theDir,
2498 CORBA::Long theNbOfSteps,
2499 CORBA::Boolean theMakeGroups,
2500 CORBA::Long theExtrFlags,
2501 CORBA::Double theSewTolerance):
2502 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2506 std::list<double>(),
2507 std::list<double>(),
2509 makeFlags( theMakeGroups, false, false, false, false,
2510 theExtrFlags, false ),
2512 myIsExtrusionByNormal( false )
2515 // params for extrusion by normal
2516 ExtrusionParams(CORBA::Double theStepSize,
2517 CORBA::Long theNbOfSteps,
2518 CORBA::Short theDim,
2519 CORBA::Boolean theByAverageNormal,
2520 CORBA::Boolean theUseInputElemsOnly,
2521 CORBA::Boolean theMakeGroups ):
2522 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2524 makeFlags( theMakeGroups, false, false,
2525 theByAverageNormal, theUseInputElemsOnly ),
2527 myIsExtrusionByNormal( true )
2533 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2536 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2538 std::list<double> scales;
2539 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2540 scales.push_back( theScaleFactors[i] );
2546 // structure used to convert SMESH::double_array to gp_XYZ*
2550 TBasePoint( const SMESH::double_array & theBasePoint )
2553 if ( theBasePoint.length() == 3 )
2555 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2559 operator const gp_XYZ*() const { return pp; }
2564 //=======================================================================
2566 * \brief Generate dim+1 elements by extrusion of elements along vector
2567 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2568 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2569 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2570 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2571 * \param [in] nbOfSteps - number of elements to generate from one element
2572 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2573 * corresponding to groups the input elements included in.
2574 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2576 //=======================================================================
2578 SMESH::ListOfGroups*
2579 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2580 const SMESH::ListOfIDSources & theEdges,
2581 const SMESH::ListOfIDSources & theFaces,
2582 const SMESH::DirStruct & theStepVector,
2583 CORBA::Long theNbOfSteps,
2584 CORBA::Boolean theToMakeGroups,
2585 const SMESH::double_array & theScaleFactors,
2586 CORBA::Boolean theScalesVariation,
2587 const SMESH::double_array & theBasePoint,
2588 const SMESH::double_array & theAngles,
2589 CORBA::Boolean theAnglesVariation)
2594 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2595 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2597 TIDSortedElemSet elemsNodes[2];
2598 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2599 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2600 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2602 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2603 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2604 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2605 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2607 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2608 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2609 if ( myIsPreviewMode )
2611 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2612 // previewType = SMDSAbs_Edge;
2614 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2615 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2616 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2617 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2618 workElements = & copyElements[0];
2620 params.SetNoGroups();
2622 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2624 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2625 ::SMESH_MeshEditor::PGroupIDs groupIds =
2626 getEditor().ExtrusionSweep( workElements, params, aHistory );
2628 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2630 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2632 if ( !myIsPreviewMode )
2634 dumpGroupsList( aPythonDump, aGroups );
2635 aPythonDump << this<< ".ExtrusionSweepObjects( "
2639 << theStepVector << ", "
2640 << TVar( theNbOfSteps ) << ", "
2641 << theToMakeGroups << ", "
2642 << TVar( theScaleFactors ) << ", "
2643 << theScalesVariation << ", "
2644 << TVar( theBasePoint ) << ", "
2645 << TVar( theAngles ) << ", "
2646 << theAnglesVariation << " )";
2650 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2653 return aGroups ? aGroups : new SMESH::ListOfGroups;
2655 SMESH_CATCH( SMESH::throwCorbaException );
2659 //=======================================================================
2660 //function : ExtrusionByNormal
2662 //=======================================================================
2664 SMESH::ListOfGroups*
2665 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2666 CORBA::Double stepSize,
2667 CORBA::Long nbOfSteps,
2668 CORBA::Boolean byAverageNormal,
2669 CORBA::Boolean useInputElemsOnly,
2670 CORBA::Boolean makeGroups,
2676 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2678 ExtrusionParams params( stepSize, nbOfSteps, dim,
2679 byAverageNormal, useInputElemsOnly, makeGroups );
2681 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2682 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2684 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2685 if (( elemTypes->length() == 1 ) &&
2686 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2687 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2690 TIDSortedElemSet elemsNodes[2];
2691 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2692 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2694 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2695 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2696 if ( myIsPreviewMode )
2698 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2699 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2700 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2701 workElements = & copyElements[0];
2703 params.SetNoGroups();
2706 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2707 ::SMESH_MeshEditor::PGroupIDs groupIds =
2708 getEditor().ExtrusionSweep( workElements, params, aHistory );
2710 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2712 if (!myIsPreviewMode) {
2713 dumpGroupsList(aPythonDump, aGroups);
2714 aPythonDump << this << ".ExtrusionByNormal( " << objects
2715 << ", " << TVar( stepSize )
2716 << ", " << TVar( nbOfSteps )
2717 << ", " << byAverageNormal
2718 << ", " << useInputElemsOnly
2719 << ", " << makeGroups
2725 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2728 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2730 return aGroups ? aGroups : new SMESH::ListOfGroups;
2732 SMESH_CATCH( SMESH::throwCorbaException );
2736 //=======================================================================
2737 //function : AdvancedExtrusion
2739 //=======================================================================
2741 SMESH::ListOfGroups*
2742 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2743 const SMESH::DirStruct & theStepVector,
2744 CORBA::Long theNbOfSteps,
2745 CORBA::Long theExtrFlags,
2746 CORBA::Double theSewTolerance,
2747 CORBA::Boolean theMakeGroups)
2752 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2754 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2755 theExtrFlags, theSewTolerance );
2757 TIDSortedElemSet elemsNodes[2];
2758 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2760 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2761 ::SMESH_MeshEditor::PGroupIDs groupIds =
2762 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2764 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2766 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2768 if ( !myIsPreviewMode ) {
2769 dumpGroupsList(aPythonDump, aGroups);
2770 aPythonDump << this << ".AdvancedExtrusion( "
2771 << theIDsOfElements << ", "
2772 << theStepVector << ", "
2773 << theNbOfSteps << ", "
2774 << theExtrFlags << ", "
2775 << theSewTolerance << ", "
2776 << theMakeGroups << " )";
2780 getPreviewMesh()->Remove( SMDSAbs_Volume );
2783 return aGroups ? aGroups : new SMESH::ListOfGroups;
2785 SMESH_CATCH( SMESH::throwCorbaException );
2789 //================================================================================
2791 * \brief Convert extrusion error to IDL enum
2793 //================================================================================
2797 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2799 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2803 RETCASE( EXTR_NO_ELEMENTS );
2804 RETCASE( EXTR_PATH_NOT_EDGE );
2805 RETCASE( EXTR_BAD_PATH_SHAPE );
2806 RETCASE( EXTR_BAD_STARTING_NODE );
2807 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2808 RETCASE( EXTR_CANT_GET_TANGENT );
2810 return SMESH::SMESH_MeshEditor::EXTR_OK;
2814 //=======================================================================
2815 //function : extrusionAlongPath
2817 //=======================================================================
2818 SMESH::ListOfGroups*
2819 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2820 const SMESH::ListOfIDSources & theEdges,
2821 const SMESH::ListOfIDSources & theFaces,
2822 SMESH::SMESH_IDSource_ptr thePathObject,
2823 GEOM::GEOM_Object_ptr thePathShape,
2824 CORBA::Long theNodeStart,
2825 CORBA::Boolean theHasAngles,
2826 const SMESH::double_array & theAngles,
2827 CORBA::Boolean theAnglesVariation,
2828 CORBA::Boolean theHasRefPoint,
2829 const SMESH::PointStruct & theRefPoint,
2831 const SMESH::double_array & theScaleFactors,
2832 CORBA::Boolean theScalesVariation,
2833 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2838 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2840 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2841 if ( thePathObject->_is_nil() )
2842 return aGroups._retn();
2845 SMDS_ElemIteratorPtr pathEdgesIterator;
2847 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2848 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2850 // get a sub-mesh of thePathShape
2851 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2852 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2854 return aGroups._retn();
2856 if ( !aSubMesh->GetSubMeshDS() )
2858 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2859 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2860 if ( !aSubMesh->GetSubMeshDS() )
2861 return aGroups._retn();
2863 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2864 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2865 if ( !pathEdgesIterator->more() ||
2866 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2867 return aGroups._retn();
2869 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2873 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2874 prepareIdSource( thePathObject );
2875 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2876 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2877 return aGroups._retn();
2882 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2883 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2887 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2888 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2890 return aGroups._retn();
2893 TIDSortedElemSet elemsNodes[2];
2894 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2895 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2896 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2898 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2899 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2900 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2901 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2903 list<double> angles = ExtrusionParams::toList( theAngles );
2904 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2906 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2907 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2909 int nbOldGroups = myMesh->NbGroup();
2911 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2912 if ( myIsPreviewMode )
2914 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2915 TPreviewMesh * tmpMesh = getPreviewMesh();
2916 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2917 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2918 workElements = & copyElements[0];
2919 theMakeGroups = false;
2922 ::SMESH_MeshEditor::Extrusion_Error error =
2923 getEditor().ExtrusionAlongTrack( workElements,
2924 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2925 angles, theAnglesVariation,
2926 scales, theScalesVariation,
2927 refPntPtr, theMakeGroups );
2929 declareMeshModified( /*isReComputeSafe=*/true );
2930 theError = convExtrError( error );
2932 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2933 if ( theMakeGroups ) {
2934 list<int> groupIDs = myMesh->GetGroupIds();
2935 list<int>::iterator newBegin = groupIDs.begin();
2936 std::advance( newBegin, nbOldGroups ); // skip old groups
2937 groupIDs.erase( groupIDs.begin(), newBegin );
2938 aGroups = getGroups( & groupIDs );
2939 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2942 if ( !myIsPreviewMode ) {
2943 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2944 else aPythonDump << "(_noGroups, error) = ";
2945 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2949 << thePathObject << ", "
2950 << thePathShape << ", "
2951 << theNodeStart << ", "
2952 << theHasAngles << ", "
2953 << TVar( theAngles ) << ", "
2954 << theAnglesVariation << ", "
2955 << theHasRefPoint << ", "
2956 << "SMESH.PointStruct( "
2957 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2958 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2959 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2960 << theMakeGroups << ", "
2961 << TVar( theScaleFactors ) << ", "
2962 << theScalesVariation << " )";
2966 getPreviewMesh()->Remove( SMDSAbs_Volume );
2969 return aGroups._retn();
2971 SMESH_CATCH( SMESH::throwCorbaException );
2975 //================================================================================
2977 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2978 * of given angles along path steps
2979 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2980 * which proceeds the extrusion
2981 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2982 * is used to define the sub-mesh for the path
2984 //================================================================================
2986 SMESH::double_array*
2987 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2988 GEOM::GEOM_Object_ptr thePathShape,
2989 const SMESH::double_array & theAngles)
2991 SMESH::double_array_var aResult = new SMESH::double_array();
2992 int nbAngles = theAngles.length();
2993 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2995 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2996 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2997 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2998 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2999 return aResult._retn();
3000 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3001 if ( nbSteps == nbAngles )
3003 aResult.inout() = theAngles;
3007 aResult->length( nbSteps );
3008 double rAn2St = double( nbAngles ) / double( nbSteps );
3009 double angPrev = 0, angle;
3010 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3012 double angCur = rAn2St * ( iSt+1 );
3013 double angCurFloor = floor( angCur );
3014 double angPrevFloor = floor( angPrev );
3015 if ( angPrevFloor == angCurFloor )
3016 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3019 int iP = int( angPrevFloor );
3020 double angPrevCeil = ceil(angPrev);
3021 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3023 int iC = int( angCurFloor );
3024 if ( iC < nbAngles )
3025 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3027 iP = int( angPrevCeil );
3029 angle += theAngles[ iC ];
3031 aResult[ iSt ] = angle;
3036 // Update Python script
3037 TPythonDump() << "rotAngles = " << theAngles;
3038 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3039 << thePathMesh << ", "
3040 << thePathShape << ", "
3043 return aResult._retn();
3046 //=======================================================================
3049 //=======================================================================
3051 SMESH::ListOfGroups*
3052 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3053 const SMESH::AxisStruct & theAxis,
3054 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3055 CORBA::Boolean theCopy,
3057 ::SMESH_Mesh* theTargetMesh)
3062 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3063 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3065 if ( theTargetMesh )
3069 switch ( theMirrorType ) {
3070 case SMESH::SMESH_MeshEditor::POINT:
3071 aTrsf.SetMirror( P );
3073 case SMESH::SMESH_MeshEditor::AXIS:
3074 aTrsf.SetMirror( gp_Ax1( P, V ));
3077 aTrsf.SetMirror( gp_Ax2( P, V ));
3080 TIDSortedElemSet copyElements;
3081 TIDSortedElemSet* workElements = & theElements;
3083 if ( myIsPreviewMode )
3085 TPreviewMesh * tmpMesh = getPreviewMesh();
3086 tmpMesh->Copy( theElements, copyElements);
3087 if ( !theCopy && !theTargetMesh )
3089 TIDSortedElemSet elemsAround, elemsAroundCopy;
3090 getElementsAround( theElements, getMeshDS(), elemsAround );
3091 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3093 workElements = & copyElements;
3094 theMakeGroups = false;
3097 ::SMESH_MeshEditor::PGroupIDs groupIds =
3098 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3100 if ( !myIsPreviewMode )
3102 if ( theTargetMesh )
3103 theTargetMesh->GetMeshDS()->Modified();
3105 declareMeshModified( /*isReComputeSafe=*/false );
3108 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3110 SMESH_CATCH( SMESH::throwCorbaException );
3114 //=======================================================================
3117 //=======================================================================
3119 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array & theIDsOfElements,
3120 const SMESH::AxisStruct & theAxis,
3121 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3122 CORBA::Boolean theCopy)
3124 if ( !myIsPreviewMode ) {
3125 TPythonDump() << this << ".Mirror( "
3126 << theIDsOfElements << ", "
3128 << mirrorTypeName(theMirrorType) << ", "
3131 if ( theIDsOfElements.length() > 0 )
3133 TIDSortedElemSet elements;
3134 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3135 mirror(elements, theAxis, theMirrorType, theCopy, false);
3140 //=======================================================================
3141 //function : MirrorObject
3143 //=======================================================================
3145 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3146 const SMESH::AxisStruct & theAxis,
3147 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3148 CORBA::Boolean theCopy)
3150 if ( !myIsPreviewMode ) {
3151 TPythonDump() << this << ".MirrorObject( "
3152 << theObject << ", "
3154 << mirrorTypeName(theMirrorType) << ", "
3157 TIDSortedElemSet elements;
3159 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3161 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3162 mirror(elements, theAxis, theMirrorType, theCopy, false);
3165 //=======================================================================
3166 //function : MirrorMakeGroups
3168 //=======================================================================
3170 SMESH::ListOfGroups*
3171 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array& theIDsOfElements,
3172 const SMESH::AxisStruct& theMirror,
3173 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3175 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3177 SMESH::ListOfGroups * aGroups = 0;
3178 if ( theIDsOfElements.length() > 0 )
3180 TIDSortedElemSet elements;
3181 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3182 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3184 if (!myIsPreviewMode) {
3185 dumpGroupsList(aPythonDump, aGroups);
3186 aPythonDump << this << ".MirrorMakeGroups( "
3187 << theIDsOfElements << ", "
3188 << theMirror << ", "
3189 << mirrorTypeName(theMirrorType) << " )";
3194 //=======================================================================
3195 //function : MirrorObjectMakeGroups
3197 //=======================================================================
3199 SMESH::ListOfGroups*
3200 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3201 const SMESH::AxisStruct& theMirror,
3202 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3204 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3206 SMESH::ListOfGroups * aGroups = 0;
3207 TIDSortedElemSet elements;
3208 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3209 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3211 if (!myIsPreviewMode)
3213 dumpGroupsList(aPythonDump,aGroups);
3214 aPythonDump << this << ".MirrorObjectMakeGroups( "
3215 << theObject << ", "
3216 << theMirror << ", "
3217 << mirrorTypeName(theMirrorType) << " )";
3222 //=======================================================================
3223 //function : MirrorMakeMesh
3225 //=======================================================================
3227 SMESH::SMESH_Mesh_ptr
3228 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array& theIDsOfElements,
3229 const SMESH::AxisStruct& theMirror,
3230 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3231 CORBA::Boolean theCopyGroups,
3232 const char* theMeshName)
3234 SMESH_Mesh_i* mesh_i;
3235 SMESH::SMESH_Mesh_var mesh;
3236 { // open new scope to dump "MakeMesh" command
3237 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3239 TPythonDump pydump; // to prevent dump at mesh creation
3241 mesh = makeMesh( theMeshName );
3242 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3243 if (mesh_i && theIDsOfElements.length() > 0 )
3245 TIDSortedElemSet elements;
3246 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3247 mirror(elements, theMirror, theMirrorType,
3248 false, theCopyGroups, & mesh_i->GetImpl());
3249 mesh_i->CreateGroupServants();
3252 if (!myIsPreviewMode) {
3253 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3254 << theIDsOfElements << ", "
3255 << theMirror << ", "
3256 << mirrorTypeName(theMirrorType) << ", "
3257 << theCopyGroups << ", '"
3258 << theMeshName << "' )";
3263 if (!myIsPreviewMode && mesh_i)
3264 mesh_i->GetGroups();
3266 return mesh._retn();
3269 //=======================================================================
3270 //function : MirrorObjectMakeMesh
3272 //=======================================================================
3274 SMESH::SMESH_Mesh_ptr
3275 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3276 const SMESH::AxisStruct& theMirror,
3277 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3278 CORBA::Boolean theCopyGroups,
3279 const char* theMeshName)
3281 SMESH_Mesh_i* mesh_i;
3282 SMESH::SMESH_Mesh_var mesh;
3283 { // open new scope to dump "MakeMesh" command
3284 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3286 TPythonDump pydump; // to prevent dump at mesh creation
3288 mesh = makeMesh( theMeshName );
3289 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3290 TIDSortedElemSet elements;
3292 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3294 mirror(elements, theMirror, theMirrorType,
3295 false, theCopyGroups, & mesh_i->GetImpl());
3296 mesh_i->CreateGroupServants();
3298 if (!myIsPreviewMode) {
3299 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3300 << theObject << ", "
3301 << theMirror << ", "
3302 << mirrorTypeName(theMirrorType) << ", "
3303 << theCopyGroups << ", '"
3304 << theMeshName << "' )";
3309 if (!myIsPreviewMode && mesh_i)
3310 mesh_i->GetGroups();
3312 return mesh._retn();
3315 //=======================================================================
3316 //function : translate
3318 //=======================================================================
3320 SMESH::ListOfGroups*
3321 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3322 const SMESH::DirStruct & theVector,
3323 CORBA::Boolean theCopy,
3325 ::SMESH_Mesh* theTargetMesh)
3330 if ( theTargetMesh )
3334 const SMESH::PointStruct * P = &theVector.PS;
3335 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3337 TIDSortedElemSet copyElements;
3338 TIDSortedElemSet* workElements = &theElements;
3340 if ( myIsPreviewMode )
3342 TPreviewMesh * tmpMesh = getPreviewMesh();
3343 tmpMesh->Copy( theElements, copyElements);
3344 if ( !theCopy && !theTargetMesh )
3346 TIDSortedElemSet elemsAround, elemsAroundCopy;
3347 getElementsAround( theElements, getMeshDS(), elemsAround );
3348 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3350 workElements = & copyElements;
3351 theMakeGroups = false;
3354 ::SMESH_MeshEditor::PGroupIDs groupIds =
3355 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3357 if ( !myIsPreviewMode )
3359 if ( theTargetMesh )
3360 theTargetMesh->GetMeshDS()->Modified();
3362 declareMeshModified( /*isReComputeSafe=*/false );
3365 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3367 SMESH_CATCH( SMESH::throwCorbaException );
3371 //=======================================================================
3372 //function : Translate
3374 //=======================================================================
3376 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3377 const SMESH::DirStruct & theVector,
3378 CORBA::Boolean theCopy)
3380 if (!myIsPreviewMode) {
3381 TPythonDump() << this << ".Translate( "
3382 << theIDsOfElements << ", "
3383 << theVector << ", "
3386 if (theIDsOfElements.length()) {
3387 TIDSortedElemSet elements;
3388 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3389 translate(elements, theVector, theCopy, false);
3393 //=======================================================================
3394 //function : TranslateObject
3396 //=======================================================================
3398 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3399 const SMESH::DirStruct & theVector,
3400 CORBA::Boolean theCopy)
3402 if (!myIsPreviewMode) {
3403 TPythonDump() << this << ".TranslateObject( "
3404 << theObject << ", "
3405 << theVector << ", "
3408 TIDSortedElemSet elements;
3410 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3412 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3413 translate(elements, theVector, theCopy, false);
3416 //=======================================================================
3417 //function : TranslateMakeGroups
3419 //=======================================================================
3421 SMESH::ListOfGroups*
3422 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3423 const SMESH::DirStruct& theVector)
3425 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3427 SMESH::ListOfGroups * aGroups = 0;
3428 if (theIDsOfElements.length()) {
3429 TIDSortedElemSet elements;
3430 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3431 aGroups = translate(elements,theVector,true,true);
3433 if (!myIsPreviewMode) {
3434 dumpGroupsList(aPythonDump, aGroups);
3435 aPythonDump << this << ".TranslateMakeGroups( "
3436 << theIDsOfElements << ", "
3437 << theVector << " )";
3442 //=======================================================================
3443 //function : TranslateObjectMakeGroups
3445 //=======================================================================
3447 SMESH::ListOfGroups*
3448 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3449 const SMESH::DirStruct& theVector)
3451 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3453 SMESH::ListOfGroups * aGroups = 0;
3454 TIDSortedElemSet elements;
3455 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3456 aGroups = translate(elements, theVector, true, true);
3458 if (!myIsPreviewMode) {
3459 dumpGroupsList(aPythonDump, aGroups);
3460 aPythonDump << this << ".TranslateObjectMakeGroups( "
3461 << theObject << ", "
3462 << theVector << " )";
3467 //=======================================================================
3468 //function : TranslateMakeMesh
3470 //=======================================================================
3472 SMESH::SMESH_Mesh_ptr
3473 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3474 const SMESH::DirStruct& theVector,
3475 CORBA::Boolean theCopyGroups,
3476 const char* theMeshName)
3478 SMESH_Mesh_i* mesh_i;
3479 SMESH::SMESH_Mesh_var mesh;
3481 { // open new scope to dump "MakeMesh" command
3482 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3484 TPythonDump pydump; // to prevent dump at mesh creation
3486 mesh = makeMesh( theMeshName );
3487 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3489 if ( mesh_i && theIDsOfElements.length() )
3491 TIDSortedElemSet elements;
3492 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3493 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3494 mesh_i->CreateGroupServants();
3497 if ( !myIsPreviewMode ) {
3498 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3499 << theIDsOfElements << ", "
3500 << theVector << ", "
3501 << theCopyGroups << ", '"
3502 << theMeshName << "' )";
3507 if (!myIsPreviewMode && mesh_i)
3508 mesh_i->GetGroups();
3510 return mesh._retn();
3513 //=======================================================================
3514 //function : TranslateObjectMakeMesh
3516 //=======================================================================
3518 SMESH::SMESH_Mesh_ptr
3519 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3520 const SMESH::DirStruct& theVector,
3521 CORBA::Boolean theCopyGroups,
3522 const char* theMeshName)
3525 SMESH_Mesh_i* mesh_i;
3526 SMESH::SMESH_Mesh_var mesh;
3527 { // open new scope to dump "MakeMesh" command
3528 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3530 TPythonDump pydump; // to prevent dump at mesh creation
3531 mesh = makeMesh( theMeshName );
3532 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3534 TIDSortedElemSet elements;
3536 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3538 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3539 mesh_i->CreateGroupServants();
3541 if ( !myIsPreviewMode ) {
3542 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3543 << theObject << ", "
3544 << theVector << ", "
3545 << theCopyGroups << ", '"
3546 << theMeshName << "' )";
3551 if (!myIsPreviewMode && mesh_i)
3552 mesh_i->GetGroups();
3554 return mesh._retn();
3556 SMESH_CATCH( SMESH::throwCorbaException );
3560 //=======================================================================
3563 //=======================================================================
3565 SMESH::ListOfGroups*
3566 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3567 const SMESH::AxisStruct & theAxis,
3568 CORBA::Double theAngle,
3569 CORBA::Boolean theCopy,
3571 ::SMESH_Mesh* theTargetMesh)
3576 if ( theTargetMesh )
3579 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3580 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3583 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3585 TIDSortedElemSet copyElements;
3586 TIDSortedElemSet* workElements = &theElements;
3587 if ( myIsPreviewMode ) {
3588 TPreviewMesh * tmpMesh = getPreviewMesh();
3589 tmpMesh->Copy( theElements, copyElements );
3590 if ( !theCopy && !theTargetMesh )
3592 TIDSortedElemSet elemsAround, elemsAroundCopy;
3593 getElementsAround( theElements, getMeshDS(), elemsAround );
3594 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3596 workElements = ©Elements;
3597 theMakeGroups = false;
3600 ::SMESH_MeshEditor::PGroupIDs groupIds =
3601 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3603 if ( !myIsPreviewMode)
3605 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3606 else declareMeshModified( /*isReComputeSafe=*/false );
3609 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3611 SMESH_CATCH( SMESH::throwCorbaException );
3615 //=======================================================================
3618 //=======================================================================
3620 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3621 const SMESH::AxisStruct & theAxis,
3622 CORBA::Double theAngle,
3623 CORBA::Boolean theCopy)
3625 if (!myIsPreviewMode) {
3626 TPythonDump() << this << ".Rotate( "
3627 << theIDsOfElements << ", "
3629 << TVar( theAngle ) << ", "
3632 if (theIDsOfElements.length() > 0)
3634 TIDSortedElemSet elements;
3635 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3636 rotate(elements,theAxis,theAngle,theCopy,false);
3640 //=======================================================================
3641 //function : RotateObject
3643 //=======================================================================
3645 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3646 const SMESH::AxisStruct & theAxis,
3647 CORBA::Double theAngle,
3648 CORBA::Boolean theCopy)
3650 if ( !myIsPreviewMode ) {
3651 TPythonDump() << this << ".RotateObject( "
3652 << theObject << ", "
3654 << TVar( theAngle ) << ", "
3657 TIDSortedElemSet elements;
3658 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3659 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3660 rotate(elements,theAxis,theAngle,theCopy,false);
3663 //=======================================================================
3664 //function : RotateMakeGroups
3666 //=======================================================================
3668 SMESH::ListOfGroups*
3669 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3670 const SMESH::AxisStruct& theAxis,
3671 CORBA::Double theAngle)
3673 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3675 SMESH::ListOfGroups * aGroups = 0;
3676 if (theIDsOfElements.length() > 0)
3678 TIDSortedElemSet elements;
3679 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3680 aGroups = rotate(elements,theAxis,theAngle,true,true);
3682 if (!myIsPreviewMode) {
3683 dumpGroupsList(aPythonDump, aGroups);
3684 aPythonDump << this << ".RotateMakeGroups( "
3685 << theIDsOfElements << ", "
3687 << TVar( theAngle ) << " )";
3692 //=======================================================================
3693 //function : RotateObjectMakeGroups
3695 //=======================================================================
3697 SMESH::ListOfGroups*
3698 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3699 const SMESH::AxisStruct& theAxis,
3700 CORBA::Double theAngle)
3702 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3704 SMESH::ListOfGroups * aGroups = 0;
3705 TIDSortedElemSet elements;
3706 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3707 aGroups = rotate(elements, theAxis, theAngle, true, true);
3709 if (!myIsPreviewMode) {
3710 dumpGroupsList(aPythonDump, aGroups);
3711 aPythonDump << this << ".RotateObjectMakeGroups( "
3712 << theObject << ", "
3714 << TVar( theAngle ) << " )";
3719 //=======================================================================
3720 //function : RotateMakeMesh
3722 //=======================================================================
3724 SMESH::SMESH_Mesh_ptr
3725 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3726 const SMESH::AxisStruct& theAxis,
3727 CORBA::Double theAngleInRadians,
3728 CORBA::Boolean theCopyGroups,
3729 const char* theMeshName)
3732 SMESH::SMESH_Mesh_var mesh;
3733 SMESH_Mesh_i* mesh_i;
3735 { // open new scope to dump "MakeMesh" command
3736 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3738 TPythonDump pydump; // to prevent dump at mesh creation
3740 mesh = makeMesh( theMeshName );
3741 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3743 if ( mesh_i && theIDsOfElements.length() > 0 )
3745 TIDSortedElemSet elements;
3746 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3747 rotate(elements, theAxis, theAngleInRadians,
3748 false, theCopyGroups, & mesh_i->GetImpl());
3749 mesh_i->CreateGroupServants();
3751 if ( !myIsPreviewMode ) {
3752 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3753 << theIDsOfElements << ", "
3755 << TVar( theAngleInRadians ) << ", "
3756 << theCopyGroups << ", '"
3757 << theMeshName << "' )";
3762 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3763 mesh_i->GetGroups();
3765 return mesh._retn();
3767 SMESH_CATCH( SMESH::throwCorbaException );
3771 //=======================================================================
3772 //function : RotateObjectMakeMesh
3774 //=======================================================================
3776 SMESH::SMESH_Mesh_ptr
3777 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3778 const SMESH::AxisStruct& theAxis,
3779 CORBA::Double theAngleInRadians,
3780 CORBA::Boolean theCopyGroups,
3781 const char* theMeshName)
3784 SMESH::SMESH_Mesh_var mesh;
3785 SMESH_Mesh_i* mesh_i;
3787 {// open new scope to dump "MakeMesh" command
3788 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3790 TPythonDump pydump; // to prevent dump at mesh creation
3791 mesh = makeMesh( theMeshName );
3792 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3794 TIDSortedElemSet elements;
3796 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3798 rotate(elements, theAxis, theAngleInRadians,
3799 false, theCopyGroups, & mesh_i->GetImpl());
3800 mesh_i->CreateGroupServants();
3802 if ( !myIsPreviewMode ) {
3803 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3804 << theObject << ", "
3806 << TVar( theAngleInRadians ) << ", "
3807 << theCopyGroups << ", '"
3808 << theMeshName << "' )";
3813 if (!myIsPreviewMode && mesh_i)
3814 mesh_i->GetGroups();
3816 return mesh._retn();
3818 SMESH_CATCH( SMESH::throwCorbaException );
3822 //=======================================================================
3825 //=======================================================================
3827 SMESH::ListOfGroups*
3828 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3829 const SMESH::PointStruct& thePoint,
3830 const SMESH::double_array& theScaleFact,
3831 CORBA::Boolean theCopy,
3833 ::SMESH_Mesh* theTargetMesh)
3837 if ( theScaleFact.length() < 1 )
3838 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3839 if ( theScaleFact.length() == 2 )
3840 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3842 if ( theTargetMesh )
3845 TIDSortedElemSet elements;
3846 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3847 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3852 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3853 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3857 // fight against orthogonalization
3858 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3859 // 0, S[1], 0, thePoint.y * (1-S[1]),
3860 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3861 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3862 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3863 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3864 loc.SetCoord( thePoint.x * (1-S[0]),
3865 thePoint.y * (1-S[1]),
3866 thePoint.z * (1-S[2]));
3867 M.SetDiagonal( S[0], S[1], S[2] );
3869 TIDSortedElemSet copyElements;
3870 TIDSortedElemSet* workElements = &elements;
3871 if ( myIsPreviewMode )
3873 TPreviewMesh * tmpMesh = getPreviewMesh();
3874 tmpMesh->Copy( elements, copyElements);
3875 if ( !theCopy && !theTargetMesh )
3877 TIDSortedElemSet elemsAround, elemsAroundCopy;
3878 getElementsAround( elements, getMeshDS(), elemsAround );
3879 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3881 workElements = & copyElements;
3882 theMakeGroups = false;
3885 ::SMESH_MeshEditor::PGroupIDs groupIds =
3886 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3888 if ( !myIsPreviewMode )
3890 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3891 else declareMeshModified( /*isReComputeSafe=*/false );
3893 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3895 SMESH_CATCH( SMESH::throwCorbaException );
3899 //=======================================================================
3902 //=======================================================================
3904 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3905 const SMESH::PointStruct& thePoint,
3906 const SMESH::double_array& theScaleFact,
3907 CORBA::Boolean theCopy)
3910 if ( !myIsPreviewMode ) {
3911 TPythonDump() << this << ".Scale( "
3912 << theObject << ", "
3914 << TVar( theScaleFact ) << ", "
3917 scale(theObject, thePoint, theScaleFact, theCopy, false);
3921 //=======================================================================
3922 //function : ScaleMakeGroups
3924 //=======================================================================
3926 SMESH::ListOfGroups*
3927 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3928 const SMESH::PointStruct& thePoint,
3929 const SMESH::double_array& theScaleFact)
3931 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3933 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3934 if (!myIsPreviewMode) {
3935 dumpGroupsList(aPythonDump, aGroups);
3936 aPythonDump << this << ".Scale("
3939 << TVar( theScaleFact ) << ",True,True)";
3945 //=======================================================================
3946 //function : ScaleMakeMesh
3948 //=======================================================================
3950 SMESH::SMESH_Mesh_ptr
3951 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3952 const SMESH::PointStruct& thePoint,
3953 const SMESH::double_array& theScaleFact,
3954 CORBA::Boolean theCopyGroups,
3955 const char* theMeshName)
3957 SMESH_Mesh_i* mesh_i;
3958 SMESH::SMESH_Mesh_var mesh;
3959 { // open new scope to dump "MakeMesh" command
3960 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3962 TPythonDump pydump; // to prevent dump at mesh creation
3963 mesh = makeMesh( theMeshName );
3964 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3968 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3969 mesh_i->CreateGroupServants();
3971 if ( !myIsPreviewMode )
3972 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3973 << theObject << ", "
3975 << TVar( theScaleFact ) << ", "
3976 << theCopyGroups << ", '"
3977 << theMeshName << "' )";
3981 if (!myIsPreviewMode && mesh_i)
3982 mesh_i->GetGroups();
3984 return mesh._retn();
3987 //================================================================================
3989 * \brief Make an offset mesh from a source 2D mesh
3990 * \param [inout] theObject - source mesh. New elements are added to this mesh
3991 * if \a theMeshName is empty.
3992 * \param [in] theValue - offset value
3993 * \param [in] theCopyGroups - to generate groups
3994 * \param [in] theMeshName - optional name of a new mesh
3995 * \param [out] theGroups - new groups
3996 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
3998 //================================================================================
4000 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4001 CORBA::Double theValue,
4002 CORBA::Boolean theCopyGroups,
4003 CORBA::Boolean theCopyElements,
4004 const char* theMeshName,
4005 SMESH::ListOfGroups_out theGroups)
4010 SMESHDS_Mesh* aMeshDS = getMeshDS();
4012 SMESH::SMESH_Mesh_var mesh_var;
4013 ::SMESH_MeshEditor::PGroupIDs groupIds;
4017 TIDSortedElemSet elements, copyElements;
4018 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4019 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4022 SMESH_Mesh* tgtMesh = 0;
4023 if ( myIsPreviewMode )
4025 TPreviewMesh * tmpMesh = getPreviewMesh();
4027 tmpMesh->Copy( elements, copyElements );
4028 elements.swap( copyElements );
4029 theCopyGroups = false;
4030 theCopyElements = false;
4035 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4036 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4037 tgtMesh = & mesh_i->GetImpl();
4039 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4040 theCopyGroups, theCopyElements, !myIsPreviewMode );
4042 tgtMesh->GetMeshDS()->Modified();
4045 if ( myIsPreviewMode )
4047 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4051 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4053 // new mesh empty, remove it
4054 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4055 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4056 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4057 builder->RemoveObjectWithChildren( meshSO );
4058 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4060 if ( !groupIds ) // nothing changed in the current mesh
4061 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4063 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4065 // result of Offset() is a tuple (mesh, groups)
4066 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4067 else pyDump << mesh_var << ", ";
4068 pyDump << theGroups << " = " << this << ".Offset( "
4069 << theObject << ", "
4071 << theCopyGroups << ", "
4072 << theCopyElements << ", "
4073 << "'" << theMeshName<< "')";
4076 return mesh_var._retn();
4078 SMESH_CATCH( SMESH::throwCorbaException );
4079 return SMESH::SMESH_Mesh::_nil();
4082 //=======================================================================
4083 //function : findCoincidentNodes
4085 //=======================================================================
4087 void SMESH_MeshEditor_i::
4088 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4089 CORBA::Double Tolerance,
4090 SMESH::array_of_long_array_out GroupsOfNodes,
4091 CORBA::Boolean SeparateCornersAndMedium)
4093 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4094 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4096 GroupsOfNodes = new SMESH::array_of_long_array;
4097 GroupsOfNodes->length( aListOfListOfNodes.size() );
4098 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4099 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4101 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4102 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4103 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4104 aGroup.length( aListOfNodes.size() );
4105 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4106 aGroup[ j ] = (*lIt)->GetID();
4110 //=======================================================================
4111 //function : FindCoincidentNodes
4113 //=======================================================================
4115 void SMESH_MeshEditor_i::
4116 FindCoincidentNodes (CORBA::Double Tolerance,
4117 SMESH::array_of_long_array_out GroupsOfNodes,
4118 CORBA::Boolean SeparateCornersAndMedium)
4123 TIDSortedNodeSet nodes; // no input nodes
4124 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4126 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4127 << Tolerance << ", "
4128 << SeparateCornersAndMedium << " )";
4130 SMESH_CATCH( SMESH::throwCorbaException );
4133 //=======================================================================
4134 //function : FindCoincidentNodesOnPart
4136 //=======================================================================
4138 void SMESH_MeshEditor_i::
4139 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4140 CORBA::Double Tolerance,
4141 SMESH::array_of_long_array_out GroupsOfNodes,
4142 CORBA::Boolean SeparateCornersAndMedium)
4147 TIDSortedNodeSet nodes;
4148 prepareIdSource( theObject );
4149 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4151 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4153 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4155 << Tolerance << ", "
4156 << SeparateCornersAndMedium << " )";
4158 SMESH_CATCH( SMESH::throwCorbaException );
4161 //================================================================================
4163 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4164 * ExceptSubMeshOrGroups
4166 //================================================================================
4168 void SMESH_MeshEditor_i::
4169 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4170 CORBA::Double theTolerance,
4171 SMESH::array_of_long_array_out theGroupsOfNodes,
4172 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4173 CORBA::Boolean theSeparateCornersAndMedium)
4178 TIDSortedNodeSet nodes;
4179 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4181 prepareIdSource( theObjects[i] );
4182 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4184 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4186 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4188 while ( nodeIt->more() )
4189 nodes.erase( cast2Node( nodeIt->next() ));
4191 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4193 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4194 << theObjects <<", "
4195 << theTolerance << ", "
4196 << theExceptSubMeshOrGroups << ", "
4197 << theSeparateCornersAndMedium << " )";
4199 SMESH_CATCH( SMESH::throwCorbaException );
4202 //=======================================================================
4203 //function : MergeNodes
4205 //=======================================================================
4207 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4208 const SMESH::ListOfIDSources& NodesToKeep,
4209 CORBA::Boolean AvoidMakingHoles)
4214 SMESHDS_Mesh* aMesh = getMeshDS();
4216 TPythonDump aTPythonDump;
4217 aTPythonDump << this << ".MergeNodes([";
4219 TIDSortedNodeSet setOfNodesToKeep;
4220 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4222 prepareIdSource( NodesToKeep[i] );
4223 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4224 while ( nodeIt->more() )
4225 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4228 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4229 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4231 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4232 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4233 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4234 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4236 CORBA::Long index = aNodeGroup[ j ];
4237 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4239 if ( setOfNodesToKeep.count( node ))
4240 aListOfNodes.push_front( node );
4242 aListOfNodes.push_back( node );
4245 if ( aListOfNodes.size() < 2 )
4246 aListOfListOfNodes.pop_back();
4248 if ( i > 0 ) aTPythonDump << ", ";
4249 aTPythonDump << aNodeGroup;
4252 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4254 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4256 declareMeshModified( /*isReComputeSafe=*/false );
4258 SMESH_CATCH( SMESH::throwCorbaException );
4261 //=======================================================================
4262 //function : FindEqualElements
4264 //=======================================================================
4266 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4267 const SMESH::ListOfIDSources& theExceptObjects,
4268 SMESH::array_of_long_array_out theGroupsOfElementsID)
4273 theGroupsOfElementsID = new SMESH::array_of_long_array;
4275 TIDSortedElemSet elems;
4276 bool hasOkObject = false;
4277 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4279 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4281 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4282 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4283 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4289 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4291 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4292 while ( elemIt->more() )
4293 elems.erase( elemIt->next() );
4296 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4297 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4299 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4301 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4302 aListOfListOfElementsID.begin();
4303 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4305 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4306 list<int>& listOfIDs = *arraysIt;
4307 aGroup.length( listOfIDs.size() );
4308 list<int>::iterator idIt = listOfIDs.begin();
4309 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4310 aGroup[ k ] = *idIt;
4313 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4314 << theObjects << ", "
4315 << theExceptObjects << " )";
4318 SMESH_CATCH( SMESH::throwCorbaException );
4321 //=======================================================================
4322 //function : MergeElements
4324 //=======================================================================
4326 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4327 const SMESH::ListOfIDSources& theElementsToKeep)
4332 TPythonDump aTPythonDump;
4333 aTPythonDump << this << ".MergeElements( [";
4335 NCollection_Map< int > idsToKeep;
4336 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4338 if ( CORBA::is_nil( theElementsToKeep[i] ))
4340 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4341 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4343 SMESH::long_array_var elementsId = theElementsToKeep[i]->GetIDs();
4344 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4345 idsToKeep.Add( elementsId[ j ]);
4348 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4350 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4352 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4353 aListOfListOfElementsID.push_back( list< int >() );
4354 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4355 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4357 CORBA::Long id = anElemsIDGroup[ j ];
4358 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4359 else aListOfElemsID.push_back( id );
4361 if ( aListOfElemsID.size() < 2 )
4362 aListOfListOfElementsID.pop_back();
4363 if ( i > 0 ) aTPythonDump << ", ";
4364 aTPythonDump << anElemsIDGroup;
4367 getEditor().MergeElements(aListOfListOfElementsID);
4369 declareMeshModified( /*isReComputeSafe=*/true );
4371 aTPythonDump << "], " << theElementsToKeep << " )";
4373 SMESH_CATCH( SMESH::throwCorbaException );
4376 //=======================================================================
4377 //function : MergeEqualElements
4379 //=======================================================================
4381 void SMESH_MeshEditor_i::MergeEqualElements()
4386 getEditor().MergeEqualElements();
4388 declareMeshModified( /*isReComputeSafe=*/true );
4390 TPythonDump() << this << ".MergeEqualElements()";
4392 SMESH_CATCH( SMESH::throwCorbaException );
4395 //=============================================================================
4397 * Move the node to a given point
4399 //=============================================================================
4401 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long NodeID,
4407 initData(/*deleteSearchers=*/false);
4409 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4413 if ( theNodeSearcher )
4414 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4416 if ( myIsPreviewMode ) // make preview data
4418 // in a preview mesh, make edges linked to a node
4419 TPreviewMesh& tmpMesh = *getPreviewMesh();
4420 TIDSortedElemSet linkedNodes;
4421 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4422 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4423 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4424 for ( ; nIt != linkedNodes.end(); ++nIt )
4426 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4427 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4431 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4432 // fill preview data
4434 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4435 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4437 getMeshDS()->MoveNode(node, x, y, z);
4439 if ( !myIsPreviewMode )
4441 // Update Python script
4442 TPythonDump() << "isDone = " << this << ".MoveNode( "
4443 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4444 declareMeshModified( /*isReComputeSafe=*/false );
4447 SMESH_CATCH( SMESH::throwCorbaException );
4452 //================================================================================
4454 * \brief Return ID of node closest to a given point
4456 //================================================================================
4458 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4463 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4465 if ( !theNodeSearcher ) {
4466 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4469 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4470 return node->GetID();
4472 SMESH_CATCH( SMESH::throwCorbaException );
4476 //================================================================================
4478 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4479 * move the node closest to the point to point's location and return ID of the node
4481 //================================================================================
4483 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4486 CORBA::Long theNodeID)
4489 // We keep theNodeSearcher until any mesh modification:
4490 // 1) initData() deletes theNodeSearcher at any edition,
4491 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4493 initData(/*deleteSearchers=*/false);
4495 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4497 int nodeID = theNodeID;
4498 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4499 if ( !node ) // preview moving node
4501 if ( !theNodeSearcher ) {
4502 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4505 node = theNodeSearcher->FindClosestTo( p );
4508 nodeID = node->GetID();
4509 if ( myIsPreviewMode ) // make preview data
4511 // in a preview mesh, make edges linked to a node
4512 TPreviewMesh tmpMesh = *getPreviewMesh();
4513 TIDSortedElemSet linkedNodes;
4514 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4515 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4516 for ( ; nIt != linkedNodes.end(); ++nIt )
4518 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4519 tmpMesh.Copy( &edge );
4522 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4524 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4525 // fill preview data
4527 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4529 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4533 getMeshDS()->MoveNode(node, x, y, z);
4537 if ( !myIsPreviewMode )
4539 TPythonDump() << "nodeID = " << this
4540 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4541 << ", " << nodeID << " )";
4543 declareMeshModified( /*isReComputeSafe=*/false );
4548 SMESH_CATCH( SMESH::throwCorbaException );
4552 //=======================================================================
4554 * Return elements of given type where the given point is IN or ON.
4556 * 'ALL' type means elements of any type excluding nodes
4558 //=======================================================================
4560 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4563 SMESH::ElementType type)
4566 SMESH::long_array_var res = new SMESH::long_array;
4567 vector< const SMDS_MeshElement* > foundElems;
4569 theSearchersDeleter.Set( myMesh );
4570 if ( !theElementSearcher ) {
4571 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4573 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4574 SMDSAbs_ElementType( type ),
4576 res->length( foundElems.size() );
4577 for ( size_t i = 0; i < foundElems.size(); ++i )
4578 res[i] = foundElems[i]->GetID();
4582 SMESH_CATCH( SMESH::throwCorbaException );
4586 //=======================================================================
4587 //function : FindAmongElementsByPoint
4588 //purpose : Searching among the given elements, return elements of given type
4589 // where the given point is IN or ON.
4590 // 'ALL' type means elements of any type excluding nodes
4591 //=======================================================================
4594 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4598 SMESH::ElementType type)
4601 SMESH::long_array_var res = new SMESH::long_array;
4603 prepareIdSource( elementIDs );
4604 if ( type != SMESH::NODE )
4606 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4607 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4608 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4609 type != types[0] ) // but search of elements of dim > 0
4613 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4614 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4615 if ( mesh_i != myMesh_i )
4617 SMESH::SMESH_MeshEditor_var editor=
4618 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4619 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4622 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4623 return FindElementsByPoint( x,y,z, type );
4625 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4627 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4628 if ( !theElementSearcher )
4630 // create a searcher from elementIDs
4631 SMDS_ElemIteratorPtr elemIt;
4632 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4634 //prepareIdSource( elementIDs );
4635 elemIt = myMesh_i->GetElements( elementIDs, type );
4639 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4642 vector< const SMDS_MeshElement* > foundElems;
4644 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4645 SMDSAbs_ElementType( type ),
4647 res->length( foundElems.size() );
4648 for ( size_t i = 0; i < foundElems.size(); ++i )
4649 res[i] = foundElems[i]->GetID();
4653 SMESH_CATCH( SMESH::throwCorbaException );
4657 //=======================================================================
4658 //function : ProjectPoint
4659 //purpose : Project a point to a mesh object.
4660 // Return ID of an element of given type where the given point is projected
4661 // and coordinates of the projection point.
4662 // In the case if nothing found, return -1 and []
4663 //=======================================================================
4665 CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4668 SMESH::ElementType type,
4669 SMESH::SMESH_IDSource_ptr meshObject,
4670 SMESH::double_array_out projecton)
4672 if ( CORBA::is_nil( meshObject ))
4673 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4677 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4678 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4679 if ( mesh_i != myMesh_i )
4681 SMESH::SMESH_MeshEditor_var editor=
4682 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4683 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4687 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4688 if ( !theElementSearcher )
4690 // create a searcher from meshObject
4692 SMDS_ElemIteratorPtr elemIt;
4693 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4695 prepareIdSource( meshObject );
4696 elemIt = myMesh_i->GetElements( meshObject, type );
4700 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4703 const SMDS_MeshElement* elem = 0;
4704 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4705 SMDSAbs_ElementType( type ),
4708 projecton = new SMESH::double_array();
4709 if ( elem && !elem->IsNull() )
4711 projecton->length( 3 );
4712 projecton[0] = pProj.X();
4713 projecton[1] = pProj.Y();
4714 projecton[2] = pProj.Z();
4715 return elem->GetID();
4718 SMESH_CATCH( SMESH::throwCorbaException );
4722 //=======================================================================
4723 //function : GetPointState
4724 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4725 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4726 //=======================================================================
4728 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4733 theSearchersDeleter.Set( myMesh );
4734 if ( !theElementSearcher ) {
4735 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4737 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4739 SMESH_CATCH( SMESH::throwCorbaException );
4743 //=======================================================================
4744 //function : IsManifold
4745 //purpose : Check if a 2D mesh is manifold
4746 //=======================================================================
4748 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4750 bool isManifold = true;
4753 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4754 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4756 /*closedOnly=*/true,
4758 SMESH_CATCH( SMESH::throwCorbaException );
4763 //=======================================================================
4764 //function : IsCoherentOrientation2D
4765 //purpose : Check if orientation of 2D elements is coherent
4766 //=======================================================================
4768 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4770 bool isGoodOri = true;
4773 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4774 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4776 /*closedOnly=*/true,
4779 SMESH_CATCH( SMESH::throwCorbaException );
4784 //=======================================================================
4785 //function : Get1DBranches
4786 //purpose : Partition given 1D elements into groups of contiguous edges.
4787 // A node where number of meeting edges != 2 is a group end.
4788 // An optional startNode is used to orient groups it belongs to.
4789 //return : a list of edge groups and a list of corresponding node groups.
4790 // If a group is closed, the first and last nodes of the group are same.
4791 //=======================================================================
4793 SMESH::array_of_long_array*
4794 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4795 CORBA::Long theStartNode,
4796 SMESH::array_of_long_array_out theNodeGroups )
4798 if ( CORBA::is_nil( theEdges ))
4799 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4801 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4802 theNodeGroups = new SMESH::array_of_long_array;
4806 prepareIdSource( theEdges );
4808 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4809 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4810 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4813 getMeshDS()->FindNode( theStartNode ));
4815 edgeGroupArray->length( edgeBranches.size() );
4816 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4818 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4819 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4820 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4823 theNodeGroups->length( nodeBranches.size() );
4824 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4826 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4827 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4828 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4831 SMESH_CATCH( SMESH::throwCorbaException );
4833 return edgeGroupArray._retn();
4836 //=======================================================================
4837 //function : FindSharpEdges
4838 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4839 //=======================================================================
4841 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4842 CORBA::Boolean theAddExisting)
4844 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4849 std::vector< SMESH_MeshAlgos::Edge > edges =
4850 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4852 if ( myIsPreviewMode ) // fill a preview mesh with edges
4854 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4855 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4856 for ( size_t i = 0; i < edges.size(); ++i )
4858 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4859 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4860 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4861 if ( edges[i]._medium )
4863 xyz1.Set( edges[i]._medium );
4864 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4865 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4869 mesh->GetMeshDS()->AddEdge( n1, n2 );
4875 resultEdges->length( edges.size() );
4876 for ( size_t i = 0; i < edges.size(); ++i )
4878 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4879 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4880 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4883 SMESH_CATCH( SMESH::throwCorbaException );
4884 return resultEdges._retn();
4887 //=======================================================================
4888 //function : FindFreeBorders
4889 //purpose : Returns all or only closed FreeBorder's.
4890 //=======================================================================
4892 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4894 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4897 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4898 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4900 resBorders->length( foundFreeBordes.size() );
4901 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4903 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4904 SMESH::FreeBorder& bordOut = resBorders[i];
4905 bordOut.nodeIDs.length( bordNodes.size() );
4906 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4907 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4910 SMESH_CATCH( SMESH::throwCorbaException );
4912 return resBorders._retn();
4915 //=======================================================================
4916 //function : FillHole
4917 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4918 //=======================================================================
4920 SMESH::SMESH_Group_ptr
4921 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
4922 const char* theGroupName)
4926 if ( theHole.nodeIDs.length() < 4 )
4927 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4928 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4929 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4930 "First and last nodes must be same", SALOME::BAD_PARAM);
4932 SMESH_MeshAlgos::TFreeBorder bordNodes;
4933 bordNodes.resize( theHole.nodeIDs.length() );
4934 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4936 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4937 if ( !bordNodes[ iN ] )
4938 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4939 << " does not exist", SALOME::BAD_PARAM);
4944 // prepare a preview mesh
4945 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4946 SMDS_Mesh* meshDS = getMeshDS();
4947 if ( myIsPreviewMode )
4949 // copy faces sharing nodes of theHole
4950 TIDSortedElemSet holeFaces;
4951 previewMesh = getPreviewMesh( SMDSAbs_Face );
4952 for ( size_t i = 0; i < bordNodes.size(); ++i )
4954 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4955 while ( fIt->more() )
4957 const SMDS_MeshElement* face = fIt->next();
4958 if ( holeFaces.insert( face ).second )
4959 previewMesh->Copy( face );
4961 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4962 ASSERT( bordNodes[i] );
4964 meshDS = previewMesh->GetMeshDS();
4968 std::vector<const SMDS_MeshElement*> newFaces;
4969 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4971 if ( myIsPreviewMode )
4974 previewMesh->Clear();
4975 for ( size_t i = 0; i < newFaces.size(); ++i )
4976 previewMesh->Copy( newFaces[i] );
4980 // return new faces via a group
4981 SMESH::SMESH_Group_var group;
4982 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
4984 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4985 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
4987 SMESH::SMESH_GroupBase_var g = groups[ i ];
4988 if ( g->GetType() != SMESH::FACE ) continue;
4989 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
4990 if ( standalone->_is_nil() ) continue;
4991 CORBA::String_var name = g->GetName();
4992 if ( strcmp( theGroupName, name.in() ) == 0 )
4998 if ( group->_is_nil() )
4999 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5001 if ( !group->_is_nil() )
5003 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5004 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5005 for ( size_t i = 0; i < newFaces.size(); ++i )
5006 grpDS->Add( newFaces[ i ]);
5011 getEditor().ClearLastCreated();
5012 SMESH_SequenceOfElemPtr& aSeq =
5013 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5014 aSeq.swap( newFaces );
5017 if ( group->_is_nil() ) pyDump << "_group = ";
5018 else pyDump << group << " = ";
5019 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5021 return group._retn();
5024 SMESH_CATCH( SMESH::throwCorbaException );
5026 return SMESH::SMESH_Group::_nil();
5029 //=======================================================================
5030 //function : convError
5032 //=======================================================================
5034 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5036 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5040 RETCASE( SEW_BORDER1_NOT_FOUND );
5041 RETCASE( SEW_BORDER2_NOT_FOUND );
5042 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5043 RETCASE( SEW_BAD_SIDE_NODES );
5044 RETCASE( SEW_VOLUMES_TO_SPLIT );
5045 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5046 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5047 RETCASE( SEW_BAD_SIDE1_NODES );
5048 RETCASE( SEW_BAD_SIDE2_NODES );
5049 RETCASE( SEW_INTERNAL_ERROR );
5051 return SMESH::SMESH_MeshEditor::SEW_OK;
5054 //=======================================================================
5056 * Returns groups of FreeBorder's coincident within the given tolerance.
5057 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5058 * to free borders being compared is used.
5060 //=======================================================================
5062 SMESH::CoincidentFreeBorders*
5063 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5065 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5069 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5070 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5072 // copy free borders
5073 aCFB->borders.length( cfb._borders.size() );
5074 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5076 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5077 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5078 aBRD.nodeIDs.length( nodes.size() );
5079 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5080 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5083 // copy coincident parts
5084 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5085 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5087 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5088 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5089 aGRP.length( grp.size() );
5090 for ( size_t iP = 0; iP < grp.size(); ++iP )
5092 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5093 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5094 aPART.border = part._border;
5095 aPART.node1 = part._node1;
5096 aPART.node2 = part._node2;
5097 aPART.nodeLast = part._nodeLast;
5100 SMESH_CATCH( SMESH::doNothing );
5102 TPythonDump() << "CoincidentFreeBorders = "
5103 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5105 return aCFB._retn();
5108 //=======================================================================
5110 * Sew FreeBorder's of each group
5112 //=======================================================================
5114 CORBA::Short SMESH_MeshEditor_i::
5115 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5116 CORBA::Boolean createPolygons,
5117 CORBA::Boolean createPolyhedra)
5119 CORBA::Short nbSewed = 0;
5121 SMESH_MeshAlgos::TFreeBorderVec groups;
5122 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5124 // check the input and collect nodes
5125 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5127 borderNodes.clear();
5128 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5129 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5131 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5132 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5133 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5135 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5137 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5138 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5139 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5140 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5141 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5142 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5144 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5145 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5146 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5147 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5149 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5151 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5153 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5155 borderNodes.push_back( n1 );
5156 borderNodes.push_back( n2 );
5157 borderNodes.push_back( n3 );
5159 groups.push_back( borderNodes );
5162 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5163 // to get nodes that replace other nodes during merge we create 0D elements
5164 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5167 vector< const SMDS_MeshElement* > tmp0Delems;
5168 for ( size_t i = 0; i < groups.size(); ++i )
5170 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5171 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5173 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5175 tmp0Delems.push_back( it0D->next() );
5177 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5181 // cout << endl << "INIT" << endl;
5182 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5184 // cout << i << " ";
5185 // if ( i % 3 == 0 ) cout << "^ ";
5186 // tmp0Delems[i]->GetNode(0)->Print( cout );
5191 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5193 for ( size_t i = 0; i < groups.size(); ++i )
5195 bool isBordToBord = true;
5196 bool groupSewed = false;
5197 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5198 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5200 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5201 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5202 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5204 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5205 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5206 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5208 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5211 // TIDSortedElemSet emptySet, avoidSet;
5212 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5214 // cout << "WRONG 2nd 1" << endl;
5215 // n0->Print( cout );
5216 // n1->Print( cout );
5218 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5220 // cout << "WRONG 2nd 2" << endl;
5221 // n3->Print( cout );
5222 // n4->Print( cout );
5225 if ( !isBordToBord )
5227 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5228 n2 = 0; // and n2 is not used
5230 // 1st border moves to 2nd
5231 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5233 /*2ndIsFreeBorder=*/ isBordToBord,
5234 createPolygons, createPolyhedra);
5235 groupSewed = ( res == ok );
5237 isBordToBord = false;
5238 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5239 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5241 // cout << t << " ";
5242 // if ( t % 3 == 0 ) cout << "^ ";
5243 // tmp0Delems[t]->GetNode(0)->Print( cout );
5246 i0D += nodes.size();
5247 nbSewed += groupSewed;
5250 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5251 << freeBorders << ", "
5252 << createPolygons << ", "
5253 << createPolyhedra << " )";
5255 SMESH_CATCH( SMESH::doNothing );
5257 declareMeshModified( /*isReComputeSafe=*/false );
5259 // remove tmp 0D elements
5261 set< const SMDS_MeshElement* > removed0D;
5262 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5264 if ( removed0D.insert( tmp0Delems[i] ).second )
5265 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5267 SMESH_CATCH( SMESH::throwCorbaException );
5272 //=======================================================================
5273 //function : SewFreeBorders
5275 //=======================================================================
5277 SMESH::SMESH_MeshEditor::Sew_Error
5278 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5279 CORBA::Long SecondNodeID1,
5280 CORBA::Long LastNodeID1,
5281 CORBA::Long FirstNodeID2,
5282 CORBA::Long SecondNodeID2,
5283 CORBA::Long LastNodeID2,
5284 CORBA::Boolean CreatePolygons,
5285 CORBA::Boolean CreatePolyedrs)
5290 SMESHDS_Mesh* aMesh = getMeshDS();
5292 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5293 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5294 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5295 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5296 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5297 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5299 if (!aBorderFirstNode ||
5300 !aBorderSecondNode||
5302 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5303 if (!aSide2FirstNode ||
5304 !aSide2SecondNode ||
5306 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5308 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5309 << FirstNodeID1 << ", "
5310 << SecondNodeID1 << ", "
5311 << LastNodeID1 << ", "
5312 << FirstNodeID2 << ", "
5313 << SecondNodeID2 << ", "
5314 << LastNodeID2 << ", "
5315 << CreatePolygons<< ", "
5316 << CreatePolyedrs<< " )";
5318 SMESH::SMESH_MeshEditor::Sew_Error error =
5319 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5330 declareMeshModified( /*isReComputeSafe=*/false );
5333 SMESH_CATCH( SMESH::throwCorbaException );
5334 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5338 //=======================================================================
5339 //function : SewConformFreeBorders
5341 //=======================================================================
5343 SMESH::SMESH_MeshEditor::Sew_Error
5344 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5345 CORBA::Long SecondNodeID1,
5346 CORBA::Long LastNodeID1,
5347 CORBA::Long FirstNodeID2,
5348 CORBA::Long SecondNodeID2)
5353 SMESHDS_Mesh* aMesh = getMeshDS();
5355 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5356 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5357 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5358 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5359 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5360 const SMDS_MeshNode* aSide2ThirdNode = 0;
5362 if (!aBorderFirstNode ||
5363 !aBorderSecondNode||
5365 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5366 if (!aSide2FirstNode ||
5368 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5370 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5371 << FirstNodeID1 << ", "
5372 << SecondNodeID1 << ", "
5373 << LastNodeID1 << ", "
5374 << FirstNodeID2 << ", "
5375 << SecondNodeID2 << " )";
5377 SMESH::SMESH_MeshEditor::Sew_Error error =
5378 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5387 declareMeshModified( /*isReComputeSafe=*/false );
5390 SMESH_CATCH( SMESH::throwCorbaException );
5391 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5395 //=======================================================================
5396 //function : SewBorderToSide
5398 //=======================================================================
5400 SMESH::SMESH_MeshEditor::Sew_Error
5401 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5402 CORBA::Long SecondNodeIDOnFreeBorder,
5403 CORBA::Long LastNodeIDOnFreeBorder,
5404 CORBA::Long FirstNodeIDOnSide,
5405 CORBA::Long LastNodeIDOnSide,
5406 CORBA::Boolean CreatePolygons,
5407 CORBA::Boolean CreatePolyedrs)
5412 SMESHDS_Mesh* aMesh = getMeshDS();
5414 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5415 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5416 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5417 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5418 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5419 const SMDS_MeshNode* aSide2ThirdNode = 0;
5421 if (!aBorderFirstNode ||
5422 !aBorderSecondNode||
5424 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5425 if (!aSide2FirstNode ||
5427 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5429 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5430 << FirstNodeIDOnFreeBorder << ", "
5431 << SecondNodeIDOnFreeBorder << ", "
5432 << LastNodeIDOnFreeBorder << ", "
5433 << FirstNodeIDOnSide << ", "
5434 << LastNodeIDOnSide << ", "
5435 << CreatePolygons << ", "
5436 << CreatePolyedrs << ") ";
5438 SMESH::SMESH_MeshEditor::Sew_Error error =
5439 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5449 declareMeshModified( /*isReComputeSafe=*/false );
5452 SMESH_CATCH( SMESH::throwCorbaException );
5453 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5457 //=======================================================================
5458 //function : SewSideElements
5460 //=======================================================================
5462 SMESH::SMESH_MeshEditor::Sew_Error
5463 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5464 const SMESH::long_array& IDsOfSide2Elements,
5465 CORBA::Long NodeID1OfSide1ToMerge,
5466 CORBA::Long NodeID1OfSide2ToMerge,
5467 CORBA::Long NodeID2OfSide1ToMerge,
5468 CORBA::Long NodeID2OfSide2ToMerge)
5473 SMESHDS_Mesh* aMesh = getMeshDS();
5475 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5476 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5477 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5478 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5480 if (!aFirstNode1ToMerge ||
5481 !aFirstNode2ToMerge )
5482 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5483 if (!aSecondNode1ToMerge||
5484 !aSecondNode2ToMerge)
5485 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5487 TIDSortedElemSet aSide1Elems, aSide2Elems;
5488 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5489 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5491 TPythonDump() << "error = " << this << ".SewSideElements( "
5492 << IDsOfSide1Elements << ", "
5493 << IDsOfSide2Elements << ", "
5494 << NodeID1OfSide1ToMerge << ", "
5495 << NodeID1OfSide2ToMerge << ", "
5496 << NodeID2OfSide1ToMerge << ", "
5497 << NodeID2OfSide2ToMerge << ")";
5499 SMESH::SMESH_MeshEditor::Sew_Error error =
5500 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5503 aSecondNode1ToMerge,
5504 aSecondNode2ToMerge));
5506 declareMeshModified( /*isReComputeSafe=*/false );
5509 SMESH_CATCH( SMESH::throwCorbaException );
5510 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5513 //================================================================================
5515 * \brief Set new nodes for given element
5516 * \param ide - element id
5517 * \param newIDs - new node ids
5518 * \retval CORBA::Boolean - true if result is OK
5520 //================================================================================
5522 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5523 const SMESH::long_array& newIDs)
5528 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5529 if ( !elem ) return false;
5531 int nbn = newIDs.length();
5532 vector<const SMDS_MeshNode*> aNodes(nbn);
5533 for ( int i = 0; i < nbn; i++ ) {
5534 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5537 aNodes[ i ] = aNode;
5539 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5540 << ide << ", " << newIDs << " )";
5542 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5544 declareMeshModified( /*isReComputeSafe=*/ !res );
5548 SMESH_CATCH( SMESH::throwCorbaException );
5552 //=======================================================================
5554 * \brief Makes a part of the mesh quadratic or bi-quadratic
5556 //=======================================================================
5558 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5559 CORBA::Boolean theToBiQuad,
5560 SMESH::SMESH_IDSource_ptr theObject)
5565 TIDSortedElemSet elems;
5567 if ( !( elemsOK = CORBA::is_nil( theObject )))
5569 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5570 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5574 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5575 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5577 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5578 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5580 declareMeshModified( /*isReComputeSafe=*/false );
5583 SMESH_CATCH( SMESH::throwCorbaException );
5586 //=======================================================================
5587 //function : ConvertFromQuadratic
5589 //=======================================================================
5591 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5596 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5597 TPythonDump() << this << ".ConvertFromQuadratic()";
5598 declareMeshModified( /*isReComputeSafe=*/!isDone );
5601 SMESH_CATCH( SMESH::throwCorbaException );
5605 //=======================================================================
5606 //function : ConvertToQuadratic
5608 //=======================================================================
5610 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5612 convertToQuadratic( theForce3d, false );
5613 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5616 //================================================================================
5618 * \brief Makes a part of the mesh quadratic
5620 //================================================================================
5622 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5623 SMESH::SMESH_IDSource_ptr theObject)
5625 convertToQuadratic( theForce3d, false, theObject );
5626 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5629 //================================================================================
5631 * \brief Makes a part of the mesh bi-quadratic
5633 //================================================================================
5635 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5636 SMESH::SMESH_IDSource_ptr theObject)
5638 convertToQuadratic( theForce3d, true, theObject );
5639 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5642 //================================================================================
5644 * \brief Makes a part of the mesh linear
5646 //================================================================================
5648 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5655 TIDSortedElemSet elems;
5656 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5658 if ( elems.empty() )
5660 ConvertFromQuadratic();
5662 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5664 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5668 getEditor().ConvertFromQuadratic(elems);
5671 declareMeshModified( /*isReComputeSafe=*/false );
5673 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5675 SMESH_CATCH( SMESH::throwCorbaException );
5678 //=======================================================================
5679 //function : makeMesh
5680 //purpose : create a named imported mesh
5681 //=======================================================================
5683 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5685 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5686 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5687 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5688 gen->SetName( meshSO, theMeshName, "Mesh" );
5689 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5691 return mesh._retn();
5694 //=======================================================================
5695 //function : dumpGroupsList
5697 //=======================================================================
5699 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5700 const SMESH::ListOfGroups * theGroupList)
5702 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5703 if ( isDumpGroupList )
5704 theDumpPython << theGroupList << " = ";
5707 //================================================================================
5709 \brief Generates the unique group name.
5710 \param thePrefix name prefix
5713 //================================================================================
5715 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5717 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5718 set<std::string> groupNames;
5720 // Get existing group names
5721 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5722 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5723 if (CORBA::is_nil(aGroup))
5726 CORBA::String_var name = aGroup->GetName();
5727 groupNames.insert( name.in() );
5731 std::string name = thePrefix;
5734 while (!groupNames.insert(name).second)
5735 name = SMESH_Comment( thePrefix ) << "_" << index++;
5740 //================================================================================
5742 * \brief Prepare SMESH_IDSource for work
5744 //================================================================================
5746 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5748 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5750 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5751 filter->SetMesh( mesh );
5754 //================================================================================
5756 * \brief Retrieve elements of given type from SMESH_IDSource
5758 //================================================================================
5760 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5761 const SMESHDS_Mesh* theMeshDS,
5762 TIDSortedElemSet& theElemSet,
5763 const SMDSAbs_ElementType theType,
5764 const bool emptyIfIsMesh,
5765 IDSource_Error* error)
5768 if ( error ) *error = IDSource_OK;
5770 if ( CORBA::is_nil( theIDSource ))
5772 if ( error ) *error = IDSource_INVALID;
5775 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5777 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5778 *error = IDSource_EMPTY;
5781 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5783 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5784 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5785 if ( mesh_i && mesh_i != myMesh_i )
5788 *error = IDSource_INVALID;
5792 prepareIdSource( theIDSource );
5793 SMESH::long_array_var anIDs = theIDSource->GetIDs();
5794 if ( anIDs->length() == 0 )
5796 if ( error ) *error = IDSource_EMPTY;
5799 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5800 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5802 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5804 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5808 if ( error ) *error = IDSource_INVALID;
5814 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5815 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5817 if ( error ) *error = IDSource_INVALID;
5824 //================================================================================
5826 * \brief Duplicates given elements, i.e. creates new elements based on the
5827 * same nodes as the given ones.
5828 * \param theElements - container of elements to duplicate.
5829 * \param theGroupName - a name of group to contain the generated elements.
5830 * If a group with such a name already exists, the new elements
5831 * are added to the existing group, else a new group is created.
5832 * If \a theGroupName is empty, new elements are not added
5834 * \return a group where the new elements are added. NULL if theGroupName == "".
5837 //================================================================================
5839 SMESH::SMESH_Group_ptr
5840 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5841 const char* theGroupName)
5843 SMESH::SMESH_Group_var newGroup;
5850 TIDSortedElemSet elems;
5851 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5853 getEditor().DoubleElements( elems );
5855 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5858 SMESH::ElementType type =
5859 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5860 // find existing group
5861 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5862 for ( size_t i = 0; i < groups->length(); ++i )
5863 if ( groups[i]->GetType() == type )
5865 CORBA::String_var name = groups[i]->GetName();
5866 if ( strcmp( name, theGroupName ) == 0 ) {
5867 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5871 // create a new group
5872 if ( newGroup->_is_nil() )
5873 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5875 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5877 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5878 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5879 for ( size_t i = 0; i < aSeq.size(); i++ )
5880 groupDS->SMDSGroup().Add( aSeq[i] );
5885 if ( !newGroup->_is_nil() )
5886 pyDump << newGroup << " = ";
5887 pyDump << this << ".DoubleElements( "
5888 << theElements << ", " << "'" << theGroupName <<"')";
5890 SMESH_CATCH( SMESH::throwCorbaException );
5892 return newGroup._retn();
5895 //================================================================================
5897 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5898 \param theNodes - identifiers of nodes to be doubled
5899 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5900 nodes. If list of element identifiers is empty then nodes are doubled but
5901 they not assigned to elements
5902 \return TRUE if operation has been completed successfully, FALSE otherwise
5903 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5905 //================================================================================
5907 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5908 const SMESH::long_array& theModifiedElems )
5913 list< int > aListOfNodes;
5915 for ( i = 0, n = theNodes.length(); i < n; i++ )
5916 aListOfNodes.push_back( theNodes[ i ] );
5918 list< int > aListOfElems;
5919 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5920 aListOfElems.push_back( theModifiedElems[ i ] );
5922 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5924 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5926 // Update Python script
5927 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5931 SMESH_CATCH( SMESH::throwCorbaException );
5935 //================================================================================
5937 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5938 This method provided for convenience works as DoubleNodes() described above.
5939 \param theNodeId - identifier of node to be doubled.
5940 \param theModifiedElems - identifiers of elements to be updated.
5941 \return TRUE if operation has been completed successfully, FALSE otherwise
5942 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5944 //================================================================================
5946 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long theNodeId,
5947 const SMESH::long_array& theModifiedElems )
5950 SMESH::long_array_var aNodes = new SMESH::long_array;
5951 aNodes->length( 1 );
5952 aNodes[ 0 ] = theNodeId;
5954 TPythonDump pyDump; // suppress dump by the next line
5956 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5958 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5962 SMESH_CATCH( SMESH::throwCorbaException );
5966 //================================================================================
5968 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5969 This method provided for convenience works as DoubleNodes() described above.
5970 \param theNodes - group of nodes to be doubled.
5971 \param theModifiedElems - group of elements to be updated.
5972 \return TRUE if operation has been completed successfully, FALSE otherwise
5973 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5975 //================================================================================
5977 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5978 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5981 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5984 SMESH::long_array_var aNodes = theNodes->GetListOfID();
5985 SMESH::long_array_var aModifiedElems;
5986 if ( !CORBA::is_nil( theModifiedElems ) )
5987 aModifiedElems = theModifiedElems->GetListOfID();
5989 aModifiedElems = new SMESH::long_array;
5991 TPythonDump pyDump; // suppress dump by the next line
5993 bool done = DoubleNodes( aNodes, aModifiedElems );
5995 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5999 SMESH_CATCH( SMESH::throwCorbaException );
6003 //================================================================================
6005 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6006 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6007 * \param theNodes - group of nodes to be doubled.
6008 * \param theModifiedElems - group of elements to be updated.
6009 * \return a new group with newly created nodes
6010 * \sa DoubleNodeGroup()
6012 //================================================================================
6014 SMESH::SMESH_Group_ptr
6015 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6016 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6019 SMESH::SMESH_Group_var aNewGroup;
6021 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6022 return aNewGroup._retn();
6025 SMESH::long_array_var aNodes = theNodes->GetListOfID();
6026 SMESH::long_array_var aModifiedElems;
6027 if ( !CORBA::is_nil( theModifiedElems ) )
6028 aModifiedElems = theModifiedElems->GetListOfID();
6030 aModifiedElems = new SMESH::long_array;
6031 aModifiedElems->length( 0 );
6034 TPythonDump pyDump; // suppress dump by the next line
6036 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6039 // Create group with newly created nodes
6040 SMESH::long_array_var anIds = GetLastCreatedNodes();
6041 if (anIds->length() > 0) {
6042 std::string anUnindexedName (theNodes->GetName());
6043 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6044 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6045 aNewGroup->Add(anIds);
6046 pyDump << aNewGroup << " = ";
6050 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6051 << theModifiedElems << " )";
6053 return aNewGroup._retn();
6055 SMESH_CATCH( SMESH::throwCorbaException );
6059 //================================================================================
6061 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6062 This method provided for convenience works as DoubleNodes() described above.
6063 \param theNodes - list of groups of nodes to be doubled
6064 \param theModifiedElems - list of groups of elements to be updated.
6065 \return TRUE if operation has been completed successfully, FALSE otherwise
6066 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6068 //================================================================================
6070 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6071 const SMESH::ListOfGroups& theModifiedElems )
6076 std::list< int > aNodes;
6078 for ( i = 0, n = theNodes.length(); i < n; i++ )
6080 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6081 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6083 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6084 for ( j = 0, m = aCurr->length(); j < m; j++ )
6085 aNodes.push_back( aCurr[ j ] );
6089 std::list< int > anElems;
6090 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6092 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6093 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6095 SMESH::long_array_var aCurr = aGrp->GetListOfID();
6096 for ( j = 0, m = aCurr->length(); j < m; j++ )
6097 anElems.push_back( aCurr[ j ] );
6101 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6103 declareMeshModified( /*isReComputeSafe=*/false );
6105 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6109 SMESH_CATCH( SMESH::throwCorbaException );
6113 //================================================================================
6115 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6116 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6117 * \param theNodes - group of nodes to be doubled.
6118 * \param theModifiedElems - group of elements to be updated.
6119 * \return a new group with newly created nodes
6120 * \sa DoubleNodeGroups()
6122 //================================================================================
6124 SMESH::SMESH_Group_ptr
6125 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6126 const SMESH::ListOfGroups& theModifiedElems )
6128 SMESH::SMESH_Group_var aNewGroup;
6130 TPythonDump pyDump; // suppress dump by the next line
6132 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6136 // Create group with newly created nodes
6137 SMESH::long_array_var anIds = GetLastCreatedNodes();
6138 if (anIds->length() > 0) {
6139 std::string anUnindexedName (theNodes[0]->GetName());
6140 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6141 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6142 aNewGroup->Add(anIds);
6143 pyDump << aNewGroup << " = ";
6147 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6148 << theModifiedElems << " )";
6150 return aNewGroup._retn();
6154 //================================================================================
6156 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6157 \param theElems - the list of elements (edges or faces) to be replicated
6158 The nodes for duplication could be found from these elements
6159 \param theNodesNot - list of nodes to NOT replicate
6160 \param theAffectedElems - the list of elements (cells and edges) to which the
6161 replicated nodes should be associated to.
6162 \return TRUE if operation has been completed successfully, FALSE otherwise
6163 \sa DoubleNodeGroup(), DoubleNodeGroups()
6165 //================================================================================
6167 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6168 const SMESH::long_array& theNodesNot,
6169 const SMESH::long_array& theAffectedElems )
6174 SMESHDS_Mesh* aMeshDS = getMeshDS();
6175 TIDSortedElemSet anElems, aNodes, anAffected;
6176 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6177 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6178 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6180 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6182 // Update Python script
6183 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6184 << theNodesNot << ", " << theAffectedElems << " )";
6186 declareMeshModified( /*isReComputeSafe=*/false );
6189 SMESH_CATCH( SMESH::throwCorbaException );
6193 //================================================================================
6195 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6196 \param theElems - the list of elements (edges or faces) to be replicated
6197 The nodes for duplication could be found from these elements
6198 \param theNodesNot - list of nodes to NOT replicate
6199 \param theShape - shape to detect affected elements (element which geometric center
6200 located on or inside shape).
6201 The replicated nodes should be associated to affected elements.
6202 \return TRUE if operation has been completed successfully, FALSE otherwise
6203 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6205 //================================================================================
6207 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6208 const SMESH::long_array& theNodesNot,
6209 GEOM::GEOM_Object_ptr theShape )
6215 SMESHDS_Mesh* aMeshDS = getMeshDS();
6216 TIDSortedElemSet anElems, aNodes;
6217 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6218 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6220 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6221 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6223 // Update Python script
6224 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6225 << theNodesNot << ", " << theShape << " )";
6227 declareMeshModified( /*isReComputeSafe=*/false );
6230 SMESH_CATCH( SMESH::throwCorbaException );
6234 //================================================================================
6236 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6237 \param theElems - group of of elements (edges or faces) to be replicated
6238 \param theNodesNot - group of nodes not to replicated
6239 \param theAffectedElems - group of elements to which the replicated nodes
6240 should be associated to.
6241 \return TRUE if operation has been completed successfully, FALSE otherwise
6242 \sa DoubleNodes(), DoubleNodeGroups()
6244 //================================================================================
6247 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6248 SMESH::SMESH_GroupBase_ptr theNodesNot,
6249 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6252 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6258 SMESHDS_Mesh* aMeshDS = getMeshDS();
6259 TIDSortedElemSet anElems, aNodes, anAffected;
6260 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6261 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6262 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6264 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6266 // Update Python script
6267 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6268 << theNodesNot << ", " << theAffectedElems << " )";
6270 declareMeshModified( /*isReComputeSafe=*/false );
6273 SMESH_CATCH( SMESH::throwCorbaException );
6277 //================================================================================
6279 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6280 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6281 * \param theElems - group of of elements (edges or faces) to be replicated
6282 * \param theNodesNot - group of nodes not to replicated
6283 * \param theAffectedElems - group of elements to which the replicated nodes
6284 * should be associated to.
6285 * \return a new group with newly created elements
6286 * \sa DoubleNodeElemGroup()
6288 //================================================================================
6290 SMESH::SMESH_Group_ptr
6291 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6292 SMESH::SMESH_GroupBase_ptr theNodesNot,
6293 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6296 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6300 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6301 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6303 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6305 << theNodesNot << ", "
6306 << theAffectedElems << " )";
6308 return elemGroup._retn();
6311 //================================================================================
6313 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6314 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6315 * \param theElems - group of of elements (edges or faces) to be replicated
6316 * \param theNodesNot - group of nodes not to replicated
6317 * \param theAffectedElems - group of elements to which the replicated nodes
6318 * should be associated to.
6319 * \return a new group with newly created elements
6320 * \sa DoubleNodeElemGroup()
6322 //================================================================================
6324 SMESH::ListOfGroups*
6325 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6326 SMESH::SMESH_GroupBase_ptr theNodesNot,
6327 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6328 CORBA::Boolean theElemGroupNeeded,
6329 CORBA::Boolean theNodeGroupNeeded)
6332 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6333 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6334 aTwoGroups->length( 2 );
6336 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6337 return aTwoGroups._retn();
6342 SMESHDS_Mesh* aMeshDS = getMeshDS();
6343 TIDSortedElemSet anElems, aNodes, anAffected;
6344 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6345 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6346 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6349 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6351 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6357 // Create group with newly created elements
6358 CORBA::String_var elemGroupName = theElems->GetName();
6359 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6360 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6362 SMESH::long_array_var anIds = GetLastCreatedElems();
6363 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6364 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6365 aNewElemGroup->Add(anIds);
6367 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6369 SMESH::long_array_var anIds = GetLastCreatedNodes();
6370 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6371 aNewNodeGroup->Add(anIds);
6375 // Update Python script
6378 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6379 else pyDump << aNewElemGroup << ", ";
6380 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6381 else pyDump << aNewNodeGroup << " ] = ";
6383 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6384 << theNodesNot << ", "
6385 << theAffectedElems << ", "
6386 << theElemGroupNeeded << ", "
6387 << theNodeGroupNeeded <<" )";
6389 aTwoGroups[0] = aNewElemGroup._retn();
6390 aTwoGroups[1] = aNewNodeGroup._retn();
6391 return aTwoGroups._retn();
6393 SMESH_CATCH( SMESH::throwCorbaException );
6397 //================================================================================
6399 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6400 \param theElems - group of of elements (edges or faces) to be replicated
6401 \param theNodesNot - group of nodes not to replicated
6402 \param theShape - shape to detect affected elements (element which geometric center
6403 located on or inside shape).
6404 The replicated nodes should be associated to affected elements.
6405 \return TRUE if operation has been completed successfully, FALSE otherwise
6406 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6408 //================================================================================
6411 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6412 SMESH::SMESH_GroupBase_ptr theNodesNot,
6413 GEOM::GEOM_Object_ptr theShape )
6416 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6422 SMESHDS_Mesh* aMeshDS = getMeshDS();
6423 TIDSortedElemSet anElems, aNodes, anAffected;
6424 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6425 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6427 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6428 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6431 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6433 // Update Python script
6434 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6435 << theNodesNot << ", " << theShape << " )";
6438 SMESH_CATCH( SMESH::throwCorbaException );
6442 //================================================================================
6444 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6445 * \param [in] theGrpList - groups
6446 * \param [in] theMeshDS - mesh
6447 * \param [out] theElemSet - set of elements
6448 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6450 //================================================================================
6452 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6453 SMESHDS_Mesh* theMeshDS,
6454 TIDSortedElemSet& theElemSet,
6455 const bool theIsNodeGrp)
6457 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6459 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6460 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6461 : aGrp->GetType() != SMESH::NODE ) )
6463 SMESH::long_array_var anIDs = aGrp->GetIDs();
6464 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6469 //================================================================================
6471 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6472 This method provided for convenience works as DoubleNodes() described above.
6473 \param theElems - list of groups of elements (edges or faces) to be replicated
6474 \param theNodesNot - list of groups of nodes not to replicated
6475 \param theAffectedElems - group of elements to which the replicated nodes
6476 should be associated to.
6477 \return TRUE if operation has been completed successfully, FALSE otherwise
6478 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6480 //================================================================================
6483 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6484 const SMESH::ListOfGroups& theNodesNot,
6485 const SMESH::ListOfGroups& theAffectedElems)
6491 SMESHDS_Mesh* aMeshDS = getMeshDS();
6492 TIDSortedElemSet anElems, aNodes, anAffected;
6493 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6494 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6495 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6497 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6499 // Update Python script
6500 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6501 << &theNodesNot << ", " << &theAffectedElems << " )";
6503 declareMeshModified( /*isReComputeSafe=*/false );
6506 SMESH_CATCH( SMESH::throwCorbaException );
6510 //================================================================================
6512 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6513 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6514 \param theElems - list of groups of elements (edges or faces) to be replicated
6515 \param theNodesNot - list of groups of nodes not to replicated
6516 \param theAffectedElems - group of elements to which the replicated nodes
6517 should be associated to.
6518 * \return a new group with newly created elements
6519 * \sa DoubleNodeElemGroups()
6521 //================================================================================
6523 SMESH::SMESH_Group_ptr
6524 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6525 const SMESH::ListOfGroups& theNodesNot,
6526 const SMESH::ListOfGroups& theAffectedElems)
6529 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6533 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6534 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6536 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6538 << theNodesNot << ", "
6539 << theAffectedElems << " )";
6541 return elemGroup._retn();
6544 //================================================================================
6546 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6547 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6548 \param theElems - list of groups of elements (edges or faces) to be replicated
6549 \param theNodesNot - list of groups of nodes not to replicated
6550 \param theAffectedElems - group of elements to which the replicated nodes
6551 should be associated to.
6552 * \return a new group with newly created elements
6553 * \sa DoubleNodeElemGroups()
6555 //================================================================================
6557 SMESH::ListOfGroups*
6558 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6559 const SMESH::ListOfGroups& theNodesNot,
6560 const SMESH::ListOfGroups& theAffectedElems,
6561 CORBA::Boolean theElemGroupNeeded,
6562 CORBA::Boolean theNodeGroupNeeded)
6565 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6566 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6567 aTwoGroups->length( 2 );
6572 SMESHDS_Mesh* aMeshDS = getMeshDS();
6573 TIDSortedElemSet anElems, aNodes, anAffected;
6574 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6575 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6576 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6578 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6580 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6585 // Create group with newly created elements
6586 CORBA::String_var elemGroupName = theElems[0]->GetName();
6587 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6588 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6590 SMESH::long_array_var anIds = GetLastCreatedElems();
6591 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6592 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6593 aNewElemGroup->Add(anIds);
6595 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6597 SMESH::long_array_var anIds = GetLastCreatedNodes();
6598 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6599 aNewNodeGroup->Add(anIds);
6603 // Update Python script
6606 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6607 else pyDump << aNewElemGroup << ", ";
6608 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6609 else pyDump << aNewNodeGroup << " ] = ";
6611 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6612 << &theNodesNot << ", "
6613 << &theAffectedElems << ", "
6614 << theElemGroupNeeded << ", "
6615 << theNodeGroupNeeded << " )";
6617 aTwoGroups[0] = aNewElemGroup._retn();
6618 aTwoGroups[1] = aNewNodeGroup._retn();
6619 return aTwoGroups._retn();
6621 SMESH_CATCH( SMESH::throwCorbaException );
6625 //================================================================================
6627 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6628 This method provided for convenience works as DoubleNodes() described above.
6629 \param theElems - list of groups of elements (edges or faces) to be replicated
6630 \param theNodesNot - list of groups of nodes not to replicated
6631 \param theShape - shape to detect affected elements (element which geometric center
6632 located on or inside shape).
6633 The replicated nodes should be associated to affected elements.
6634 \return TRUE if operation has been completed successfully, FALSE otherwise
6635 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6637 //================================================================================
6640 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6641 const SMESH::ListOfGroups& theNodesNot,
6642 GEOM::GEOM_Object_ptr theShape )
6648 SMESHDS_Mesh* aMeshDS = getMeshDS();
6649 TIDSortedElemSet anElems, aNodes;
6650 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6651 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6653 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6654 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6656 // Update Python script
6657 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6658 << &theNodesNot << ", " << theShape << " )";
6660 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6663 SMESH_CATCH( SMESH::throwCorbaException );
6667 //================================================================================
6669 \brief Identify the elements that will be affected by node duplication (actual
6670 duplication is not performed.
6671 This method is the first step of DoubleNodeElemGroupsInRegion.
6672 \param theElems - list of groups of elements (edges or faces) to be replicated
6673 \param theNodesNot - list of groups of nodes not to replicated
6674 \param theShape - shape to detect affected elements (element which geometric center
6675 located on or inside shape).
6676 The replicated nodes should be associated to affected elements.
6677 \return groups of affected elements
6678 \sa DoubleNodeElemGroupsInRegion()
6680 //================================================================================
6681 SMESH::ListOfGroups*
6682 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6683 const SMESH::ListOfGroups& theNodesNot,
6684 GEOM::GEOM_Object_ptr theShape )
6687 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6688 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6689 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6690 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6694 ::SMESH_MeshEditor aMeshEditor(myMesh);
6696 SMESHDS_Mesh* aMeshDS = getMeshDS();
6697 TIDSortedElemSet anElems, aNodes;
6698 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6699 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6700 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6702 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6703 TIDSortedElemSet anAffected;
6704 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6706 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6709 if ( aResult && anAffected.size() > 0 )
6711 SMESH::long_array_var volumeIds = new SMESH::long_array;
6712 SMESH::long_array_var faceIds = new SMESH::long_array;
6713 SMESH::long_array_var edgeIds = new SMESH::long_array;
6714 volumeIds->length( anAffected.size() );
6715 faceIds ->length( anAffected.size() );
6716 edgeIds ->length( anAffected.size() );
6721 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6722 for (; eIt != anAffected.end(); ++eIt)
6724 const SMDS_MeshElement* anElem = *eIt;
6725 int elemId = anElem->GetID();
6726 switch ( anElem->GetType() ) {
6727 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6728 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6729 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6733 volumeIds->length(ivol);
6734 faceIds->length(iface);
6735 edgeIds->length(iedge);
6740 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6741 GenerateGroupName("affectedVolumes").c_str());
6742 aNewVolumeGroup->Add(volumeIds);
6743 aListOfGroups->length( nbGroups+1 );
6744 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6748 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6749 GenerateGroupName("affectedFaces").c_str());
6750 aNewFaceGroup->Add(faceIds);
6751 aListOfGroups->length( nbGroups+1 );
6752 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6756 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6757 GenerateGroupName("affectedEdges").c_str());
6758 aNewEdgeGroup->Add(edgeIds);
6759 aListOfGroups->length( nbGroups+1 );
6760 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6764 // Update Python script
6766 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6767 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6769 return aListOfGroups._retn();
6771 SMESH_CATCH( SMESH::throwCorbaException );
6775 //================================================================================
6777 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6778 The created 2D mesh elements based on nodes of free faces of boundary volumes
6779 \return TRUE if operation has been completed successfully, FALSE otherwise
6781 //================================================================================
6783 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6788 bool aResult = getEditor().Make2DMeshFrom3D();
6790 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6792 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6795 SMESH_CATCH( SMESH::throwCorbaException );
6799 //================================================================================
6801 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6802 * The list of groups must contain at least two groups. The groups have to be disjoint:
6803 * no common element into two different groups.
6804 * The nodes of the internal faces at the boundaries of the groups are doubled.
6805 * Optionally, the internal faces are replaced by flat elements.
6806 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6807 * The flat elements are stored in groups of volumes.
6808 * These groups are named according to the position of the group in the list:
6809 * 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.
6810 * 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.
6811 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6812 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6813 * \param theDomains - list of groups of volumes
6814 * \param createJointElems - if TRUE, create the elements
6815 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6816 * the boundary between \a theDomains and the rest mesh
6817 * \return TRUE if operation has been completed successfully, FALSE otherwise
6819 //================================================================================
6822 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6823 CORBA::Boolean createJointElems,
6824 CORBA::Boolean onAllBoundaries )
6831 SMESHDS_Mesh* aMeshDS = getMeshDS();
6833 // MESSAGE("theDomains.length = "<<theDomains.length());
6834 if ( theDomains.length() <= 1 && !onAllBoundaries )
6835 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6837 vector<TIDSortedElemSet> domains;
6838 domains.resize( theDomains.length() );
6840 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6842 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6843 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6845 // if ( aGrp->GetType() != SMESH::VOLUME )
6846 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6847 SMESH::long_array_var anIDs = aGrp->GetIDs();
6848 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6852 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6853 // TODO publish the groups of flat elements in study
6855 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6857 // Update Python script
6858 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6859 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6861 SMESH_CATCH( SMESH::throwCorbaException );
6863 myMesh_i->CreateGroupServants(); // publish created groups if any
6868 //================================================================================
6870 * \brief Double nodes on some external faces and create flat elements.
6871 * Flat elements are mainly used by some types of mechanic calculations.
6873 * Each group of the list must be constituted of faces.
6874 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6875 * @param theGroupsOfFaces - list of groups of faces
6876 * @return TRUE if operation has been completed successfully, FALSE otherwise
6878 //================================================================================
6881 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6886 SMESHDS_Mesh* aMeshDS = getMeshDS();
6888 vector<TIDSortedElemSet> faceGroups;
6891 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6893 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6894 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6896 TIDSortedElemSet faceGroup;
6898 faceGroups.push_back(faceGroup);
6899 SMESH::long_array_var anIDs = aGrp->GetIDs();
6900 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6904 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6905 // TODO publish the groups of flat elements in study
6907 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6909 // Update Python script
6910 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6913 SMESH_CATCH( SMESH::throwCorbaException );
6917 //================================================================================
6919 * \brief Identify all the elements around a geom shape, get the faces delimiting
6922 * Build groups of volume to remove, groups of faces to replace on the skin of the
6923 * object, groups of faces to remove inside the object, (idem edges).
6924 * Build ordered list of nodes at the border of each group of faces to replace
6925 * (to be used to build a geom subshape).
6927 //================================================================================
6929 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6930 GEOM::GEOM_Object_ptr theShape,
6931 const char* groupName,
6932 const SMESH::double_array& theNodesCoords,
6933 SMESH::array_of_long_array_out GroupsOfNodes)
6938 std::vector<std::vector<int> > aListOfListOfNodes;
6939 ::SMESH_MeshEditor aMeshEditor( myMesh );
6941 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6942 if ( !theNodeSearcher )
6943 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6945 vector<double> nodesCoords;
6946 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6948 nodesCoords.push_back( theNodesCoords[i] );
6951 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6952 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6953 nodesCoords, aListOfListOfNodes);
6955 GroupsOfNodes = new SMESH::array_of_long_array;
6956 GroupsOfNodes->length( aListOfListOfNodes.size() );
6957 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6958 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6960 vector<int>& aListOfNodes = *llIt;
6961 vector<int>::iterator lIt = aListOfNodes.begin();;
6962 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6963 aGroup.length( aListOfNodes.size() );
6964 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6965 aGroup[ j ] = (*lIt);
6967 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6970 << ", '" << groupName << "', "
6971 << theNodesCoords << " )";
6973 SMESH_CATCH( SMESH::throwCorbaException );
6976 // issue 20749 ===================================================================
6978 * \brief Creates missing boundary elements
6979 * \param elements - elements whose boundary is to be checked
6980 * \param dimension - defines type of boundary elements to create
6981 * \param groupName - a name of group to store created boundary elements in,
6982 * "" means not to create the group
6983 * \param meshName - a name of new mesh to store created boundary elements in,
6984 * "" means not to create the new mesh
6985 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6986 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6987 * boundary elements will be copied into the new mesh
6988 * \param group - returns the create group, if any
6989 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6991 // ================================================================================
6993 SMESH::SMESH_Mesh_ptr
6994 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6995 SMESH::Bnd_Dimension dim,
6996 const char* groupName,
6997 const char* meshName,
6998 CORBA::Boolean toCopyElements,
6999 CORBA::Boolean toCopyExistingBondary,
7000 SMESH::SMESH_Group_out group)
7005 if ( dim > SMESH::BND_1DFROM2D )
7006 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7008 SMESHDS_Mesh* aMeshDS = getMeshDS();
7010 SMESH::SMESH_Mesh_var mesh_var;
7011 SMESH::SMESH_Group_var group_var;
7015 TIDSortedElemSet elements;
7016 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7017 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7021 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7022 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7024 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7026 // group of new boundary elements
7027 SMESH_Group* smesh_group = 0;
7028 if ( strlen(groupName) )
7030 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7031 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7032 smesh_group = group_i->GetSmeshGroup();
7036 getEditor().MakeBoundaryMesh( elements,
7037 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7041 toCopyExistingBondary);
7044 smesh_mesh->GetMeshDS()->Modified();
7047 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7049 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7050 if ( mesh_var->_is_nil() )
7051 pyDump << myMesh_i->_this() << ", ";
7053 pyDump << mesh_var << ", ";
7054 if ( group_var->_is_nil() )
7055 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7057 pyDump << group_var << " = ";
7058 pyDump << this << ".MakeBoundaryMesh( "
7060 << "SMESH." << dimName[int(dim)] << ", "
7061 << "'" << groupName << "', "
7062 << "'" << meshName<< "', "
7063 << toCopyElements << ", "
7064 << toCopyExistingBondary << ")";
7066 group = group_var._retn();
7067 return mesh_var._retn();
7069 SMESH_CATCH( SMESH::throwCorbaException );
7070 return SMESH::SMESH_Mesh::_nil();
7073 //================================================================================
7075 * \brief Creates missing boundary elements
7076 * \param dimension - defines type of boundary elements to create
7077 * \param groupName - a name of group to store all boundary elements in,
7078 * "" means not to create the group
7079 * \param meshName - a name of a new mesh, which is a copy of the initial
7080 * mesh + created boundary elements; "" means not to create the new mesh
7081 * \param toCopyAll - if true, the whole initial mesh will be copied into
7082 * the new mesh else only boundary elements will be copied into the new mesh
7083 * \param groups - optional groups of elements to make boundary around
7084 * \param mesh - returns the mesh where elements were added to
7085 * \param group - returns the created group, if any
7086 * \retval long - number of added boundary elements
7088 //================================================================================
7090 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7091 const char* groupName,
7092 const char* meshName,
7093 CORBA::Boolean toCopyAll,
7094 const SMESH::ListOfIDSources& groups,
7095 SMESH::SMESH_Mesh_out mesh,
7096 SMESH::SMESH_Group_out group)
7101 if ( dim > SMESH::BND_1DFROM2D )
7102 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7104 // separate groups belonging to this and other mesh
7105 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7106 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7107 groupsOfThisMesh ->length( groups.length() );
7108 groupsOfOtherMesh->length( groups.length() );
7109 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7110 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7112 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7113 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7114 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7116 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7117 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7118 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7120 groupsOfThisMesh->length( nbGroups );
7121 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7126 if ( nbGroupsOfOtherMesh > 0 )
7128 // process groups belonging to another mesh
7129 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7130 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7131 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7132 groupsOfOtherMesh, mesh, group );
7135 SMESH::SMESH_Mesh_var mesh_var;
7136 SMESH::SMESH_Group_var group_var;
7139 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7140 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7144 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7146 /*toCopyGroups=*/false,
7147 /*toKeepIDs=*/true);
7149 mesh_var = makeMesh(meshName);
7151 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7152 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7155 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7156 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7158 // group of boundary elements
7159 SMESH_Group* smesh_group = 0;
7160 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7161 if ( strlen( groupName ))
7163 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7164 group_var = mesh_i->CreateGroup( groupType, groupName );
7165 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7166 smesh_group = group_i->GetSmeshGroup();
7169 TIDSortedElemSet elements;
7171 if ( groups.length() > 0 )
7173 for ( int i = 0; i < nbGroups; ++i )
7176 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7178 SMESH::Bnd_Dimension bdim =
7179 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7180 nbAdded += getEditor().MakeBoundaryMesh( elements,
7181 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7184 /*toCopyElements=*/false,
7185 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7186 /*toAddExistingBondary=*/true,
7187 /*aroundElements=*/true);
7193 nbAdded += getEditor().MakeBoundaryMesh( elements,
7194 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7197 /*toCopyElements=*/false,
7198 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7199 /*toAddExistingBondary=*/true);
7201 tgtMesh->GetMeshDS()->Modified();
7203 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7205 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7206 pyDump << "nbAdded, ";
7207 if ( mesh_var->_is_nil() )
7208 pyDump << myMesh_i->_this() << ", ";
7210 pyDump << mesh_var << ", ";
7211 if ( group_var->_is_nil() )
7212 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7214 pyDump << group_var << " = ";
7215 pyDump << this << ".MakeBoundaryElements( "
7216 << "SMESH." << dimName[int(dim)] << ", "
7217 << "'" << groupName << "', "
7218 << "'" << meshName<< "', "
7219 << toCopyAll << ", "
7222 mesh = mesh_var._retn();
7223 group = group_var._retn();
7226 SMESH_CATCH( SMESH::throwCorbaException );
7230 //================================================================================
7232 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7233 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7234 * plane passing through pairs of points specified by each PolySegment structure.
7235 * If there are several paths connecting a pair of points, the shortest path is
7236 * selected by the module. Position of the cutting plane is defined by the two
7237 * points and an optional vector lying on the plane specified by a PolySegment.
7238 * By default the vector is defined by Mesh module as following. A middle point
7239 * of the two given points is computed. The middle point is projected to the mesh.
7240 * The vector goes from the middle point to the projection point. In case of planar
7241 * mesh, the vector is normal to the mesh.
7242 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7243 * Return the used vector and position of the middle point.
7244 * \param [in] groupName - optional name of a group where created mesh segments will
7247 //================================================================================
7249 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7250 const char* theGroupName)
7252 if ( theSegments.length() == 0 )
7253 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7254 if ( myMesh->NbFaces() == 0 )
7255 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7258 initData(/*deleteSearchers=*/false);
7260 SMESHDS_Group* groupDS = 0;
7261 SMESHDS_Mesh* meshDS = getMeshDS();
7262 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7264 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7265 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7266 while ( faceIt->more() )
7267 tmpMesh->Copy( faceIt->next() );
7268 meshDS = tmpMesh->GetMeshDS();
7270 else if ( theGroupName[0] ) // find/create a group of segments
7272 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7273 // while ( !groupDS && grpIt->more() )
7275 // SMESH_Group* group = grpIt->next();
7276 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7277 // strcmp( group->GetName(), theGroupName ) == 0 )
7279 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7284 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7286 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7287 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7291 // convert input polySegments
7292 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7293 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7295 SMESH::PolySegment& segIn = theSegments[ i ];
7296 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7297 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7298 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7299 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7300 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7301 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7304 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7307 segOut.myVector.SetCoord( segIn.vector.PS.x,
7309 segIn.vector.PS.z );
7312 // get a static ElementSearcher
7313 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7314 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7315 if ( !theElementSearcher )
7316 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7319 std::vector<const SMDS_MeshElement*> newEdges;
7320 std::vector<const SMDS_MeshNode*> newNodes;
7321 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7322 groupDS ? &groupDS->SMDSGroup() : 0,
7323 theElementSearcher );
7325 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7327 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7328 assign( newNodes.begin(), newNodes.end() );
7331 if ( myIsPreviewMode )
7333 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7335 SMESH::PolySegment& segOut = theSegments[ i ];
7336 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7337 segOut.vector.PS.x = segIn.myVector.X();
7338 segOut.vector.PS.y = segIn.myVector.Y();
7339 segOut.vector.PS.z = segIn.myVector.Z();
7344 TPythonDump() << "_segments = []";
7345 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7347 SMESH::PolySegment& segIn = theSegments[ i ];
7348 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7349 << segIn.node1ID1 << ", "
7350 << segIn.node1ID2 << ", "
7351 << segIn.node2ID1 << ", "
7352 << segIn.node2ID2 << ", "
7353 << "smeshBuilder.MakeDirStruct( "
7354 << segIn.vector.PS.x << ", "
7355 << segIn.vector.PS.y << ", "
7356 << segIn.vector.PS.z << ")))";
7358 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7361 SMESH_CATCH( SMESH::throwCorbaException );
7365 //================================================================================
7367 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7368 * The slot is constructed by cutting faces by cylindrical surfaces made
7369 * around each segment. Segments are expected to be created by MakePolyLine().
7370 * \return Edges located at the slot boundary
7372 //================================================================================
7374 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7375 CORBA::Double theWidth)
7377 if ( CORBA::is_nil( theSegments ) ||
7378 theSegments->GetType() != SMESH::EDGE )
7379 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7380 if ( myMesh->NbFaces() == 0 )
7381 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7383 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7386 initData(/*deleteSearchers=*/false);
7388 SMESHDS_Mesh* meshDS = getMeshDS();
7390 // get standalone face groups to be updated
7391 std::vector< SMDS_MeshGroup* > faceGroups;
7392 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7393 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7394 for ( ; grIt != allGroups.end(); ++grIt )
7395 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7396 if ( gr->GetType() == SMDSAbs_Face )
7397 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7399 std::vector< SMESH_MeshAlgos::Edge > edges =
7400 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7401 theWidth, meshDS, faceGroups );
7403 resultEdges->length( edges.size() );
7404 for ( size_t i = 0; i < edges.size(); ++i )
7406 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7407 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7408 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7412 SMESH_CATCH( SMESH::throwCorbaException );
7414 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7416 return resultEdges._retn();