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::smIdType_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( SMESH::smIdType i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( SMESH::smIdType i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::smIdType_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
528 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
530 if ( myIsPreviewMode || hasBadElems )
532 list<int> aNodesConnectivity;
533 typedef map<int, int> TNodesMap;
536 SMESHDS_Mesh* aMeshDS;
537 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
539 const list<const SMDS_MeshElement*>& badElems =
540 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
541 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
542 aMeshDS = aMeshPartDS.get();
545 aMeshDS = getEditor().GetMeshDS();
547 myPreviewData = new SMESH::MeshPreviewStruct();
548 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
551 SMDSAbs_ElementType previewType = SMDSAbs_All;
553 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
554 previewType = aPreviewMesh->myPreviewType;
555 switch ( previewType ) {
556 case SMDSAbs_Edge : break;
557 case SMDSAbs_Face : break;
558 case SMDSAbs_Volume: break;
560 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
564 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
566 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
568 while ( itMeshElems->more() ) {
569 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
570 SMDS_NodeIteratorPtr itElemNodes =
571 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
572 aMeshElem->interlacedNodesIterator() :
573 aMeshElem->nodeIterator() );
574 while ( itElemNodes->more() ) {
575 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
576 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::smIdType_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
621 SMESH::smIdType_array_var myLastCreatedNodes = new SMESH::smIdType_array();
623 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
624 myLastCreatedNodes->length( aSeq.size() );
625 for ( smIdType i = 0; i < aSeq.size(); i++)
626 myLastCreatedNodes[i] = aSeq[i]->GetID();
628 return myLastCreatedNodes._retn();
629 SMESH_CATCH( SMESH::throwCorbaException );
633 //================================================================================
635 * \brief Returns list of it's IDs of created elements
636 * \retval SMESH::long_array* - list of elements' ID
638 //================================================================================
640 SMESH::smIdType_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 SMESH::smIdType_array_var myLastCreatedElems = new SMESH::smIdType_array();
645 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
646 myLastCreatedElems->length( aSeq.size() );
647 for ( smIdType i = 0; i < aSeq.size(); i++ )
648 myLastCreatedElems[i] = aSeq[i]->GetID();
650 return myLastCreatedElems._retn();
651 SMESH_CATCH( SMESH::throwCorbaException );
655 //=======================================================================
656 //function : ClearLastCreated
657 //purpose : Clears sequences of last created elements and nodes
658 //=======================================================================
660 void SMESH_MeshEditor_i::ClearLastCreated()
663 getEditor().ClearLastCreated();
664 SMESH_CATCH( SMESH::throwCorbaException );
667 //=======================================================================
669 * Returns description of an error/warning occurred during the last operation
670 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
672 //=======================================================================
674 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
677 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
678 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
679 if ( errIn && !errIn->IsOK() )
681 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
682 errOut->comment = errIn->myComment.c_str();
683 errOut->subShapeID = -1;
684 errOut->hasBadMesh = errIn->HasBadElems();
689 errOut->subShapeID = -1;
690 errOut->hasBadMesh = false;
693 return errOut._retn();
694 SMESH_CATCH( SMESH::throwCorbaException );
698 //=======================================================================
699 //function : MakeIDSource
700 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
701 // Call UnRegister() as you fininsh using it!!
702 //=======================================================================
704 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
705 public virtual SALOME::GenericObj_i
707 SMESH::smIdType_array _ids;
708 SMESH::ElementType _type;
709 SMESH::SMESH_Mesh_ptr _mesh;
710 SMESH::smIdType_array* GetIDs() { return new SMESH::smIdType_array( _ids ); }
711 SMESH::smIdType_array* GetMeshInfo() { return 0; }
712 SMESH::smIdType_array* GetNbElementsByType()
714 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
715 aRes->length(SMESH::NB_ELEMENT_TYPES);
716 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
717 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
720 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
721 bool IsMeshInfoCorrect() { return true; }
722 SMESH::array_of_ElementType* GetTypes()
724 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
725 if ( _ids.length() > 0 ) {
729 return types._retn();
731 SALOMEDS::TMPFile* GetVtkUgStream()
733 SALOMEDS::TMPFile_var SeqFile;
734 return SeqFile._retn();
738 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::smIdType_array& ids,
739 SMESH::ElementType type)
741 _IDSource* idSrc = new _IDSource;
742 idSrc->_mesh = myMesh_i->_this();
745 if ( type == SMESH::ALL && ids.length() > 0 )
746 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
748 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
750 return anIDSourceVar._retn();
753 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
755 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
758 SMESH::smIdType* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
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::smIdType_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::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::RemoveOrphanNodes()
846 // Update Python script
847 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
849 // Create filter to find all orphan nodes
850 SMESH::Controls::Filter::TIdSequence seq;
851 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
852 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
854 // remove orphan nodes (if there are any)
855 list< 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 SMESH::smIdType 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 SMESH::smIdType SMESH_MeshEditor_i::Add0DElement(SMESH::smIdType 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 SMESH::smIdType SMESH_MeshEditor_i::AddBall(SMESH::smIdType 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 SMESH::smIdType SMESH_MeshEditor_i::AddEdge(const SMESH::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::AddFace(const SMESH::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::AddVolume(const SMESH::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::smIdType_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 SMESH::smIdType SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::smIdType_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::smIdType_array_var newElems = new SMESH::smIdType_array;
1276 newElems->length( elems0D.size() );
1277 TIDSortedElemSet::iterator eIt = elems0D.begin();
1278 for ( smIdType 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(SMESH::smIdType 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(SMESH::smIdType 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(SMESH::smIdType 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(SMESH::smIdType 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(SMESH::smIdType 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(SMESH::smIdType NodeID1,
1515 SMESH::smIdType 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(SMESH::smIdType NodeID1,
1545 SMESH::smIdType 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::smIdType_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::smIdType_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::smIdType_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::smIdType_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::smIdType_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::smIdType_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 declareMeshModified( /*isReComputeSafe=*/false );
1937 SMESH_CATCH( SMESH::throwCorbaException );
1940 //=============================================================================
1942 * \brief Split quadrangles into triangles.
1944 //=============================================================================
1946 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::smIdType_array & IDsOfElements,
1947 CORBA::Boolean Diag13)
1952 SMESHDS_Mesh* aMesh = getMeshDS();
1953 TIDSortedElemSet faces;
1954 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1956 // Update Python script
1957 TPythonDump() << "isDone = " << this << ".SplitQuad( "
1958 << IDsOfElements << ", " << Diag13 << " )";
1960 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1962 declareMeshModified( /*isReComputeSafe=*/ !stat );
1965 SMESH_CATCH( SMESH::throwCorbaException );
1969 //=============================================================================
1971 * \brief Split quadrangles into triangles.
1973 //=============================================================================
1975 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1976 CORBA::Boolean Diag13)
1981 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
1983 prepareIdSource( theObject );
1984 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
1985 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1987 // Update Python script
1988 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1989 << theObject << ", " << Diag13 << " )";
1991 declareMeshModified( /*isReComputeSafe=*/!isDone );
1994 SMESH_CATCH( SMESH::throwCorbaException );
1999 //=============================================================================
2001 * Find better splitting of the given quadrangle.
2002 * \param IDOfQuad ID of the quadrangle to be split.
2003 * \param Criterion A criterion to choose a diagonal for splitting.
2004 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2005 * diagonal is better, 0 if error occurs.
2007 //=============================================================================
2009 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2010 SMESH::NumericalFunctor_ptr Criterion)
2015 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2016 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2018 SMESH::NumericalFunctor_i* aNumericalFunctor =
2019 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2020 SMESH::Controls::NumericalFunctorPtr aCrit;
2021 if (aNumericalFunctor)
2022 aCrit = aNumericalFunctor->GetNumericalFunctor();
2024 aCrit.reset(new SMESH::Controls::AspectRatio());
2026 int id = getEditor().BestSplit(quad, aCrit);
2027 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2031 SMESH_CATCH( SMESH::throwCorbaException );
2035 //================================================================================
2037 * \brief Split volumic elements into tetrahedrons
2039 //================================================================================
2041 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2042 CORBA::Short methodFlags)
2047 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2048 const int noneFacet = -1;
2049 prepareIdSource( elems );
2050 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2051 while ( volIt->more() )
2052 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2054 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2055 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2057 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2058 << elems << ", " << methodFlags << " )";
2060 SMESH_CATCH( SMESH::throwCorbaException );
2063 //================================================================================
2065 * \brief Split hexahedra into triangular prisms
2066 * \param elems - elements to split
2067 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2068 * to split into triangles
2069 * \param methodFlags - flags passing splitting method:
2070 * 1 - split the hexahedron into 2 prisms
2071 * 2 - split the hexahedron into 4 prisms
2073 //================================================================================
2075 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2076 const SMESH::PointStruct & startHexPoint,
2077 const SMESH::DirStruct& facetToSplitNormal,
2078 CORBA::Short methodFlags,
2079 CORBA::Boolean allDomains)
2083 prepareIdSource( elems );
2085 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2088 gp_Dir( facetToSplitNormal.PS.x,
2089 facetToSplitNormal.PS.y,
2090 facetToSplitNormal.PS.z ));
2091 TIDSortedElemSet elemSet;
2092 prepareIdSource( elems );
2093 SMESH::smIdType_array_var anElementsId = elems->GetIDs();
2094 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2095 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2097 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2098 while ( !elemSet.empty() )
2100 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2104 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2105 for ( ; ef != elemFacets.end(); ++ef )
2106 elemSet.erase( ef->first );
2109 if ( methodFlags == 2 )
2110 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2112 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2114 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2115 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2117 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2119 << startHexPoint << ", "
2120 << facetToSplitNormal<< ", "
2121 << methodFlags<< ", "
2122 << allDomains << " )";
2124 SMESH_CATCH( SMESH::throwCorbaException );
2127 //================================================================================
2129 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2130 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2131 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2132 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2133 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2134 * will be split in order to keep the mesh conformal.
2135 * \param elems - elements to split
2137 //================================================================================
2139 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2144 TIDSortedElemSet elemSet;
2145 for ( size_t i = 0; i < theElems.length(); ++i )
2147 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2148 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2149 if ( mesh->GetId() != myMesh_i->GetId() )
2150 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2152 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2154 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2156 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2158 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2159 << theElems << " )";
2161 SMESH_CATCH( SMESH::throwCorbaException );
2164 //=======================================================================
2167 //=======================================================================
2170 SMESH_MeshEditor_i::Smooth(const SMESH::smIdType_array & IDsOfElements,
2171 const SMESH::smIdType_array & IDsOfFixedNodes,
2172 CORBA::Short MaxNbOfIterations,
2173 CORBA::Double MaxAspectRatio,
2174 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2176 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2177 MaxAspectRatio, Method, false );
2181 //=======================================================================
2182 //function : SmoothParametric
2184 //=======================================================================
2187 SMESH_MeshEditor_i::SmoothParametric(const SMESH::smIdType_array & IDsOfElements,
2188 const SMESH::smIdType_array & IDsOfFixedNodes,
2189 CORBA::Short MaxNbOfIterations,
2190 CORBA::Double MaxAspectRatio,
2191 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2193 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2194 MaxAspectRatio, Method, true );
2198 //=======================================================================
2199 //function : SmoothObject
2201 //=======================================================================
2204 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2205 const SMESH::smIdType_array & IDsOfFixedNodes,
2206 CORBA::Short MaxNbOfIterations,
2207 CORBA::Double MaxAspectRatio,
2208 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2210 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2211 MaxAspectRatio, Method, false);
2215 //=======================================================================
2216 //function : SmoothParametricObject
2218 //=======================================================================
2221 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2222 const SMESH::smIdType_array & IDsOfFixedNodes,
2223 CORBA::Short MaxNbOfIterations,
2224 CORBA::Double MaxAspectRatio,
2225 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2227 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2228 MaxAspectRatio, Method, true);
2232 //=============================================================================
2236 //=============================================================================
2239 SMESH_MeshEditor_i::smooth(const SMESH::smIdType_array & IDsOfElements,
2240 const SMESH::smIdType_array & IDsOfFixedNodes,
2241 CORBA::Short MaxNbOfIterations,
2242 CORBA::Double MaxAspectRatio,
2243 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2249 SMESHDS_Mesh* aMesh = getMeshDS();
2251 TIDSortedElemSet elements;
2252 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2254 set<const SMDS_MeshNode*> fixedNodes;
2255 for ( SMESH::smIdType i = 0; i < IDsOfFixedNodes.length(); i++) {
2256 SMESH::smIdType index = IDsOfFixedNodes[i];
2257 const SMDS_MeshNode * node = aMesh->FindNode(index);
2259 fixedNodes.insert( node );
2261 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2262 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2263 method = ::SMESH_MeshEditor::CENTROIDAL;
2265 getEditor().Smooth(elements, fixedNodes, method,
2266 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2268 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2270 // Update Python script
2271 TPythonDump() << "isDone = " << this << "."
2272 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2273 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2274 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2275 << "SMESH.SMESH_MeshEditor."
2276 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2277 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2281 SMESH_CATCH( SMESH::throwCorbaException );
2285 //=============================================================================
2289 //=============================================================================
2292 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2293 const SMESH::smIdType_array & IDsOfFixedNodes,
2294 CORBA::Short MaxNbOfIterations,
2295 CORBA::Double MaxAspectRatio,
2296 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2302 TPythonDump aTPythonDump; // suppress dump in smooth()
2304 prepareIdSource( theObject );
2305 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2306 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2307 MaxAspectRatio, Method, IsParametric);
2309 // Update Python script
2310 aTPythonDump << "isDone = " << this << "."
2311 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2312 << theObject << ", " << IDsOfFixedNodes << ", "
2313 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2314 << "SMESH.SMESH_MeshEditor."
2315 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2316 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2320 SMESH_CATCH( SMESH::throwCorbaException );
2324 //=============================================================================
2328 //=============================================================================
2330 void SMESH_MeshEditor_i::RenumberNodes()
2333 // Update Python script
2334 TPythonDump() << this << ".RenumberNodes()";
2336 getMeshDS()->Renumber( true );
2338 SMESH_CATCH( SMESH::throwCorbaException );
2341 //=============================================================================
2345 //=============================================================================
2347 void SMESH_MeshEditor_i::RenumberElements()
2350 // Update Python script
2351 TPythonDump() << this << ".RenumberElements()";
2353 getMeshDS()->Renumber( false );
2355 SMESH_CATCH( SMESH::throwCorbaException );
2358 //=======================================================================
2360 * \brief Return groups by their IDs
2362 //=======================================================================
2364 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2369 myMesh_i->CreateGroupServants();
2370 return myMesh_i->GetGroups( *groupIDs );
2372 SMESH_CATCH( SMESH::throwCorbaException );
2376 //=======================================================================
2377 //function : RotationSweepObjects
2379 //=======================================================================
2381 SMESH::ListOfGroups*
2382 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2383 const SMESH::ListOfIDSources & theEdges,
2384 const SMESH::ListOfIDSources & theFaces,
2385 const SMESH::AxisStruct & theAxis,
2386 CORBA::Double theAngleInRadians,
2387 CORBA::Long theNbOfSteps,
2388 CORBA::Double theTolerance,
2389 const bool theMakeGroups)
2394 TIDSortedElemSet elemsNodes[2];
2395 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2396 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2397 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2399 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2400 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2401 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2402 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2404 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2405 bool makeWalls=true;
2406 if ( myIsPreviewMode )
2408 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2409 TPreviewMesh * tmpMesh = getPreviewMesh();
2410 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2411 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2412 workElements = & copyElements[0];
2413 //makeWalls = false; -- faces are needed for preview
2416 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2418 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2419 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2421 ::SMESH_MeshEditor::PGroupIDs groupIds =
2422 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2423 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2425 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2427 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2429 if ( !myIsPreviewMode )
2431 dumpGroupsList( aPythonDump, aGroups );
2432 aPythonDump << this<< ".RotationSweepObjects( "
2437 << TVar( theAngleInRadians ) << ", "
2438 << TVar( theNbOfSteps ) << ", "
2439 << TVar( theTolerance ) << ", "
2440 << theMakeGroups << " )";
2444 getPreviewMesh()->Remove( SMDSAbs_Volume );
2447 return aGroups ? aGroups : new SMESH::ListOfGroups;
2449 SMESH_CATCH( SMESH::throwCorbaException );
2453 namespace MeshEditor_I
2456 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2458 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2460 bool myIsExtrusionByNormal;
2462 static int makeFlags( CORBA::Boolean MakeGroups,
2463 CORBA::Boolean ScaleVariation = false,
2464 CORBA::Boolean AngleVariation = false,
2465 CORBA::Boolean ByAverageNormal = false,
2466 CORBA::Boolean UseInputElemsOnly = false,
2467 CORBA::Long Flags = 0,
2468 CORBA::Boolean MakeBoundary = true )
2470 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2471 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2472 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2473 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2474 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2475 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2479 ExtrusionParams(const SMESH::DirStruct & theDir,
2480 CORBA::Long theNbOfSteps,
2481 const SMESH::double_array & theScaleFactors,
2482 CORBA::Boolean theScaleVariation,
2483 const SMESH::double_array & theAngles,
2484 CORBA::Boolean theAngleVariation,
2485 const SMESH::double_array & theBasePoint,
2486 CORBA::Boolean theMakeGroups):
2487 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2491 toList( theScaleFactors ),
2492 toList( theAngles ),
2493 TBasePoint( theBasePoint ),
2494 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2495 myIsExtrusionByNormal( false )
2499 ExtrusionParams(const SMESH::DirStruct & theDir,
2500 CORBA::Long theNbOfSteps,
2501 CORBA::Boolean theMakeGroups,
2502 CORBA::Long theExtrFlags,
2503 CORBA::Double theSewTolerance):
2504 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2508 std::list<double>(),
2509 std::list<double>(),
2511 makeFlags( theMakeGroups, false, false, false, false,
2512 theExtrFlags, false ),
2514 myIsExtrusionByNormal( false )
2517 // params for extrusion by normal
2518 ExtrusionParams(CORBA::Double theStepSize,
2519 CORBA::Long theNbOfSteps,
2520 CORBA::Short theDim,
2521 CORBA::Boolean theByAverageNormal,
2522 CORBA::Boolean theUseInputElemsOnly,
2523 CORBA::Boolean theMakeGroups ):
2524 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2526 makeFlags( theMakeGroups, false, false,
2527 theByAverageNormal, theUseInputElemsOnly ),
2529 myIsExtrusionByNormal( true )
2535 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2538 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2540 std::list<double> scales;
2541 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2542 scales.push_back( theScaleFactors[i] );
2548 // structure used to convert SMESH::double_array to gp_XYZ*
2552 TBasePoint( const SMESH::double_array & theBasePoint )
2555 if ( theBasePoint.length() == 3 )
2557 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2561 operator const gp_XYZ*() const { return pp; }
2566 //=======================================================================
2568 * \brief Generate dim+1 elements by extrusion of elements along vector
2569 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2570 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2571 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2572 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2573 * \param [in] nbOfSteps - number of elements to generate from one element
2574 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2575 * corresponding to groups the input elements included in.
2576 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2578 //=======================================================================
2580 SMESH::ListOfGroups*
2581 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2582 const SMESH::ListOfIDSources & theEdges,
2583 const SMESH::ListOfIDSources & theFaces,
2584 const SMESH::DirStruct & theStepVector,
2585 CORBA::Long theNbOfSteps,
2586 CORBA::Boolean theToMakeGroups,
2587 const SMESH::double_array & theScaleFactors,
2588 CORBA::Boolean theScalesVariation,
2589 const SMESH::double_array & theBasePoint,
2590 const SMESH::double_array & theAngles,
2591 CORBA::Boolean theAnglesVariation)
2596 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2597 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2599 TIDSortedElemSet elemsNodes[2];
2600 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2601 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2602 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2604 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2605 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2606 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2607 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2609 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2610 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2611 if ( myIsPreviewMode )
2613 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2614 // previewType = SMDSAbs_Edge;
2616 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2617 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2618 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2619 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2620 workElements = & copyElements[0];
2622 params.SetNoGroups();
2624 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2626 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2627 ::SMESH_MeshEditor::PGroupIDs groupIds =
2628 getEditor().ExtrusionSweep( workElements, params, aHistory );
2630 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2632 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2634 if ( !myIsPreviewMode )
2636 dumpGroupsList( aPythonDump, aGroups );
2637 aPythonDump << this<< ".ExtrusionSweepObjects( "
2641 << theStepVector << ", "
2642 << TVar( theNbOfSteps ) << ", "
2643 << theToMakeGroups << ", "
2644 << TVar( theScaleFactors ) << ", "
2645 << theScalesVariation << ", "
2646 << TVar( theBasePoint ) << ", "
2647 << TVar( theAngles ) << ", "
2648 << theAnglesVariation << " )";
2652 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2655 return aGroups ? aGroups : new SMESH::ListOfGroups;
2657 SMESH_CATCH( SMESH::throwCorbaException );
2661 //=======================================================================
2662 //function : ExtrusionByNormal
2664 //=======================================================================
2666 SMESH::ListOfGroups*
2667 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2668 CORBA::Double stepSize,
2669 CORBA::Long nbOfSteps,
2670 CORBA::Boolean byAverageNormal,
2671 CORBA::Boolean useInputElemsOnly,
2672 CORBA::Boolean makeGroups,
2678 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2680 ExtrusionParams params( stepSize, nbOfSteps, dim,
2681 byAverageNormal, useInputElemsOnly, makeGroups );
2683 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2684 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2686 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2687 if (( elemTypes->length() == 1 ) &&
2688 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2689 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2692 TIDSortedElemSet elemsNodes[2];
2693 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2694 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2696 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2697 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2698 if ( myIsPreviewMode )
2700 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2701 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2702 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2703 workElements = & copyElements[0];
2705 params.SetNoGroups();
2708 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2709 ::SMESH_MeshEditor::PGroupIDs groupIds =
2710 getEditor().ExtrusionSweep( workElements, params, aHistory );
2712 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2714 if (!myIsPreviewMode) {
2715 dumpGroupsList(aPythonDump, aGroups);
2716 aPythonDump << this << ".ExtrusionByNormal( " << objects
2717 << ", " << TVar( stepSize )
2718 << ", " << TVar( nbOfSteps )
2719 << ", " << byAverageNormal
2720 << ", " << useInputElemsOnly
2721 << ", " << makeGroups
2727 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2730 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2732 return aGroups ? aGroups : new SMESH::ListOfGroups;
2734 SMESH_CATCH( SMESH::throwCorbaException );
2738 //=======================================================================
2739 //function : AdvancedExtrusion
2741 //=======================================================================
2743 SMESH::ListOfGroups*
2744 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::smIdType_array & theIDsOfElements,
2745 const SMESH::DirStruct & theStepVector,
2746 CORBA::Long theNbOfSteps,
2747 CORBA::Long theExtrFlags,
2748 CORBA::Double theSewTolerance,
2749 CORBA::Boolean theMakeGroups)
2754 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2756 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2757 theExtrFlags, theSewTolerance );
2759 TIDSortedElemSet elemsNodes[2];
2760 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2762 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2763 ::SMESH_MeshEditor::PGroupIDs groupIds =
2764 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2766 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2768 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2770 if ( !myIsPreviewMode ) {
2771 dumpGroupsList(aPythonDump, aGroups);
2772 aPythonDump << this << ".AdvancedExtrusion( "
2773 << theIDsOfElements << ", "
2774 << theStepVector << ", "
2775 << theNbOfSteps << ", "
2776 << theExtrFlags << ", "
2777 << theSewTolerance << ", "
2778 << theMakeGroups << " )";
2782 getPreviewMesh()->Remove( SMDSAbs_Volume );
2785 return aGroups ? aGroups : new SMESH::ListOfGroups;
2787 SMESH_CATCH( SMESH::throwCorbaException );
2791 //================================================================================
2793 * \brief Convert extrusion error to IDL enum
2795 //================================================================================
2799 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2801 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2805 RETCASE( EXTR_NO_ELEMENTS );
2806 RETCASE( EXTR_PATH_NOT_EDGE );
2807 RETCASE( EXTR_BAD_PATH_SHAPE );
2808 RETCASE( EXTR_BAD_STARTING_NODE );
2809 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2810 RETCASE( EXTR_CANT_GET_TANGENT );
2812 return SMESH::SMESH_MeshEditor::EXTR_OK;
2816 //=======================================================================
2817 //function : extrusionAlongPath
2819 //=======================================================================
2820 SMESH::ListOfGroups*
2821 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2822 const SMESH::ListOfIDSources & theEdges,
2823 const SMESH::ListOfIDSources & theFaces,
2824 SMESH::SMESH_IDSource_ptr thePathObject,
2825 GEOM::GEOM_Object_ptr thePathShape,
2826 SMESH::smIdType theNodeStart,
2827 CORBA::Boolean theHasAngles,
2828 const SMESH::double_array & theAngles,
2829 CORBA::Boolean theAnglesVariation,
2830 CORBA::Boolean theHasRefPoint,
2831 const SMESH::PointStruct & theRefPoint,
2833 const SMESH::double_array & theScaleFactors,
2834 CORBA::Boolean theScalesVariation,
2835 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2840 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2842 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2843 if ( thePathObject->_is_nil() )
2844 return aGroups._retn();
2847 SMDS_ElemIteratorPtr pathEdgesIterator;
2849 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2850 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2852 // get a sub-mesh of thePathShape
2853 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2854 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2856 return aGroups._retn();
2858 if ( !aSubMesh->GetSubMeshDS() )
2860 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2861 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2862 if ( !aSubMesh->GetSubMeshDS() )
2863 return aGroups._retn();
2865 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2866 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2867 if ( !pathEdgesIterator->more() ||
2868 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2869 return aGroups._retn();
2871 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2875 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2876 prepareIdSource( thePathObject );
2877 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2878 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2879 return aGroups._retn();
2884 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2885 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2889 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2890 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2892 return aGroups._retn();
2895 TIDSortedElemSet elemsNodes[2];
2896 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2897 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2898 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2900 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2901 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2902 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2903 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2905 list<double> angles = ExtrusionParams::toList( theAngles );
2906 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2908 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2909 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2911 int nbOldGroups = myMesh->NbGroup();
2913 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2914 if ( myIsPreviewMode )
2916 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2917 TPreviewMesh * tmpMesh = getPreviewMesh();
2918 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2919 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2920 workElements = & copyElements[0];
2921 theMakeGroups = false;
2924 ::SMESH_MeshEditor::Extrusion_Error error =
2925 getEditor().ExtrusionAlongTrack( workElements,
2926 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2927 angles, theAnglesVariation,
2928 scales, theScalesVariation,
2929 refPntPtr, theMakeGroups );
2931 declareMeshModified( /*isReComputeSafe=*/true );
2932 theError = convExtrError( error );
2934 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2935 if ( theMakeGroups ) {
2936 list<int> groupIDs = myMesh->GetGroupIds();
2937 list<int>::iterator newBegin = groupIDs.begin();
2938 std::advance( newBegin, nbOldGroups ); // skip old groups
2939 groupIDs.erase( groupIDs.begin(), newBegin );
2940 aGroups = getGroups( & groupIDs );
2941 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
2944 if ( !myIsPreviewMode ) {
2945 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
2946 else aPythonDump << "(_noGroups, error) = ";
2947 aPythonDump << this << ".ExtrusionAlongPathObjects( "
2951 << thePathObject << ", "
2952 << thePathShape << ", "
2953 << theNodeStart << ", "
2954 << theHasAngles << ", "
2955 << TVar( theAngles ) << ", "
2956 << theAnglesVariation << ", "
2957 << theHasRefPoint << ", "
2958 << "SMESH.PointStruct( "
2959 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2960 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2961 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
2962 << theMakeGroups << ", "
2963 << TVar( theScaleFactors ) << ", "
2964 << theScalesVariation << " )";
2968 getPreviewMesh()->Remove( SMDSAbs_Volume );
2971 return aGroups._retn();
2973 SMESH_CATCH( SMESH::throwCorbaException );
2977 //================================================================================
2979 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2980 * of given angles along path steps
2981 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2982 * which proceeds the extrusion
2983 * \param PathShape is shape(edge); as the mesh can be complex, the edge
2984 * is used to define the sub-mesh for the path
2986 //================================================================================
2988 SMESH::double_array*
2989 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
2990 GEOM::GEOM_Object_ptr thePathShape,
2991 const SMESH::double_array & theAngles)
2993 SMESH::double_array_var aResult = new SMESH::double_array();
2994 int nbAngles = theAngles.length();
2995 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2997 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2998 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2999 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3000 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3001 return aResult._retn();
3002 int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3003 if ( nbSteps == nbAngles )
3005 aResult.inout() = theAngles;
3009 aResult->length( nbSteps );
3010 double rAn2St = double( nbAngles ) / double( nbSteps );
3011 double angPrev = 0, angle;
3012 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3014 double angCur = rAn2St * ( iSt+1 );
3015 double angCurFloor = floor( angCur );
3016 double angPrevFloor = floor( angPrev );
3017 if ( angPrevFloor == angCurFloor )
3018 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3021 int iP = int( angPrevFloor );
3022 double angPrevCeil = ceil(angPrev);
3023 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3025 int iC = int( angCurFloor );
3026 if ( iC < nbAngles )
3027 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3029 iP = int( angPrevCeil );
3031 angle += theAngles[ iC ];
3033 aResult[ iSt ] = angle;
3038 // Update Python script
3039 TPythonDump() << "rotAngles = " << theAngles;
3040 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3041 << thePathMesh << ", "
3042 << thePathShape << ", "
3045 return aResult._retn();
3048 //=======================================================================
3051 //=======================================================================
3053 SMESH::ListOfGroups*
3054 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3055 const SMESH::AxisStruct & theAxis,
3056 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3057 CORBA::Boolean theCopy,
3059 ::SMESH_Mesh* theTargetMesh)
3064 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3065 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3067 if ( theTargetMesh )
3071 switch ( theMirrorType ) {
3072 case SMESH::SMESH_MeshEditor::POINT:
3073 aTrsf.SetMirror( P );
3075 case SMESH::SMESH_MeshEditor::AXIS:
3076 aTrsf.SetMirror( gp_Ax1( P, V ));
3079 aTrsf.SetMirror( gp_Ax2( P, V ));
3082 TIDSortedElemSet copyElements;
3083 TIDSortedElemSet* workElements = & theElements;
3085 if ( myIsPreviewMode )
3087 TPreviewMesh * tmpMesh = getPreviewMesh();
3088 tmpMesh->Copy( theElements, copyElements);
3089 if ( !theCopy && !theTargetMesh )
3091 TIDSortedElemSet elemsAround, elemsAroundCopy;
3092 getElementsAround( theElements, getMeshDS(), elemsAround );
3093 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3095 workElements = & copyElements;
3096 theMakeGroups = false;
3099 ::SMESH_MeshEditor::PGroupIDs groupIds =
3100 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3102 if ( !myIsPreviewMode )
3104 if ( theTargetMesh )
3105 theTargetMesh->GetMeshDS()->Modified();
3107 declareMeshModified( /*isReComputeSafe=*/false );
3110 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3112 SMESH_CATCH( SMESH::throwCorbaException );
3116 //=======================================================================
3119 //=======================================================================
3121 void SMESH_MeshEditor_i::Mirror(const SMESH::smIdType_array & theIDsOfElements,
3122 const SMESH::AxisStruct & theAxis,
3123 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3124 CORBA::Boolean theCopy)
3126 if ( !myIsPreviewMode ) {
3127 TPythonDump() << this << ".Mirror( "
3128 << theIDsOfElements << ", "
3130 << mirrorTypeName(theMirrorType) << ", "
3133 if ( theIDsOfElements.length() > 0 )
3135 TIDSortedElemSet elements;
3136 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3137 mirror(elements, theAxis, theMirrorType, theCopy, false);
3142 //=======================================================================
3143 //function : MirrorObject
3145 //=======================================================================
3147 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3148 const SMESH::AxisStruct & theAxis,
3149 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3150 CORBA::Boolean theCopy)
3152 if ( !myIsPreviewMode ) {
3153 TPythonDump() << this << ".MirrorObject( "
3154 << theObject << ", "
3156 << mirrorTypeName(theMirrorType) << ", "
3159 TIDSortedElemSet elements;
3161 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3163 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3164 mirror(elements, theAxis, theMirrorType, theCopy, false);
3167 //=======================================================================
3168 //function : MirrorMakeGroups
3170 //=======================================================================
3172 SMESH::ListOfGroups*
3173 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3174 const SMESH::AxisStruct& theMirror,
3175 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3177 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3179 SMESH::ListOfGroups * aGroups = 0;
3180 if ( theIDsOfElements.length() > 0 )
3182 TIDSortedElemSet elements;
3183 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3184 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3186 if (!myIsPreviewMode) {
3187 dumpGroupsList(aPythonDump, aGroups);
3188 aPythonDump << this << ".MirrorMakeGroups( "
3189 << theIDsOfElements << ", "
3190 << theMirror << ", "
3191 << mirrorTypeName(theMirrorType) << " )";
3196 //=======================================================================
3197 //function : MirrorObjectMakeGroups
3199 //=======================================================================
3201 SMESH::ListOfGroups*
3202 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3203 const SMESH::AxisStruct& theMirror,
3204 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3206 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3208 SMESH::ListOfGroups * aGroups = 0;
3209 TIDSortedElemSet elements;
3210 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3211 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3213 if (!myIsPreviewMode)
3215 dumpGroupsList(aPythonDump,aGroups);
3216 aPythonDump << this << ".MirrorObjectMakeGroups( "
3217 << theObject << ", "
3218 << theMirror << ", "
3219 << mirrorTypeName(theMirrorType) << " )";
3224 //=======================================================================
3225 //function : MirrorMakeMesh
3227 //=======================================================================
3229 SMESH::SMESH_Mesh_ptr
3230 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3231 const SMESH::AxisStruct& theMirror,
3232 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3233 CORBA::Boolean theCopyGroups,
3234 const char* theMeshName)
3236 SMESH_Mesh_i* mesh_i;
3237 SMESH::SMESH_Mesh_var mesh;
3238 { // open new scope to dump "MakeMesh" command
3239 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3241 TPythonDump pydump; // to prevent dump at mesh creation
3243 mesh = makeMesh( theMeshName );
3244 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3245 if (mesh_i && theIDsOfElements.length() > 0 )
3247 TIDSortedElemSet elements;
3248 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3249 mirror(elements, theMirror, theMirrorType,
3250 false, theCopyGroups, & mesh_i->GetImpl());
3251 mesh_i->CreateGroupServants();
3254 if (!myIsPreviewMode) {
3255 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3256 << theIDsOfElements << ", "
3257 << theMirror << ", "
3258 << mirrorTypeName(theMirrorType) << ", "
3259 << theCopyGroups << ", '"
3260 << theMeshName << "' )";
3265 if (!myIsPreviewMode && mesh_i)
3266 mesh_i->GetGroups();
3268 return mesh._retn();
3271 //=======================================================================
3272 //function : MirrorObjectMakeMesh
3274 //=======================================================================
3276 SMESH::SMESH_Mesh_ptr
3277 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3278 const SMESH::AxisStruct& theMirror,
3279 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3280 CORBA::Boolean theCopyGroups,
3281 const char* theMeshName)
3283 SMESH_Mesh_i* mesh_i;
3284 SMESH::SMESH_Mesh_var mesh;
3285 { // open new scope to dump "MakeMesh" command
3286 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3288 TPythonDump pydump; // to prevent dump at mesh creation
3290 mesh = makeMesh( theMeshName );
3291 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3292 TIDSortedElemSet elements;
3294 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3296 mirror(elements, theMirror, theMirrorType,
3297 false, theCopyGroups, & mesh_i->GetImpl());
3298 mesh_i->CreateGroupServants();
3300 if (!myIsPreviewMode) {
3301 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3302 << theObject << ", "
3303 << theMirror << ", "
3304 << mirrorTypeName(theMirrorType) << ", "
3305 << theCopyGroups << ", '"
3306 << theMeshName << "' )";
3311 if (!myIsPreviewMode && mesh_i)
3312 mesh_i->GetGroups();
3314 return mesh._retn();
3317 //=======================================================================
3318 //function : translate
3320 //=======================================================================
3322 SMESH::ListOfGroups*
3323 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3324 const SMESH::DirStruct & theVector,
3325 CORBA::Boolean theCopy,
3327 ::SMESH_Mesh* theTargetMesh)
3332 if ( theTargetMesh )
3336 const SMESH::PointStruct * P = &theVector.PS;
3337 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3339 TIDSortedElemSet copyElements;
3340 TIDSortedElemSet* workElements = &theElements;
3342 if ( myIsPreviewMode )
3344 TPreviewMesh * tmpMesh = getPreviewMesh();
3345 tmpMesh->Copy( theElements, copyElements);
3346 if ( !theCopy && !theTargetMesh )
3348 TIDSortedElemSet elemsAround, elemsAroundCopy;
3349 getElementsAround( theElements, getMeshDS(), elemsAround );
3350 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3352 workElements = & copyElements;
3353 theMakeGroups = false;
3356 ::SMESH_MeshEditor::PGroupIDs groupIds =
3357 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3359 if ( !myIsPreviewMode )
3361 if ( theTargetMesh )
3362 theTargetMesh->GetMeshDS()->Modified();
3364 declareMeshModified( /*isReComputeSafe=*/false );
3367 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3369 SMESH_CATCH( SMESH::throwCorbaException );
3373 //=======================================================================
3374 //function : Translate
3376 //=======================================================================
3378 void SMESH_MeshEditor_i::Translate(const SMESH::smIdType_array & theIDsOfElements,
3379 const SMESH::DirStruct & theVector,
3380 CORBA::Boolean theCopy)
3382 if (!myIsPreviewMode) {
3383 TPythonDump() << this << ".Translate( "
3384 << theIDsOfElements << ", "
3385 << theVector << ", "
3388 if (theIDsOfElements.length()) {
3389 TIDSortedElemSet elements;
3390 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3391 translate(elements, theVector, theCopy, false);
3395 //=======================================================================
3396 //function : TranslateObject
3398 //=======================================================================
3400 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3401 const SMESH::DirStruct & theVector,
3402 CORBA::Boolean theCopy)
3404 if (!myIsPreviewMode) {
3405 TPythonDump() << this << ".TranslateObject( "
3406 << theObject << ", "
3407 << theVector << ", "
3410 TIDSortedElemSet elements;
3412 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3414 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3415 translate(elements, theVector, theCopy, false);
3418 //=======================================================================
3419 //function : TranslateMakeGroups
3421 //=======================================================================
3423 SMESH::ListOfGroups*
3424 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3425 const SMESH::DirStruct& theVector)
3427 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3429 SMESH::ListOfGroups * aGroups = 0;
3430 if (theIDsOfElements.length()) {
3431 TIDSortedElemSet elements;
3432 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3433 aGroups = translate(elements,theVector,true,true);
3435 if (!myIsPreviewMode) {
3436 dumpGroupsList(aPythonDump, aGroups);
3437 aPythonDump << this << ".TranslateMakeGroups( "
3438 << theIDsOfElements << ", "
3439 << theVector << " )";
3444 //=======================================================================
3445 //function : TranslateObjectMakeGroups
3447 //=======================================================================
3449 SMESH::ListOfGroups*
3450 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3451 const SMESH::DirStruct& theVector)
3453 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3455 SMESH::ListOfGroups * aGroups = 0;
3456 TIDSortedElemSet elements;
3457 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3458 aGroups = translate(elements, theVector, true, true);
3460 if (!myIsPreviewMode) {
3461 dumpGroupsList(aPythonDump, aGroups);
3462 aPythonDump << this << ".TranslateObjectMakeGroups( "
3463 << theObject << ", "
3464 << theVector << " )";
3469 //=======================================================================
3470 //function : TranslateMakeMesh
3472 //=======================================================================
3474 SMESH::SMESH_Mesh_ptr
3475 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3476 const SMESH::DirStruct& theVector,
3477 CORBA::Boolean theCopyGroups,
3478 const char* theMeshName)
3480 SMESH_Mesh_i* mesh_i;
3481 SMESH::SMESH_Mesh_var mesh;
3483 { // open new scope to dump "MakeMesh" command
3484 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3486 TPythonDump pydump; // to prevent dump at mesh creation
3488 mesh = makeMesh( theMeshName );
3489 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3491 if ( mesh_i && theIDsOfElements.length() )
3493 TIDSortedElemSet elements;
3494 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3495 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3496 mesh_i->CreateGroupServants();
3499 if ( !myIsPreviewMode ) {
3500 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3501 << theIDsOfElements << ", "
3502 << theVector << ", "
3503 << theCopyGroups << ", '"
3504 << theMeshName << "' )";
3509 if (!myIsPreviewMode && mesh_i)
3510 mesh_i->GetGroups();
3512 return mesh._retn();
3515 //=======================================================================
3516 //function : TranslateObjectMakeMesh
3518 //=======================================================================
3520 SMESH::SMESH_Mesh_ptr
3521 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3522 const SMESH::DirStruct& theVector,
3523 CORBA::Boolean theCopyGroups,
3524 const char* theMeshName)
3527 SMESH_Mesh_i* mesh_i;
3528 SMESH::SMESH_Mesh_var mesh;
3529 { // open new scope to dump "MakeMesh" command
3530 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3532 TPythonDump pydump; // to prevent dump at mesh creation
3533 mesh = makeMesh( theMeshName );
3534 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3536 TIDSortedElemSet elements;
3538 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3540 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3541 mesh_i->CreateGroupServants();
3543 if ( !myIsPreviewMode ) {
3544 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3545 << theObject << ", "
3546 << theVector << ", "
3547 << theCopyGroups << ", '"
3548 << theMeshName << "' )";
3553 if (!myIsPreviewMode && mesh_i)
3554 mesh_i->GetGroups();
3556 return mesh._retn();
3558 SMESH_CATCH( SMESH::throwCorbaException );
3562 //=======================================================================
3565 //=======================================================================
3567 SMESH::ListOfGroups*
3568 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3569 const SMESH::AxisStruct & theAxis,
3570 CORBA::Double theAngle,
3571 CORBA::Boolean theCopy,
3573 ::SMESH_Mesh* theTargetMesh)
3578 if ( theTargetMesh )
3581 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3582 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3585 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3587 TIDSortedElemSet copyElements;
3588 TIDSortedElemSet* workElements = &theElements;
3589 if ( myIsPreviewMode ) {
3590 TPreviewMesh * tmpMesh = getPreviewMesh();
3591 tmpMesh->Copy( theElements, copyElements );
3592 if ( !theCopy && !theTargetMesh )
3594 TIDSortedElemSet elemsAround, elemsAroundCopy;
3595 getElementsAround( theElements, getMeshDS(), elemsAround );
3596 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3598 workElements = ©Elements;
3599 theMakeGroups = false;
3602 ::SMESH_MeshEditor::PGroupIDs groupIds =
3603 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3605 if ( !myIsPreviewMode)
3607 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3608 else declareMeshModified( /*isReComputeSafe=*/false );
3611 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3613 SMESH_CATCH( SMESH::throwCorbaException );
3617 //=======================================================================
3620 //=======================================================================
3622 void SMESH_MeshEditor_i::Rotate(const SMESH::smIdType_array & theIDsOfElements,
3623 const SMESH::AxisStruct & theAxis,
3624 CORBA::Double theAngle,
3625 CORBA::Boolean theCopy)
3627 if (!myIsPreviewMode) {
3628 TPythonDump() << this << ".Rotate( "
3629 << theIDsOfElements << ", "
3631 << TVar( theAngle ) << ", "
3634 if (theIDsOfElements.length() > 0)
3636 TIDSortedElemSet elements;
3637 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3638 rotate(elements,theAxis,theAngle,theCopy,false);
3642 //=======================================================================
3643 //function : RotateObject
3645 //=======================================================================
3647 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3648 const SMESH::AxisStruct & theAxis,
3649 CORBA::Double theAngle,
3650 CORBA::Boolean theCopy)
3652 if ( !myIsPreviewMode ) {
3653 TPythonDump() << this << ".RotateObject( "
3654 << theObject << ", "
3656 << TVar( theAngle ) << ", "
3659 TIDSortedElemSet elements;
3660 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3661 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3662 rotate(elements,theAxis,theAngle,theCopy,false);
3665 //=======================================================================
3666 //function : RotateMakeGroups
3668 //=======================================================================
3670 SMESH::ListOfGroups*
3671 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3672 const SMESH::AxisStruct& theAxis,
3673 CORBA::Double theAngle)
3675 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3677 SMESH::ListOfGroups * aGroups = 0;
3678 if (theIDsOfElements.length() > 0)
3680 TIDSortedElemSet elements;
3681 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3682 aGroups = rotate(elements,theAxis,theAngle,true,true);
3684 if (!myIsPreviewMode) {
3685 dumpGroupsList(aPythonDump, aGroups);
3686 aPythonDump << this << ".RotateMakeGroups( "
3687 << theIDsOfElements << ", "
3689 << TVar( theAngle ) << " )";
3694 //=======================================================================
3695 //function : RotateObjectMakeGroups
3697 //=======================================================================
3699 SMESH::ListOfGroups*
3700 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3701 const SMESH::AxisStruct& theAxis,
3702 CORBA::Double theAngle)
3704 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3706 SMESH::ListOfGroups * aGroups = 0;
3707 TIDSortedElemSet elements;
3708 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3709 aGroups = rotate(elements, theAxis, theAngle, true, true);
3711 if (!myIsPreviewMode) {
3712 dumpGroupsList(aPythonDump, aGroups);
3713 aPythonDump << this << ".RotateObjectMakeGroups( "
3714 << theObject << ", "
3716 << TVar( theAngle ) << " )";
3721 //=======================================================================
3722 //function : RotateMakeMesh
3724 //=======================================================================
3726 SMESH::SMESH_Mesh_ptr
3727 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3728 const SMESH::AxisStruct& theAxis,
3729 CORBA::Double theAngleInRadians,
3730 CORBA::Boolean theCopyGroups,
3731 const char* theMeshName)
3734 SMESH::SMESH_Mesh_var mesh;
3735 SMESH_Mesh_i* mesh_i;
3737 { // open new scope to dump "MakeMesh" command
3738 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3740 TPythonDump pydump; // to prevent dump at mesh creation
3742 mesh = makeMesh( theMeshName );
3743 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3745 if ( mesh_i && theIDsOfElements.length() > 0 )
3747 TIDSortedElemSet elements;
3748 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3749 rotate(elements, theAxis, theAngleInRadians,
3750 false, theCopyGroups, & mesh_i->GetImpl());
3751 mesh_i->CreateGroupServants();
3753 if ( !myIsPreviewMode ) {
3754 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3755 << theIDsOfElements << ", "
3757 << TVar( theAngleInRadians ) << ", "
3758 << theCopyGroups << ", '"
3759 << theMeshName << "' )";
3764 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3765 mesh_i->GetGroups();
3767 return mesh._retn();
3769 SMESH_CATCH( SMESH::throwCorbaException );
3773 //=======================================================================
3774 //function : RotateObjectMakeMesh
3776 //=======================================================================
3778 SMESH::SMESH_Mesh_ptr
3779 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3780 const SMESH::AxisStruct& theAxis,
3781 CORBA::Double theAngleInRadians,
3782 CORBA::Boolean theCopyGroups,
3783 const char* theMeshName)
3786 SMESH::SMESH_Mesh_var mesh;
3787 SMESH_Mesh_i* mesh_i;
3789 {// open new scope to dump "MakeMesh" command
3790 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3792 TPythonDump pydump; // to prevent dump at mesh creation
3793 mesh = makeMesh( theMeshName );
3794 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3796 TIDSortedElemSet elements;
3798 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3800 rotate(elements, theAxis, theAngleInRadians,
3801 false, theCopyGroups, & mesh_i->GetImpl());
3802 mesh_i->CreateGroupServants();
3804 if ( !myIsPreviewMode ) {
3805 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3806 << theObject << ", "
3808 << TVar( theAngleInRadians ) << ", "
3809 << theCopyGroups << ", '"
3810 << theMeshName << "' )";
3815 if (!myIsPreviewMode && mesh_i)
3816 mesh_i->GetGroups();
3818 return mesh._retn();
3820 SMESH_CATCH( SMESH::throwCorbaException );
3824 //=======================================================================
3827 //=======================================================================
3829 SMESH::ListOfGroups*
3830 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3831 const SMESH::PointStruct& thePoint,
3832 const SMESH::double_array& theScaleFact,
3833 CORBA::Boolean theCopy,
3835 ::SMESH_Mesh* theTargetMesh)
3839 if ( theScaleFact.length() < 1 )
3840 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3841 if ( theScaleFact.length() == 2 )
3842 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3844 if ( theTargetMesh )
3847 TIDSortedElemSet elements;
3848 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3849 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3854 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3855 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3859 // fight against orthogonalization
3860 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3861 // 0, S[1], 0, thePoint.y * (1-S[1]),
3862 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3863 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3864 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3865 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3866 loc.SetCoord( thePoint.x * (1-S[0]),
3867 thePoint.y * (1-S[1]),
3868 thePoint.z * (1-S[2]));
3869 M.SetDiagonal( S[0], S[1], S[2] );
3871 TIDSortedElemSet copyElements;
3872 TIDSortedElemSet* workElements = &elements;
3873 if ( myIsPreviewMode )
3875 TPreviewMesh * tmpMesh = getPreviewMesh();
3876 tmpMesh->Copy( elements, copyElements);
3877 if ( !theCopy && !theTargetMesh )
3879 TIDSortedElemSet elemsAround, elemsAroundCopy;
3880 getElementsAround( elements, getMeshDS(), elemsAround );
3881 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3883 workElements = & copyElements;
3884 theMakeGroups = false;
3887 ::SMESH_MeshEditor::PGroupIDs groupIds =
3888 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3890 if ( !myIsPreviewMode )
3892 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3893 else declareMeshModified( /*isReComputeSafe=*/false );
3895 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3897 SMESH_CATCH( SMESH::throwCorbaException );
3901 //=======================================================================
3904 //=======================================================================
3906 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3907 const SMESH::PointStruct& thePoint,
3908 const SMESH::double_array& theScaleFact,
3909 CORBA::Boolean theCopy)
3911 if ( !myIsPreviewMode ) {
3912 TPythonDump() << this << ".Scale( "
3913 << theObject << ", "
3915 << TVar( theScaleFact ) << ", "
3918 scale(theObject, thePoint, theScaleFact, theCopy, false);
3922 //=======================================================================
3923 //function : ScaleMakeGroups
3925 //=======================================================================
3927 SMESH::ListOfGroups*
3928 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3929 const SMESH::PointStruct& thePoint,
3930 const SMESH::double_array& theScaleFact)
3932 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3934 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3935 if (!myIsPreviewMode) {
3936 dumpGroupsList(aPythonDump, aGroups);
3937 aPythonDump << this << ".Scale("
3940 << TVar( theScaleFact ) << ",True,True)";
3946 //=======================================================================
3947 //function : ScaleMakeMesh
3949 //=======================================================================
3951 SMESH::SMESH_Mesh_ptr
3952 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3953 const SMESH::PointStruct& thePoint,
3954 const SMESH::double_array& theScaleFact,
3955 CORBA::Boolean theCopyGroups,
3956 const char* theMeshName)
3958 SMESH_Mesh_i* mesh_i;
3959 SMESH::SMESH_Mesh_var mesh;
3960 { // open new scope to dump "MakeMesh" command
3961 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3963 TPythonDump pydump; // to prevent dump at mesh creation
3964 mesh = makeMesh( theMeshName );
3965 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3969 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3970 mesh_i->CreateGroupServants();
3972 if ( !myIsPreviewMode )
3973 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3974 << theObject << ", "
3976 << TVar( theScaleFact ) << ", "
3977 << theCopyGroups << ", '"
3978 << theMeshName << "' )";
3982 if (!myIsPreviewMode && mesh_i)
3983 mesh_i->GetGroups();
3985 return mesh._retn();
3988 //================================================================================
3990 * \brief Make an offset mesh from a source 2D mesh
3991 * \param [inout] theObject - source mesh. New elements are added to this mesh
3992 * if \a theMeshName is empty.
3993 * \param [in] theValue - offset value
3994 * \param [in] theCopyGroups - to generate groups
3995 * \param [in] theMeshName - optional name of a new mesh
3996 * \param [out] theGroups - new groups
3997 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
3999 //================================================================================
4001 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4002 CORBA::Double theValue,
4003 CORBA::Boolean theCopyGroups,
4004 CORBA::Boolean theCopyElements,
4005 const char* theMeshName,
4006 SMESH::ListOfGroups_out theGroups)
4011 SMESHDS_Mesh* aMeshDS = getMeshDS();
4013 SMESH::SMESH_Mesh_var mesh_var;
4014 ::SMESH_MeshEditor::PGroupIDs groupIds;
4018 TIDSortedElemSet elements, copyElements;
4019 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4020 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4023 SMESH_Mesh* tgtMesh = 0;
4024 if ( myIsPreviewMode )
4026 TPreviewMesh * tmpMesh = getPreviewMesh();
4028 tmpMesh->Copy( elements, copyElements );
4029 elements.swap( copyElements );
4030 theCopyGroups = false;
4031 theCopyElements = false;
4036 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4037 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4038 tgtMesh = & mesh_i->GetImpl();
4040 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4041 theCopyGroups, theCopyElements, !myIsPreviewMode );
4043 tgtMesh->GetMeshDS()->Modified();
4046 if ( myIsPreviewMode )
4048 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4052 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4054 // new mesh empty, remove it
4055 SALOMEDS::Study_var study = SMESH_Gen_i::getStudyServant();
4056 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4057 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::ObjectToSObject( mesh_var );
4058 builder->RemoveObjectWithChildren( meshSO );
4059 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4061 if ( !groupIds ) // nothing changed in the current mesh
4062 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4064 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4066 // result of Offset() is a tuple (mesh, groups)
4067 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4068 else pyDump << mesh_var << ", ";
4069 pyDump << theGroups << " = " << this << ".Offset( "
4070 << theObject << ", "
4072 << theCopyGroups << ", "
4073 << theCopyElements << ", "
4074 << "'" << theMeshName<< "')";
4077 return mesh_var._retn();
4079 SMESH_CATCH( SMESH::throwCorbaException );
4080 return SMESH::SMESH_Mesh::_nil();
4083 //=======================================================================
4084 //function : findCoincidentNodes
4086 //=======================================================================
4088 void SMESH_MeshEditor_i::
4089 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4090 CORBA::Double Tolerance,
4091 SMESH::array_of_long_array_out GroupsOfNodes,
4092 CORBA::Boolean SeparateCornersAndMedium)
4094 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4095 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4097 GroupsOfNodes = new SMESH::array_of_long_array;
4098 GroupsOfNodes->length( aListOfListOfNodes.size() );
4099 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4100 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4102 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4103 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4104 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4105 aGroup.length( aListOfNodes.size() );
4106 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4107 aGroup[ j ] = (*lIt)->GetID();
4111 //=======================================================================
4112 //function : FindCoincidentNodes
4114 //=======================================================================
4116 void SMESH_MeshEditor_i::
4117 FindCoincidentNodes (CORBA::Double Tolerance,
4118 SMESH::array_of_long_array_out GroupsOfNodes,
4119 CORBA::Boolean SeparateCornersAndMedium)
4124 TIDSortedNodeSet nodes; // no input nodes
4125 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4127 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4128 << Tolerance << ", "
4129 << SeparateCornersAndMedium << " )";
4131 SMESH_CATCH( SMESH::throwCorbaException );
4134 //=======================================================================
4135 //function : FindCoincidentNodesOnPart
4137 //=======================================================================
4139 void SMESH_MeshEditor_i::
4140 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4141 CORBA::Double Tolerance,
4142 SMESH::array_of_long_array_out GroupsOfNodes,
4143 CORBA::Boolean SeparateCornersAndMedium)
4148 TIDSortedNodeSet nodes;
4149 prepareIdSource( theObject );
4150 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4152 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4154 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4156 << Tolerance << ", "
4157 << SeparateCornersAndMedium << " )";
4159 SMESH_CATCH( SMESH::throwCorbaException );
4162 //================================================================================
4164 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4165 * ExceptSubMeshOrGroups
4167 //================================================================================
4169 void SMESH_MeshEditor_i::
4170 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4171 CORBA::Double theTolerance,
4172 SMESH::array_of_long_array_out theGroupsOfNodes,
4173 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4174 CORBA::Boolean theSeparateCornersAndMedium)
4179 TIDSortedNodeSet nodes;
4180 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4182 prepareIdSource( theObjects[i] );
4183 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4185 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4187 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4189 while ( nodeIt->more() )
4190 nodes.erase( cast2Node( nodeIt->next() ));
4192 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4194 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4195 << theObjects <<", "
4196 << theTolerance << ", "
4197 << theExceptSubMeshOrGroups << ", "
4198 << theSeparateCornersAndMedium << " )";
4200 SMESH_CATCH( SMESH::throwCorbaException );
4203 //=======================================================================
4204 //function : MergeNodes
4206 //=======================================================================
4208 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4209 const SMESH::ListOfIDSources& NodesToKeep,
4210 CORBA::Boolean AvoidMakingHoles)
4215 SMESHDS_Mesh* aMesh = getMeshDS();
4217 TPythonDump aTPythonDump;
4218 aTPythonDump << this << ".MergeNodes([";
4220 TIDSortedNodeSet setOfNodesToKeep;
4221 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4223 prepareIdSource( NodesToKeep[i] );
4224 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4225 while ( nodeIt->more() )
4226 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4229 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4230 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4232 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4233 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4234 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4235 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4237 CORBA::Long index = aNodeGroup[ j ];
4238 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4240 if ( setOfNodesToKeep.count( node ))
4241 aListOfNodes.push_front( node );
4243 aListOfNodes.push_back( node );
4246 if ( aListOfNodes.size() < 2 )
4247 aListOfListOfNodes.pop_back();
4249 if ( i > 0 ) aTPythonDump << ", ";
4250 aTPythonDump << aNodeGroup;
4253 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4255 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4257 declareMeshModified( /*isReComputeSafe=*/false );
4259 SMESH_CATCH( SMESH::throwCorbaException );
4262 //=======================================================================
4263 //function : FindEqualElements
4265 //=======================================================================
4267 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4268 const SMESH::ListOfIDSources& theExceptObjects,
4269 SMESH::array_of_long_array_out theGroupsOfElementsID)
4274 theGroupsOfElementsID = new SMESH::array_of_long_array;
4276 TIDSortedElemSet elems;
4277 bool hasOkObject = false;
4278 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4280 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4282 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4283 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4284 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4290 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4292 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4293 while ( elemIt->more() )
4294 elems.erase( elemIt->next() );
4297 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4298 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4300 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4302 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4303 aListOfListOfElementsID.begin();
4304 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4306 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4307 list<int>& listOfIDs = *arraysIt;
4308 aGroup.length( listOfIDs.size() );
4309 list<int>::iterator idIt = listOfIDs.begin();
4310 for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4311 aGroup[ k ] = *idIt;
4314 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4315 << theObjects << ", "
4316 << theExceptObjects << " )";
4319 SMESH_CATCH( SMESH::throwCorbaException );
4322 //=======================================================================
4323 //function : MergeElements
4325 //=======================================================================
4327 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4328 const SMESH::ListOfIDSources& theElementsToKeep)
4333 TPythonDump aTPythonDump;
4334 aTPythonDump << this << ".MergeElements( [";
4336 NCollection_Map< int > idsToKeep;
4337 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4339 if ( CORBA::is_nil( theElementsToKeep[i] ))
4341 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4342 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4344 SMESH::smIdType_array_var elementsId = theElementsToKeep[i]->GetIDs();
4345 for ( SMESH::smIdType j = 0; j < elementsId->length(); ++j )
4346 idsToKeep.Add( elementsId[ j ]);
4349 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4351 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4353 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4354 aListOfListOfElementsID.push_back( list< int >() );
4355 list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4356 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4358 CORBA::Long id = anElemsIDGroup[ j ];
4359 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4360 else aListOfElemsID.push_back( id );
4362 if ( aListOfElemsID.size() < 2 )
4363 aListOfListOfElementsID.pop_back();
4364 if ( i > 0 ) aTPythonDump << ", ";
4365 aTPythonDump << anElemsIDGroup;
4368 getEditor().MergeElements(aListOfListOfElementsID);
4370 declareMeshModified( /*isReComputeSafe=*/true );
4372 aTPythonDump << "], " << theElementsToKeep << " )";
4374 SMESH_CATCH( SMESH::throwCorbaException );
4377 //=======================================================================
4378 //function : MergeEqualElements
4380 //=======================================================================
4382 void SMESH_MeshEditor_i::MergeEqualElements()
4387 getEditor().MergeEqualElements();
4389 declareMeshModified( /*isReComputeSafe=*/true );
4391 TPythonDump() << this << ".MergeEqualElements()";
4393 SMESH_CATCH( SMESH::throwCorbaException );
4396 //=============================================================================
4398 * Move the node to a given point
4400 //=============================================================================
4402 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(SMESH::smIdType NodeID,
4408 initData(/*deleteSearchers=*/false);
4410 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4414 if ( theNodeSearcher )
4415 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4417 if ( myIsPreviewMode ) // make preview data
4419 // in a preview mesh, make edges linked to a node
4420 TPreviewMesh& tmpMesh = *getPreviewMesh();
4421 TIDSortedElemSet linkedNodes;
4422 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4423 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4424 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4425 for ( ; nIt != linkedNodes.end(); ++nIt )
4427 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4428 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4432 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4433 // fill preview data
4435 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4436 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4438 getMeshDS()->MoveNode(node, x, y, z);
4440 if ( !myIsPreviewMode )
4442 // Update Python script
4443 TPythonDump() << "isDone = " << this << ".MoveNode( "
4444 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4445 declareMeshModified( /*isReComputeSafe=*/false );
4448 SMESH_CATCH( SMESH::throwCorbaException );
4453 //================================================================================
4455 * \brief Return ID of node closest to a given point
4457 //================================================================================
4459 SMESH::smIdType SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4464 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4466 if ( !theNodeSearcher ) {
4467 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4470 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4471 return node->GetID();
4473 SMESH_CATCH( SMESH::throwCorbaException );
4477 //================================================================================
4479 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4480 * move the node closest to the point to point's location and return ID of the node
4482 //================================================================================
4484 SMESH::smIdType SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4487 SMESH::smIdType theNodeID)
4490 // We keep theNodeSearcher until any mesh modification:
4491 // 1) initData() deletes theNodeSearcher at any edition,
4492 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4494 initData(/*deleteSearchers=*/false);
4496 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4498 smIdType nodeID = theNodeID;
4499 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4500 if ( !node ) // preview moving node
4502 if ( !theNodeSearcher ) {
4503 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4506 node = theNodeSearcher->FindClosestTo( p );
4509 nodeID = node->GetID();
4510 if ( myIsPreviewMode ) // make preview data
4512 // in a preview mesh, make edges linked to a node
4513 TPreviewMesh tmpMesh = *getPreviewMesh();
4514 TIDSortedElemSet linkedNodes;
4515 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4516 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4517 for ( ; nIt != linkedNodes.end(); ++nIt )
4519 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4520 tmpMesh.Copy( &edge );
4523 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4525 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4526 // fill preview data
4528 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4530 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4534 getMeshDS()->MoveNode(node, x, y, z);
4538 if ( !myIsPreviewMode )
4540 TPythonDump() << "nodeID = " << this
4541 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4542 << ", " << nodeID << " )";
4544 declareMeshModified( /*isReComputeSafe=*/false );
4549 SMESH_CATCH( SMESH::throwCorbaException );
4553 //=======================================================================
4555 * Return elements of given type where the given point is IN or ON.
4557 * 'ALL' type means elements of any type excluding nodes
4559 //=======================================================================
4561 SMESH::smIdType_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4564 SMESH::ElementType type)
4567 SMESH::smIdType_array_var res = new SMESH::smIdType_array;
4568 vector< const SMDS_MeshElement* > foundElems;
4570 theSearchersDeleter.Set( myMesh );
4571 if ( !theElementSearcher ) {
4572 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4574 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4575 SMDSAbs_ElementType( type ),
4577 res->length( foundElems.size() );
4578 for ( smIdType i = 0; i < foundElems.size(); ++i )
4579 res[i] = foundElems[i]->GetID();
4583 SMESH_CATCH( SMESH::throwCorbaException );
4587 //=======================================================================
4588 //function : FindAmongElementsByPoint
4589 //purpose : Searching among the given elements, return elements of given type
4590 // where the given point is IN or ON.
4591 // 'ALL' type means elements of any type excluding nodes
4592 //=======================================================================
4594 SMESH::smIdType_array*
4595 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4599 SMESH::ElementType type)
4602 SMESH::smIdType_array_var res = new SMESH::smIdType_array;
4604 prepareIdSource( elementIDs );
4605 if ( type != SMESH::NODE )
4607 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4608 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4609 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4610 type != types[0] ) // but search of elements of dim > 0
4614 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4615 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4616 if ( mesh_i != myMesh_i )
4618 SMESH::SMESH_MeshEditor_var editor=
4619 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4620 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4623 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4624 return FindElementsByPoint( x,y,z, type );
4626 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4628 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4629 if ( !theElementSearcher )
4631 // create a searcher from elementIDs
4632 SMDS_ElemIteratorPtr elemIt;
4633 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4635 //prepareIdSource( elementIDs );
4636 elemIt = myMesh_i->GetElements( elementIDs, type );
4640 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4643 vector< const SMDS_MeshElement* > foundElems;
4645 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4646 SMDSAbs_ElementType( type ),
4648 res->length( foundElems.size() );
4649 for ( smIdType i = 0; i < foundElems.size(); ++i )
4650 res[i] = foundElems[i]->GetID();
4654 SMESH_CATCH( SMESH::throwCorbaException );
4658 //=======================================================================
4659 //function : ProjectPoint
4660 //purpose : Project a point to a mesh object.
4661 // Return ID of an element of given type where the given point is projected
4662 // and coordinates of the projection point.
4663 // In the case if nothing found, return -1 and []
4664 //=======================================================================
4666 SMESH::smIdType SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4669 SMESH::ElementType type,
4670 SMESH::SMESH_IDSource_ptr meshObject,
4671 SMESH::double_array_out projecton)
4673 if ( CORBA::is_nil( meshObject ))
4674 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4678 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4679 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4680 if ( mesh_i != myMesh_i )
4682 SMESH::SMESH_MeshEditor_var editor=
4683 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4684 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4688 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4689 if ( !theElementSearcher )
4691 // create a searcher from meshObject
4693 SMDS_ElemIteratorPtr elemIt;
4694 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4696 prepareIdSource( meshObject );
4697 elemIt = myMesh_i->GetElements( meshObject, type );
4701 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4704 const SMDS_MeshElement* elem = 0;
4705 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4706 SMDSAbs_ElementType( type ),
4709 projecton = new SMESH::double_array();
4710 if ( elem && !elem->IsNull() )
4712 projecton->length( 3 );
4713 projecton[0] = pProj.X();
4714 projecton[1] = pProj.Y();
4715 projecton[2] = pProj.Z();
4716 return elem->GetID();
4719 SMESH_CATCH( SMESH::throwCorbaException );
4723 //=======================================================================
4724 //function : GetPointState
4725 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4726 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4727 //=======================================================================
4729 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4734 theSearchersDeleter.Set( myMesh );
4735 if ( !theElementSearcher ) {
4736 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4738 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4740 SMESH_CATCH( SMESH::throwCorbaException );
4744 //=======================================================================
4745 //function : IsManifold
4746 //purpose : Check if a 2D mesh is manifold
4747 //=======================================================================
4749 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4751 bool isManifold = true;
4754 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4755 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4757 /*closedOnly=*/true,
4759 SMESH_CATCH( SMESH::throwCorbaException );
4764 //=======================================================================
4765 //function : IsCoherentOrientation2D
4766 //purpose : Check if orientation of 2D elements is coherent
4767 //=======================================================================
4769 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4771 bool isGoodOri = true;
4774 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4775 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4777 /*closedOnly=*/true,
4780 SMESH_CATCH( SMESH::throwCorbaException );
4785 //=======================================================================
4786 //function : Get1DBranches
4787 //purpose : Partition given 1D elements into groups of contiguous edges.
4788 // A node where number of meeting edges != 2 is a group end.
4789 // An optional startNode is used to orient groups it belongs to.
4790 //return : a list of edge groups and a list of corresponding node groups.
4791 // If a group is closed, the first and last nodes of the group are same.
4792 //=======================================================================
4794 SMESH::array_of_long_array*
4795 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4796 SMESH::smIdType theStartNode,
4797 SMESH::array_of_long_array_out theNodeGroups )
4799 if ( CORBA::is_nil( theEdges ))
4800 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4802 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4803 theNodeGroups = new SMESH::array_of_long_array;
4807 prepareIdSource( theEdges );
4809 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4810 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4811 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4814 getMeshDS()->FindNode( theStartNode ));
4816 edgeGroupArray->length( edgeBranches.size() );
4817 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4819 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4820 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4821 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4824 theNodeGroups->length( nodeBranches.size() );
4825 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4827 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4828 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4829 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4832 SMESH_CATCH( SMESH::throwCorbaException );
4834 return edgeGroupArray._retn();
4837 //=======================================================================
4838 //function : FindSharpEdges
4839 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4840 //=======================================================================
4842 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4843 CORBA::Boolean theAddExisting)
4845 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4850 std::vector< SMESH_MeshAlgos::Edge > edges =
4851 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4853 if ( myIsPreviewMode ) // fill a preview mesh with edges
4855 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4856 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4857 for ( size_t i = 0; i < edges.size(); ++i )
4859 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4860 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4861 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4862 if ( edges[i]._medium )
4864 xyz1.Set( edges[i]._medium );
4865 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4866 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4870 mesh->GetMeshDS()->AddEdge( n1, n2 );
4876 resultEdges->length( edges.size() );
4877 for ( size_t i = 0; i < edges.size(); ++i )
4879 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4880 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4881 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4884 SMESH_CATCH( SMESH::throwCorbaException );
4885 return resultEdges._retn();
4888 //=======================================================================
4889 //function : FindFreeBorders
4890 //purpose : Returns all or only closed FreeBorder's.
4891 //=======================================================================
4893 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4895 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4898 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4899 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4901 resBorders->length( foundFreeBordes.size() );
4902 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4904 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4905 SMESH::FreeBorder& bordOut = resBorders[i];
4906 bordOut.nodeIDs.length( bordNodes.size() );
4907 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4908 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4911 SMESH_CATCH( SMESH::throwCorbaException );
4913 return resBorders._retn();
4916 //=======================================================================
4917 //function : FillHole
4918 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4919 //=======================================================================
4921 SMESH::SMESH_Group_ptr
4922 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
4923 const char* theGroupName)
4927 if ( theHole.nodeIDs.length() < 4 )
4928 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4929 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4930 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4931 "First and last nodes must be same", SALOME::BAD_PARAM);
4933 SMESH_MeshAlgos::TFreeBorder bordNodes;
4934 bordNodes.resize( theHole.nodeIDs.length() );
4935 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4937 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4938 if ( !bordNodes[ iN ] )
4939 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4940 << " does not exist", SALOME::BAD_PARAM);
4945 // prepare a preview mesh
4946 MeshEditor_I::TPreviewMesh* previewMesh = 0;
4947 SMDS_Mesh* meshDS = getMeshDS();
4948 if ( myIsPreviewMode )
4950 // copy faces sharing nodes of theHole
4951 TIDSortedElemSet holeFaces;
4952 previewMesh = getPreviewMesh( SMDSAbs_Face );
4953 for ( size_t i = 0; i < bordNodes.size(); ++i )
4955 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
4956 while ( fIt->more() )
4958 const SMDS_MeshElement* face = fIt->next();
4959 if ( holeFaces.insert( face ).second )
4960 previewMesh->Copy( face );
4962 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
4963 ASSERT( bordNodes[i] );
4965 meshDS = previewMesh->GetMeshDS();
4969 std::vector<const SMDS_MeshElement*> newFaces;
4970 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
4972 if ( myIsPreviewMode )
4975 previewMesh->Clear();
4976 for ( size_t i = 0; i < newFaces.size(); ++i )
4977 previewMesh->Copy( newFaces[i] );
4981 // return new faces via a group
4982 SMESH::SMESH_Group_var group;
4983 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
4985 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4986 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
4988 SMESH::SMESH_GroupBase_var g = groups[ i ];
4989 if ( g->GetType() != SMESH::FACE ) continue;
4990 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
4991 if ( standalone->_is_nil() ) continue;
4992 CORBA::String_var name = g->GetName();
4993 if ( strcmp( theGroupName, name.in() ) == 0 )
4999 if ( group->_is_nil() )
5000 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5002 if ( !group->_is_nil() )
5004 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5005 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5006 for ( size_t i = 0; i < newFaces.size(); ++i )
5007 grpDS->Add( newFaces[ i ]);
5012 getEditor().ClearLastCreated();
5013 SMESH_SequenceOfElemPtr& aSeq =
5014 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5015 aSeq.swap( newFaces );
5018 if ( group->_is_nil() ) pyDump << "_group = ";
5019 else pyDump << group << " = ";
5020 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5022 return group._retn();
5025 SMESH_CATCH( SMESH::throwCorbaException );
5027 return SMESH::SMESH_Group::_nil();
5030 //=======================================================================
5031 //function : convError
5033 //=======================================================================
5035 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5037 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5041 RETCASE( SEW_BORDER1_NOT_FOUND );
5042 RETCASE( SEW_BORDER2_NOT_FOUND );
5043 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5044 RETCASE( SEW_BAD_SIDE_NODES );
5045 RETCASE( SEW_VOLUMES_TO_SPLIT );
5046 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5047 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5048 RETCASE( SEW_BAD_SIDE1_NODES );
5049 RETCASE( SEW_BAD_SIDE2_NODES );
5050 RETCASE( SEW_INTERNAL_ERROR );
5052 return SMESH::SMESH_MeshEditor::SEW_OK;
5055 //=======================================================================
5057 * Returns groups of FreeBorder's coincident within the given tolerance.
5058 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5059 * to free borders being compared is used.
5061 //=======================================================================
5063 SMESH::CoincidentFreeBorders*
5064 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5066 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5070 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5071 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5073 // copy free borders
5074 aCFB->borders.length( cfb._borders.size() );
5075 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5077 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5078 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5079 aBRD.nodeIDs.length( nodes.size() );
5080 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5081 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5084 // copy coincident parts
5085 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5086 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5088 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5089 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5090 aGRP.length( grp.size() );
5091 for ( size_t iP = 0; iP < grp.size(); ++iP )
5093 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5094 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5095 aPART.border = part._border;
5096 aPART.node1 = part._node1;
5097 aPART.node2 = part._node2;
5098 aPART.nodeLast = part._nodeLast;
5101 SMESH_CATCH( SMESH::doNothing );
5103 TPythonDump() << "CoincidentFreeBorders = "
5104 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5106 return aCFB._retn();
5109 //=======================================================================
5111 * Sew FreeBorder's of each group
5113 //=======================================================================
5115 CORBA::Short SMESH_MeshEditor_i::
5116 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5117 CORBA::Boolean createPolygons,
5118 CORBA::Boolean createPolyhedra)
5120 CORBA::Short nbSewed = 0;
5122 SMESH_MeshAlgos::TFreeBorderVec groups;
5123 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5125 // check the input and collect nodes
5126 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5128 borderNodes.clear();
5129 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5130 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5132 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5133 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5134 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5136 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5138 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5139 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5140 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5141 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5142 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5143 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5145 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5146 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5147 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5148 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5150 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5152 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5154 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5156 borderNodes.push_back( n1 );
5157 borderNodes.push_back( n2 );
5158 borderNodes.push_back( n3 );
5160 groups.push_back( borderNodes );
5163 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5164 // to get nodes that replace other nodes during merge we create 0D elements
5165 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5168 vector< const SMDS_MeshElement* > tmp0Delems;
5169 for ( size_t i = 0; i < groups.size(); ++i )
5171 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5172 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5174 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5176 tmp0Delems.push_back( it0D->next() );
5178 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5182 // cout << endl << "INIT" << endl;
5183 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5185 // cout << i << " ";
5186 // if ( i % 3 == 0 ) cout << "^ ";
5187 // tmp0Delems[i]->GetNode(0)->Print( cout );
5192 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5194 for ( size_t i = 0; i < groups.size(); ++i )
5196 bool isBordToBord = true;
5197 bool groupSewed = false;
5198 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5199 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5201 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5202 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5203 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5205 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5206 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5207 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5209 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5212 // TIDSortedElemSet emptySet, avoidSet;
5213 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5215 // cout << "WRONG 2nd 1" << endl;
5216 // n0->Print( cout );
5217 // n1->Print( cout );
5219 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5221 // cout << "WRONG 2nd 2" << endl;
5222 // n3->Print( cout );
5223 // n4->Print( cout );
5226 if ( !isBordToBord )
5228 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5229 n2 = 0; // and n2 is not used
5231 // 1st border moves to 2nd
5232 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5234 /*2ndIsFreeBorder=*/ isBordToBord,
5235 createPolygons, createPolyhedra);
5236 groupSewed = ( res == ok );
5238 isBordToBord = false;
5239 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5240 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5242 // cout << t << " ";
5243 // if ( t % 3 == 0 ) cout << "^ ";
5244 // tmp0Delems[t]->GetNode(0)->Print( cout );
5247 i0D += nodes.size();
5248 nbSewed += groupSewed;
5251 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5252 << freeBorders << ", "
5253 << createPolygons << ", "
5254 << createPolyhedra << " )";
5256 SMESH_CATCH( SMESH::doNothing );
5258 declareMeshModified( /*isReComputeSafe=*/false );
5260 // remove tmp 0D elements
5262 set< const SMDS_MeshElement* > removed0D;
5263 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5265 if ( removed0D.insert( tmp0Delems[i] ).second )
5266 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5268 SMESH_CATCH( SMESH::throwCorbaException );
5273 //=======================================================================
5274 //function : SewFreeBorders
5276 //=======================================================================
5278 SMESH::SMESH_MeshEditor::Sew_Error
5279 SMESH_MeshEditor_i::SewFreeBorders(SMESH::smIdType FirstNodeID1,
5280 SMESH::smIdType SecondNodeID1,
5281 SMESH::smIdType LastNodeID1,
5282 SMESH::smIdType FirstNodeID2,
5283 SMESH::smIdType SecondNodeID2,
5284 SMESH::smIdType LastNodeID2,
5285 CORBA::Boolean CreatePolygons,
5286 CORBA::Boolean CreatePolyedrs)
5291 SMESHDS_Mesh* aMesh = getMeshDS();
5293 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5294 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5295 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5296 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5297 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5298 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5300 if (!aBorderFirstNode ||
5301 !aBorderSecondNode||
5303 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5304 if (!aSide2FirstNode ||
5305 !aSide2SecondNode ||
5307 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5309 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5310 << FirstNodeID1 << ", "
5311 << SecondNodeID1 << ", "
5312 << LastNodeID1 << ", "
5313 << FirstNodeID2 << ", "
5314 << SecondNodeID2 << ", "
5315 << LastNodeID2 << ", "
5316 << CreatePolygons<< ", "
5317 << CreatePolyedrs<< " )";
5319 SMESH::SMESH_MeshEditor::Sew_Error error =
5320 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5331 declareMeshModified( /*isReComputeSafe=*/false );
5334 SMESH_CATCH( SMESH::throwCorbaException );
5335 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5339 //=======================================================================
5340 //function : SewConformFreeBorders
5342 //=======================================================================
5344 SMESH::SMESH_MeshEditor::Sew_Error
5345 SMESH_MeshEditor_i::SewConformFreeBorders(SMESH::smIdType FirstNodeID1,
5346 SMESH::smIdType SecondNodeID1,
5347 SMESH::smIdType LastNodeID1,
5348 SMESH::smIdType FirstNodeID2,
5349 SMESH::smIdType SecondNodeID2)
5354 SMESHDS_Mesh* aMesh = getMeshDS();
5356 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5357 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5358 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5359 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5360 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5361 const SMDS_MeshNode* aSide2ThirdNode = 0;
5363 if (!aBorderFirstNode ||
5364 !aBorderSecondNode||
5366 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5367 if (!aSide2FirstNode ||
5369 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5371 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5372 << FirstNodeID1 << ", "
5373 << SecondNodeID1 << ", "
5374 << LastNodeID1 << ", "
5375 << FirstNodeID2 << ", "
5376 << SecondNodeID2 << " )";
5378 SMESH::SMESH_MeshEditor::Sew_Error error =
5379 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5388 declareMeshModified( /*isReComputeSafe=*/false );
5391 SMESH_CATCH( SMESH::throwCorbaException );
5392 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5396 //=======================================================================
5397 //function : SewBorderToSide
5399 //=======================================================================
5401 SMESH::SMESH_MeshEditor::Sew_Error
5402 SMESH_MeshEditor_i::SewBorderToSide(SMESH::smIdType FirstNodeIDOnFreeBorder,
5403 SMESH::smIdType SecondNodeIDOnFreeBorder,
5404 SMESH::smIdType LastNodeIDOnFreeBorder,
5405 SMESH::smIdType FirstNodeIDOnSide,
5406 SMESH::smIdType LastNodeIDOnSide,
5407 CORBA::Boolean CreatePolygons,
5408 CORBA::Boolean CreatePolyedrs)
5413 SMESHDS_Mesh* aMesh = getMeshDS();
5415 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5416 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5417 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5418 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5419 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5420 const SMDS_MeshNode* aSide2ThirdNode = 0;
5422 if (!aBorderFirstNode ||
5423 !aBorderSecondNode||
5425 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5426 if (!aSide2FirstNode ||
5428 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5430 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5431 << FirstNodeIDOnFreeBorder << ", "
5432 << SecondNodeIDOnFreeBorder << ", "
5433 << LastNodeIDOnFreeBorder << ", "
5434 << FirstNodeIDOnSide << ", "
5435 << LastNodeIDOnSide << ", "
5436 << CreatePolygons << ", "
5437 << CreatePolyedrs << ") ";
5439 SMESH::SMESH_MeshEditor::Sew_Error error =
5440 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5450 declareMeshModified( /*isReComputeSafe=*/false );
5453 SMESH_CATCH( SMESH::throwCorbaException );
5454 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5458 //=======================================================================
5459 //function : SewSideElements
5461 //=======================================================================
5463 SMESH::SMESH_MeshEditor::Sew_Error
5464 SMESH_MeshEditor_i::SewSideElements(const SMESH::smIdType_array& IDsOfSide1Elements,
5465 const SMESH::smIdType_array& IDsOfSide2Elements,
5466 SMESH::smIdType NodeID1OfSide1ToMerge,
5467 SMESH::smIdType NodeID1OfSide2ToMerge,
5468 SMESH::smIdType NodeID2OfSide1ToMerge,
5469 SMESH::smIdType NodeID2OfSide2ToMerge)
5474 SMESHDS_Mesh* aMesh = getMeshDS();
5476 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5477 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5478 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5479 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5481 if (!aFirstNode1ToMerge ||
5482 !aFirstNode2ToMerge )
5483 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5484 if (!aSecondNode1ToMerge||
5485 !aSecondNode2ToMerge)
5486 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5488 TIDSortedElemSet aSide1Elems, aSide2Elems;
5489 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5490 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5492 TPythonDump() << "error = " << this << ".SewSideElements( "
5493 << IDsOfSide1Elements << ", "
5494 << IDsOfSide2Elements << ", "
5495 << NodeID1OfSide1ToMerge << ", "
5496 << NodeID1OfSide2ToMerge << ", "
5497 << NodeID2OfSide1ToMerge << ", "
5498 << NodeID2OfSide2ToMerge << ")";
5500 SMESH::SMESH_MeshEditor::Sew_Error error =
5501 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5504 aSecondNode1ToMerge,
5505 aSecondNode2ToMerge));
5507 declareMeshModified( /*isReComputeSafe=*/false );
5510 SMESH_CATCH( SMESH::throwCorbaException );
5511 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5514 //================================================================================
5516 * \brief Set new nodes for given element
5517 * \param ide - element id
5518 * \param newIDs - new node ids
5519 * \retval CORBA::Boolean - true if result is OK
5521 //================================================================================
5523 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(SMESH::smIdType ide,
5524 const SMESH::smIdType_array& newIDs)
5529 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5530 if ( !elem ) return false;
5532 int nbn = newIDs.length();
5533 vector<const SMDS_MeshNode*> aNodes(nbn);
5534 for ( int i = 0; i < nbn; i++ ) {
5535 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5538 aNodes[ i ] = aNode;
5540 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5541 << ide << ", " << newIDs << " )";
5543 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5545 declareMeshModified( /*isReComputeSafe=*/ !res );
5549 SMESH_CATCH( SMESH::throwCorbaException );
5553 //=======================================================================
5555 * \brief Makes a part of the mesh quadratic or bi-quadratic
5557 //=======================================================================
5559 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5560 CORBA::Boolean theToBiQuad,
5561 SMESH::SMESH_IDSource_ptr theObject)
5566 TIDSortedElemSet elems;
5568 if ( !( elemsOK = CORBA::is_nil( theObject )))
5570 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5571 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5575 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5576 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5578 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5579 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5581 declareMeshModified( /*isReComputeSafe=*/false );
5584 SMESH_CATCH( SMESH::throwCorbaException );
5587 //=======================================================================
5588 //function : ConvertFromQuadratic
5590 //=======================================================================
5592 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5597 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5598 TPythonDump() << this << ".ConvertFromQuadratic()";
5599 declareMeshModified( /*isReComputeSafe=*/!isDone );
5602 SMESH_CATCH( SMESH::throwCorbaException );
5606 //=======================================================================
5607 //function : ConvertToQuadratic
5609 //=======================================================================
5611 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5613 convertToQuadratic( theForce3d, false );
5614 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5617 //================================================================================
5619 * \brief Makes a part of the mesh quadratic
5621 //================================================================================
5623 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5624 SMESH::SMESH_IDSource_ptr theObject)
5626 convertToQuadratic( theForce3d, false, theObject );
5627 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5630 //================================================================================
5632 * \brief Makes a part of the mesh bi-quadratic
5634 //================================================================================
5636 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5637 SMESH::SMESH_IDSource_ptr theObject)
5639 convertToQuadratic( theForce3d, true, theObject );
5640 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5643 //================================================================================
5645 * \brief Makes a part of the mesh linear
5647 //================================================================================
5649 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5656 TIDSortedElemSet elems;
5657 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5659 if ( elems.empty() )
5661 ConvertFromQuadratic();
5663 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5665 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5669 getEditor().ConvertFromQuadratic(elems);
5672 declareMeshModified( /*isReComputeSafe=*/false );
5674 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5676 SMESH_CATCH( SMESH::throwCorbaException );
5679 //=======================================================================
5680 //function : makeMesh
5681 //purpose : create a named imported mesh
5682 //=======================================================================
5684 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5686 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5687 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5688 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5689 gen->SetName( meshSO, theMeshName, "Mesh" );
5690 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5692 return mesh._retn();
5695 //=======================================================================
5696 //function : dumpGroupsList
5698 //=======================================================================
5700 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5701 const SMESH::ListOfGroups * theGroupList)
5703 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5704 if ( isDumpGroupList )
5705 theDumpPython << theGroupList << " = ";
5708 //================================================================================
5710 \brief Generates the unique group name.
5711 \param thePrefix name prefix
5714 //================================================================================
5716 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5718 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5719 set<std::string> groupNames;
5721 // Get existing group names
5722 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5723 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5724 if (CORBA::is_nil(aGroup))
5727 CORBA::String_var name = aGroup->GetName();
5728 groupNames.insert( name.in() );
5732 std::string name = thePrefix;
5735 while (!groupNames.insert(name).second)
5736 name = SMESH_Comment( thePrefix ) << "_" << index++;
5741 //================================================================================
5743 * \brief Prepare SMESH_IDSource for work
5745 //================================================================================
5747 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5749 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5751 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5752 filter->SetMesh( mesh );
5755 //================================================================================
5757 * \brief Retrieve elements of given type from SMESH_IDSource
5759 //================================================================================
5761 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5762 const SMESHDS_Mesh* theMeshDS,
5763 TIDSortedElemSet& theElemSet,
5764 const SMDSAbs_ElementType theType,
5765 const bool emptyIfIsMesh,
5766 IDSource_Error* error)
5769 if ( error ) *error = IDSource_OK;
5771 if ( CORBA::is_nil( theIDSource ))
5773 if ( error ) *error = IDSource_INVALID;
5776 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5778 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5779 *error = IDSource_EMPTY;
5782 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5784 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5785 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5786 if ( mesh_i && mesh_i != myMesh_i )
5789 *error = IDSource_INVALID;
5793 prepareIdSource( theIDSource );
5794 SMESH::smIdType_array_var anIDs = theIDSource->GetIDs();
5795 if ( anIDs->length() == 0 )
5797 if ( error ) *error = IDSource_EMPTY;
5800 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5801 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5803 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5805 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5809 if ( error ) *error = IDSource_INVALID;
5815 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5816 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5818 if ( error ) *error = IDSource_INVALID;
5825 //================================================================================
5827 * \brief Duplicates given elements, i.e. creates new elements based on the
5828 * same nodes as the given ones.
5829 * \param theElements - container of elements to duplicate.
5830 * \param theGroupName - a name of group to contain the generated elements.
5831 * If a group with such a name already exists, the new elements
5832 * are added to the existing group, else a new group is created.
5833 * If \a theGroupName is empty, new elements are not added
5835 * \return a group where the new elements are added. NULL if theGroupName == "".
5838 //================================================================================
5840 SMESH::SMESH_Group_ptr
5841 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5842 const char* theGroupName)
5844 SMESH::SMESH_Group_var newGroup;
5851 TIDSortedElemSet elems;
5852 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5854 getEditor().DoubleElements( elems );
5856 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5859 SMESH::ElementType type =
5860 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5861 // find existing group
5862 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5863 for ( size_t i = 0; i < groups->length(); ++i )
5864 if ( groups[i]->GetType() == type )
5866 CORBA::String_var name = groups[i]->GetName();
5867 if ( strcmp( name, theGroupName ) == 0 ) {
5868 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5872 // create a new group
5873 if ( newGroup->_is_nil() )
5874 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5876 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5878 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5879 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5880 for ( size_t i = 0; i < aSeq.size(); i++ )
5881 groupDS->SMDSGroup().Add( aSeq[i] );
5886 if ( !newGroup->_is_nil() )
5887 pyDump << newGroup << " = ";
5888 pyDump << this << ".DoubleElements( "
5889 << theElements << ", " << "'" << theGroupName <<"')";
5891 SMESH_CATCH( SMESH::throwCorbaException );
5893 return newGroup._retn();
5896 //================================================================================
5898 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5899 \param theNodes - identifiers of nodes to be doubled
5900 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5901 nodes. If list of element identifiers is empty then nodes are doubled but
5902 they not assigned to elements
5903 \return TRUE if operation has been completed successfully, FALSE otherwise
5904 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5906 //================================================================================
5908 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::smIdType_array& theNodes,
5909 const SMESH::smIdType_array& theModifiedElems )
5914 list< int > aListOfNodes;
5916 for ( i = 0, n = theNodes.length(); i < n; i++ )
5917 aListOfNodes.push_back( theNodes[ i ] );
5919 list< int > aListOfElems;
5920 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5921 aListOfElems.push_back( theModifiedElems[ i ] );
5923 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5925 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5927 // Update Python script
5928 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5932 SMESH_CATCH( SMESH::throwCorbaException );
5936 //================================================================================
5938 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5939 This method provided for convenience works as DoubleNodes() described above.
5940 \param theNodeId - identifier of node to be doubled.
5941 \param theModifiedElems - identifiers of elements to be updated.
5942 \return TRUE if operation has been completed successfully, FALSE otherwise
5943 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5945 //================================================================================
5947 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( SMESH::smIdType theNodeId,
5948 const SMESH::smIdType_array& theModifiedElems )
5951 SMESH::smIdType_array_var aNodes = new SMESH::smIdType_array;
5952 aNodes->length( 1 );
5953 aNodes[ 0 ] = theNodeId;
5955 TPythonDump pyDump; // suppress dump by the next line
5957 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5959 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5963 SMESH_CATCH( SMESH::throwCorbaException );
5967 //================================================================================
5969 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5970 This method provided for convenience works as DoubleNodes() described above.
5971 \param theNodes - group of nodes to be doubled.
5972 \param theModifiedElems - group of elements to be updated.
5973 \return TRUE if operation has been completed successfully, FALSE otherwise
5974 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5976 //================================================================================
5978 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5979 SMESH::SMESH_GroupBase_ptr theModifiedElems )
5982 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5985 SMESH::smIdType_array_var aNodes = theNodes->GetListOfID();
5986 SMESH::smIdType_array_var aModifiedElems;
5987 if ( !CORBA::is_nil( theModifiedElems ) )
5988 aModifiedElems = theModifiedElems->GetListOfID();
5990 aModifiedElems = new SMESH::smIdType_array;
5992 TPythonDump pyDump; // suppress dump by the next line
5994 bool done = DoubleNodes( aNodes, aModifiedElems );
5996 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6000 SMESH_CATCH( SMESH::throwCorbaException );
6004 //================================================================================
6006 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6007 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6008 * \param theNodes - group of nodes to be doubled.
6009 * \param theModifiedElems - group of elements to be updated.
6010 * \return a new group with newly created nodes
6011 * \sa DoubleNodeGroup()
6013 //================================================================================
6015 SMESH::SMESH_Group_ptr
6016 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6017 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6020 SMESH::SMESH_Group_var aNewGroup;
6022 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6023 return aNewGroup._retn();
6026 SMESH::smIdType_array_var aNodes = theNodes->GetListOfID();
6027 SMESH::smIdType_array_var aModifiedElems;
6028 if ( !CORBA::is_nil( theModifiedElems ) )
6029 aModifiedElems = theModifiedElems->GetListOfID();
6031 aModifiedElems = new SMESH::smIdType_array;
6032 aModifiedElems->length( 0 );
6035 TPythonDump pyDump; // suppress dump by the next line
6037 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6040 // Create group with newly created nodes
6041 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6042 if (anIds->length() > 0) {
6043 std::string anUnindexedName (theNodes->GetName());
6044 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6045 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6046 aNewGroup->Add(anIds);
6047 pyDump << aNewGroup << " = ";
6051 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6052 << theModifiedElems << " )";
6054 return aNewGroup._retn();
6056 SMESH_CATCH( SMESH::throwCorbaException );
6060 //================================================================================
6062 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6063 This method provided for convenience works as DoubleNodes() described above.
6064 \param theNodes - list of groups of nodes to be doubled
6065 \param theModifiedElems - list of groups of elements to be updated.
6066 \return TRUE if operation has been completed successfully, FALSE otherwise
6067 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6069 //================================================================================
6071 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6072 const SMESH::ListOfGroups& theModifiedElems )
6077 std::list< int > aNodes;
6078 smIdType i, n, j, m;
6079 for ( i = 0, n = theNodes.length(); i < n; i++ )
6081 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6082 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6084 SMESH::smIdType_array_var aCurr = aGrp->GetListOfID();
6085 for ( j = 0, m = aCurr->length(); j < m; j++ )
6086 aNodes.push_back( aCurr[ j ] );
6090 std::list< int > anElems;
6091 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6093 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6094 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6096 SMESH::smIdType_array_var aCurr = aGrp->GetListOfID();
6097 for ( j = 0, m = aCurr->length(); j < m; j++ )
6098 anElems.push_back( aCurr[ j ] );
6102 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6104 declareMeshModified( /*isReComputeSafe=*/false );
6106 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6110 SMESH_CATCH( SMESH::throwCorbaException );
6114 //================================================================================
6116 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6117 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6118 * \param theNodes - group of nodes to be doubled.
6119 * \param theModifiedElems - group of elements to be updated.
6120 * \return a new group with newly created nodes
6121 * \sa DoubleNodeGroups()
6123 //================================================================================
6125 SMESH::SMESH_Group_ptr
6126 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6127 const SMESH::ListOfGroups& theModifiedElems )
6129 SMESH::SMESH_Group_var aNewGroup;
6131 TPythonDump pyDump; // suppress dump by the next line
6133 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6137 // Create group with newly created nodes
6138 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6139 if (anIds->length() > 0) {
6140 std::string anUnindexedName (theNodes[0]->GetName());
6141 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6142 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6143 aNewGroup->Add(anIds);
6144 pyDump << aNewGroup << " = ";
6148 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6149 << theModifiedElems << " )";
6151 return aNewGroup._retn();
6155 //================================================================================
6157 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6158 \param theElems - the list of elements (edges or faces) to be replicated
6159 The nodes for duplication could be found from these elements
6160 \param theNodesNot - list of nodes to NOT replicate
6161 \param theAffectedElems - the list of elements (cells and edges) to which the
6162 replicated nodes should be associated to.
6163 \return TRUE if operation has been completed successfully, FALSE otherwise
6164 \sa DoubleNodeGroup(), DoubleNodeGroups()
6166 //================================================================================
6168 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::smIdType_array& theElems,
6169 const SMESH::smIdType_array& theNodesNot,
6170 const SMESH::smIdType_array& theAffectedElems )
6175 SMESHDS_Mesh* aMeshDS = getMeshDS();
6176 TIDSortedElemSet anElems, aNodes, anAffected;
6177 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6178 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6179 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6181 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6183 // Update Python script
6184 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6185 << theNodesNot << ", " << theAffectedElems << " )";
6187 declareMeshModified( /*isReComputeSafe=*/false );
6190 SMESH_CATCH( SMESH::throwCorbaException );
6194 //================================================================================
6196 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6197 \param theElems - the list of elements (edges or faces) to be replicated
6198 The nodes for duplication could be found from these elements
6199 \param theNodesNot - list of nodes to NOT replicate
6200 \param theShape - shape to detect affected elements (element which geometric center
6201 located on or inside shape).
6202 The replicated nodes should be associated to affected elements.
6203 \return TRUE if operation has been completed successfully, FALSE otherwise
6204 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6206 //================================================================================
6208 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::smIdType_array& theElems,
6209 const SMESH::smIdType_array& theNodesNot,
6210 GEOM::GEOM_Object_ptr theShape )
6216 SMESHDS_Mesh* aMeshDS = getMeshDS();
6217 TIDSortedElemSet anElems, aNodes;
6218 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6219 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6221 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6222 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6224 // Update Python script
6225 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6226 << theNodesNot << ", " << theShape << " )";
6228 declareMeshModified( /*isReComputeSafe=*/false );
6231 SMESH_CATCH( SMESH::throwCorbaException );
6235 //================================================================================
6237 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6238 \param theElems - group of of elements (edges or faces) to be replicated
6239 \param theNodesNot - group of nodes not to replicated
6240 \param theAffectedElems - group of elements to which the replicated nodes
6241 should be associated to.
6242 \return TRUE if operation has been completed successfully, FALSE otherwise
6243 \sa DoubleNodes(), DoubleNodeGroups()
6245 //================================================================================
6248 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6249 SMESH::SMESH_GroupBase_ptr theNodesNot,
6250 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6253 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6259 SMESHDS_Mesh* aMeshDS = getMeshDS();
6260 TIDSortedElemSet anElems, aNodes, anAffected;
6261 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6262 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6263 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6265 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6267 // Update Python script
6268 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6269 << theNodesNot << ", " << theAffectedElems << " )";
6271 declareMeshModified( /*isReComputeSafe=*/false );
6274 SMESH_CATCH( SMESH::throwCorbaException );
6278 //================================================================================
6280 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6281 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6282 * \param theElems - group of of elements (edges or faces) to be replicated
6283 * \param theNodesNot - group of nodes not to replicated
6284 * \param theAffectedElems - group of elements to which the replicated nodes
6285 * should be associated to.
6286 * \return a new group with newly created elements
6287 * \sa DoubleNodeElemGroup()
6289 //================================================================================
6291 SMESH::SMESH_Group_ptr
6292 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6293 SMESH::SMESH_GroupBase_ptr theNodesNot,
6294 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6297 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6301 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6302 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6304 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6306 << theNodesNot << ", "
6307 << theAffectedElems << " )";
6309 return elemGroup._retn();
6312 //================================================================================
6314 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6315 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6316 * \param theElems - group of of elements (edges or faces) to be replicated
6317 * \param theNodesNot - group of nodes not to replicated
6318 * \param theAffectedElems - group of elements to which the replicated nodes
6319 * should be associated to.
6320 * \return a new group with newly created elements
6321 * \sa DoubleNodeElemGroup()
6323 //================================================================================
6325 SMESH::ListOfGroups*
6326 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6327 SMESH::SMESH_GroupBase_ptr theNodesNot,
6328 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6329 CORBA::Boolean theElemGroupNeeded,
6330 CORBA::Boolean theNodeGroupNeeded)
6333 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6334 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6335 aTwoGroups->length( 2 );
6337 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6338 return aTwoGroups._retn();
6343 SMESHDS_Mesh* aMeshDS = getMeshDS();
6344 TIDSortedElemSet anElems, aNodes, anAffected;
6345 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6346 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6347 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6350 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6352 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6358 // Create group with newly created elements
6359 CORBA::String_var elemGroupName = theElems->GetName();
6360 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6361 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6363 SMESH::smIdType_array_var anIds = GetLastCreatedElems();
6364 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6365 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6366 aNewElemGroup->Add(anIds);
6368 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6370 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6371 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6372 aNewNodeGroup->Add(anIds);
6376 // Update Python script
6379 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6380 else pyDump << aNewElemGroup << ", ";
6381 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6382 else pyDump << aNewNodeGroup << " ] = ";
6384 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6385 << theNodesNot << ", "
6386 << theAffectedElems << ", "
6387 << theElemGroupNeeded << ", "
6388 << theNodeGroupNeeded <<" )";
6390 aTwoGroups[0] = aNewElemGroup._retn();
6391 aTwoGroups[1] = aNewNodeGroup._retn();
6392 return aTwoGroups._retn();
6394 SMESH_CATCH( SMESH::throwCorbaException );
6398 //================================================================================
6400 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6401 \param theElems - group of of elements (edges or faces) to be replicated
6402 \param theNodesNot - group of nodes not to replicated
6403 \param theShape - shape to detect affected elements (element which geometric center
6404 located on or inside shape).
6405 The replicated nodes should be associated to affected elements.
6406 \return TRUE if operation has been completed successfully, FALSE otherwise
6407 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6409 //================================================================================
6412 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6413 SMESH::SMESH_GroupBase_ptr theNodesNot,
6414 GEOM::GEOM_Object_ptr theShape )
6417 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6423 SMESHDS_Mesh* aMeshDS = getMeshDS();
6424 TIDSortedElemSet anElems, aNodes, anAffected;
6425 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6426 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6428 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6429 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6432 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6434 // Update Python script
6435 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6436 << theNodesNot << ", " << theShape << " )";
6439 SMESH_CATCH( SMESH::throwCorbaException );
6443 //================================================================================
6445 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6446 * \param [in] theGrpList - groups
6447 * \param [in] theMeshDS - mesh
6448 * \param [out] theElemSet - set of elements
6449 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6451 //================================================================================
6453 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6454 SMESHDS_Mesh* theMeshDS,
6455 TIDSortedElemSet& theElemSet,
6456 const bool theIsNodeGrp)
6458 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6460 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6461 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6462 : aGrp->GetType() != SMESH::NODE ) )
6464 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6465 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6470 //================================================================================
6472 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6473 This method provided for convenience works as DoubleNodes() described above.
6474 \param theElems - list of groups of elements (edges or faces) to be replicated
6475 \param theNodesNot - list of groups of nodes not to replicated
6476 \param theAffectedElems - group of elements to which the replicated nodes
6477 should be associated to.
6478 \return TRUE if operation has been completed successfully, FALSE otherwise
6479 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6481 //================================================================================
6484 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6485 const SMESH::ListOfGroups& theNodesNot,
6486 const SMESH::ListOfGroups& theAffectedElems)
6492 SMESHDS_Mesh* aMeshDS = getMeshDS();
6493 TIDSortedElemSet anElems, aNodes, anAffected;
6494 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6495 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6496 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6498 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6500 // Update Python script
6501 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6502 << &theNodesNot << ", " << &theAffectedElems << " )";
6504 declareMeshModified( /*isReComputeSafe=*/false );
6507 SMESH_CATCH( SMESH::throwCorbaException );
6511 //================================================================================
6513 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6514 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6515 \param theElems - list of groups of elements (edges or faces) to be replicated
6516 \param theNodesNot - list of groups of nodes not to replicated
6517 \param theAffectedElems - group of elements to which the replicated nodes
6518 should be associated to.
6519 * \return a new group with newly created elements
6520 * \sa DoubleNodeElemGroups()
6522 //================================================================================
6524 SMESH::SMESH_Group_ptr
6525 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6526 const SMESH::ListOfGroups& theNodesNot,
6527 const SMESH::ListOfGroups& theAffectedElems)
6530 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6534 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6535 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6537 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6539 << theNodesNot << ", "
6540 << theAffectedElems << " )";
6542 return elemGroup._retn();
6545 //================================================================================
6547 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6548 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6549 \param theElems - list of groups of elements (edges or faces) to be replicated
6550 \param theNodesNot - list of groups of nodes not to replicated
6551 \param theAffectedElems - group of elements to which the replicated nodes
6552 should be associated to.
6553 * \return a new group with newly created elements
6554 * \sa DoubleNodeElemGroups()
6556 //================================================================================
6558 SMESH::ListOfGroups*
6559 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6560 const SMESH::ListOfGroups& theNodesNot,
6561 const SMESH::ListOfGroups& theAffectedElems,
6562 CORBA::Boolean theElemGroupNeeded,
6563 CORBA::Boolean theNodeGroupNeeded)
6566 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6567 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6568 aTwoGroups->length( 2 );
6573 SMESHDS_Mesh* aMeshDS = getMeshDS();
6574 TIDSortedElemSet anElems, aNodes, anAffected;
6575 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6576 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6577 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6579 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6581 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6586 // Create group with newly created elements
6587 CORBA::String_var elemGroupName = theElems[0]->GetName();
6588 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6589 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6591 SMESH::smIdType_array_var anIds = GetLastCreatedElems();
6592 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6593 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6594 aNewElemGroup->Add(anIds);
6596 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6598 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6599 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6600 aNewNodeGroup->Add(anIds);
6604 // Update Python script
6607 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6608 else pyDump << aNewElemGroup << ", ";
6609 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6610 else pyDump << aNewNodeGroup << " ] = ";
6612 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6613 << &theNodesNot << ", "
6614 << &theAffectedElems << ", "
6615 << theElemGroupNeeded << ", "
6616 << theNodeGroupNeeded << " )";
6618 aTwoGroups[0] = aNewElemGroup._retn();
6619 aTwoGroups[1] = aNewNodeGroup._retn();
6620 return aTwoGroups._retn();
6622 SMESH_CATCH( SMESH::throwCorbaException );
6626 //================================================================================
6628 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6629 This method provided for convenience works as DoubleNodes() described above.
6630 \param theElems - list of groups of elements (edges or faces) to be replicated
6631 \param theNodesNot - list of groups of nodes not to replicated
6632 \param theShape - shape to detect affected elements (element which geometric center
6633 located on or inside shape).
6634 The replicated nodes should be associated to affected elements.
6635 \return TRUE if operation has been completed successfully, FALSE otherwise
6636 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6638 //================================================================================
6641 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6642 const SMESH::ListOfGroups& theNodesNot,
6643 GEOM::GEOM_Object_ptr theShape )
6649 SMESHDS_Mesh* aMeshDS = getMeshDS();
6650 TIDSortedElemSet anElems, aNodes;
6651 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6652 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6654 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6655 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6657 // Update Python script
6658 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6659 << &theNodesNot << ", " << theShape << " )";
6661 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6664 SMESH_CATCH( SMESH::throwCorbaException );
6668 //================================================================================
6670 \brief Identify the elements that will be affected by node duplication (actual
6671 duplication is not performed.
6672 This method is the first step of DoubleNodeElemGroupsInRegion.
6673 \param theElems - list of groups of elements (edges or faces) to be replicated
6674 \param theNodesNot - list of groups of nodes not to replicated
6675 \param theShape - shape to detect affected elements (element which geometric center
6676 located on or inside shape).
6677 The replicated nodes should be associated to affected elements.
6678 \return groups of affected elements
6679 \sa DoubleNodeElemGroupsInRegion()
6681 //================================================================================
6682 SMESH::ListOfGroups*
6683 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6684 const SMESH::ListOfGroups& theNodesNot,
6685 GEOM::GEOM_Object_ptr theShape )
6688 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6689 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6690 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6691 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6695 ::SMESH_MeshEditor aMeshEditor(myMesh);
6697 SMESHDS_Mesh* aMeshDS = getMeshDS();
6698 TIDSortedElemSet anElems, aNodes;
6699 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6700 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6701 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6703 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6704 TIDSortedElemSet anAffected;
6705 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6707 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6710 if ( aResult && anAffected.size() > 0 )
6712 SMESH::smIdType_array_var volumeIds = new SMESH::smIdType_array;
6713 SMESH::smIdType_array_var faceIds = new SMESH::smIdType_array;
6714 SMESH::smIdType_array_var edgeIds = new SMESH::smIdType_array;
6715 volumeIds->length( anAffected.size() );
6716 faceIds ->length( anAffected.size() );
6717 edgeIds ->length( anAffected.size() );
6722 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6723 for (; eIt != anAffected.end(); ++eIt)
6725 const SMDS_MeshElement* anElem = *eIt;
6726 int elemId = anElem->GetID();
6727 switch ( anElem->GetType() ) {
6728 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6729 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6730 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6734 volumeIds->length(ivol);
6735 faceIds->length(iface);
6736 edgeIds->length(iedge);
6741 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6742 GenerateGroupName("affectedVolumes").c_str());
6743 aNewVolumeGroup->Add(volumeIds);
6744 aListOfGroups->length( nbGroups+1 );
6745 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6749 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6750 GenerateGroupName("affectedFaces").c_str());
6751 aNewFaceGroup->Add(faceIds);
6752 aListOfGroups->length( nbGroups+1 );
6753 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6757 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6758 GenerateGroupName("affectedEdges").c_str());
6759 aNewEdgeGroup->Add(edgeIds);
6760 aListOfGroups->length( nbGroups+1 );
6761 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6765 // Update Python script
6767 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6768 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6770 return aListOfGroups._retn();
6772 SMESH_CATCH( SMESH::throwCorbaException );
6776 //================================================================================
6778 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6779 The created 2D mesh elements based on nodes of free faces of boundary volumes
6780 \return TRUE if operation has been completed successfully, FALSE otherwise
6782 //================================================================================
6784 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6789 bool aResult = getEditor().Make2DMeshFrom3D();
6791 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6793 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6796 SMESH_CATCH( SMESH::throwCorbaException );
6800 //================================================================================
6802 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6803 * The list of groups must contain at least two groups. The groups have to be disjoint:
6804 * no common element into two different groups.
6805 * The nodes of the internal faces at the boundaries of the groups are doubled.
6806 * Optionally, the internal faces are replaced by flat elements.
6807 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6808 * The flat elements are stored in groups of volumes.
6809 * These groups are named according to the position of the group in the list:
6810 * 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.
6811 * 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.
6812 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6813 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6814 * \param theDomains - list of groups of volumes
6815 * \param createJointElems - if TRUE, create the elements
6816 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6817 * the boundary between \a theDomains and the rest mesh
6818 * \return TRUE if operation has been completed successfully, FALSE otherwise
6820 //================================================================================
6823 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6824 CORBA::Boolean createJointElems,
6825 CORBA::Boolean onAllBoundaries )
6832 SMESHDS_Mesh* aMeshDS = getMeshDS();
6834 // MESSAGE("theDomains.length = "<<theDomains.length());
6835 if ( theDomains.length() <= 1 && !onAllBoundaries )
6836 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6838 vector<TIDSortedElemSet> domains;
6839 domains.resize( theDomains.length() );
6841 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6843 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6844 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6846 // if ( aGrp->GetType() != SMESH::VOLUME )
6847 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6848 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6849 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6853 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6854 // TODO publish the groups of flat elements in study
6856 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6858 // Update Python script
6859 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6860 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6862 SMESH_CATCH( SMESH::throwCorbaException );
6864 myMesh_i->CreateGroupServants(); // publish created groups if any
6869 //================================================================================
6871 * \brief Double nodes on some external faces and create flat elements.
6872 * Flat elements are mainly used by some types of mechanic calculations.
6874 * Each group of the list must be constituted of faces.
6875 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6876 * @param theGroupsOfFaces - list of groups of faces
6877 * @return TRUE if operation has been completed successfully, FALSE otherwise
6879 //================================================================================
6882 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6887 SMESHDS_Mesh* aMeshDS = getMeshDS();
6889 vector<TIDSortedElemSet> faceGroups;
6892 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6894 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6895 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6897 TIDSortedElemSet faceGroup;
6899 faceGroups.push_back(faceGroup);
6900 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6901 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6905 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6906 // TODO publish the groups of flat elements in study
6908 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6910 // Update Python script
6911 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6914 SMESH_CATCH( SMESH::throwCorbaException );
6918 //================================================================================
6920 * \brief Identify all the elements around a geom shape, get the faces delimiting
6923 * Build groups of volume to remove, groups of faces to replace on the skin of the
6924 * object, groups of faces to remove inside the object, (idem edges).
6925 * Build ordered list of nodes at the border of each group of faces to replace
6926 * (to be used to build a geom subshape).
6928 //================================================================================
6930 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6931 GEOM::GEOM_Object_ptr theShape,
6932 const char* groupName,
6933 const SMESH::double_array& theNodesCoords,
6934 SMESH::array_of_long_array_out GroupsOfNodes)
6939 std::vector<std::vector<int> > aListOfListOfNodes;
6940 ::SMESH_MeshEditor aMeshEditor( myMesh );
6942 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6943 if ( !theNodeSearcher )
6944 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6946 vector<double> nodesCoords;
6947 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
6949 nodesCoords.push_back( theNodesCoords[i] );
6952 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6953 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6954 nodesCoords, aListOfListOfNodes);
6956 GroupsOfNodes = new SMESH::array_of_long_array;
6957 GroupsOfNodes->length( aListOfListOfNodes.size() );
6958 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6959 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6961 vector<int>& aListOfNodes = *llIt;
6962 vector<int>::iterator lIt = aListOfNodes.begin();;
6963 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6964 aGroup.length( aListOfNodes.size() );
6965 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6966 aGroup[ j ] = (*lIt);
6968 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6971 << ", '" << groupName << "', "
6972 << theNodesCoords << " )";
6974 SMESH_CATCH( SMESH::throwCorbaException );
6977 // issue 20749 ===================================================================
6979 * \brief Creates missing boundary elements
6980 * \param elements - elements whose boundary is to be checked
6981 * \param dimension - defines type of boundary elements to create
6982 * \param groupName - a name of group to store created boundary elements in,
6983 * "" means not to create the group
6984 * \param meshName - a name of new mesh to store created boundary elements in,
6985 * "" means not to create the new mesh
6986 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
6987 * \param toCopyExistingBondary - if true, not only new but also pre-existing
6988 * boundary elements will be copied into the new mesh
6989 * \param group - returns the create group, if any
6990 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
6992 // ================================================================================
6994 SMESH::SMESH_Mesh_ptr
6995 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
6996 SMESH::Bnd_Dimension dim,
6997 const char* groupName,
6998 const char* meshName,
6999 CORBA::Boolean toCopyElements,
7000 CORBA::Boolean toCopyExistingBondary,
7001 SMESH::SMESH_Group_out group)
7006 if ( dim > SMESH::BND_1DFROM2D )
7007 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7009 SMESHDS_Mesh* aMeshDS = getMeshDS();
7011 SMESH::SMESH_Mesh_var mesh_var;
7012 SMESH::SMESH_Group_var group_var;
7016 TIDSortedElemSet elements;
7017 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7018 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7022 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7023 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7025 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7027 // group of new boundary elements
7028 SMESH_Group* smesh_group = 0;
7029 if ( strlen(groupName) )
7031 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7032 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7033 smesh_group = group_i->GetSmeshGroup();
7037 getEditor().MakeBoundaryMesh( elements,
7038 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7042 toCopyExistingBondary);
7045 smesh_mesh->GetMeshDS()->Modified();
7048 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7050 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7051 if ( mesh_var->_is_nil() )
7052 pyDump << myMesh_i->_this() << ", ";
7054 pyDump << mesh_var << ", ";
7055 if ( group_var->_is_nil() )
7056 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7058 pyDump << group_var << " = ";
7059 pyDump << this << ".MakeBoundaryMesh( "
7061 << "SMESH." << dimName[int(dim)] << ", "
7062 << "'" << groupName << "', "
7063 << "'" << meshName<< "', "
7064 << toCopyElements << ", "
7065 << toCopyExistingBondary << ")";
7067 group = group_var._retn();
7068 return mesh_var._retn();
7070 SMESH_CATCH( SMESH::throwCorbaException );
7071 return SMESH::SMESH_Mesh::_nil();
7074 //================================================================================
7076 * \brief Creates missing boundary elements
7077 * \param dimension - defines type of boundary elements to create
7078 * \param groupName - a name of group to store all boundary elements in,
7079 * "" means not to create the group
7080 * \param meshName - a name of a new mesh, which is a copy of the initial
7081 * mesh + created boundary elements; "" means not to create the new mesh
7082 * \param toCopyAll - if true, the whole initial mesh will be copied into
7083 * the new mesh else only boundary elements will be copied into the new mesh
7084 * \param groups - optional groups of elements to make boundary around
7085 * \param mesh - returns the mesh where elements were added to
7086 * \param group - returns the created group, if any
7087 * \retval long - number of added boundary elements
7089 //================================================================================
7091 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7092 const char* groupName,
7093 const char* meshName,
7094 CORBA::Boolean toCopyAll,
7095 const SMESH::ListOfIDSources& groups,
7096 SMESH::SMESH_Mesh_out mesh,
7097 SMESH::SMESH_Group_out group)
7102 if ( dim > SMESH::BND_1DFROM2D )
7103 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7105 // separate groups belonging to this and other mesh
7106 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7107 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7108 groupsOfThisMesh ->length( groups.length() );
7109 groupsOfOtherMesh->length( groups.length() );
7110 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7111 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7113 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7114 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7115 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7117 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7118 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7119 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7121 groupsOfThisMesh->length( nbGroups );
7122 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7127 if ( nbGroupsOfOtherMesh > 0 )
7129 // process groups belonging to another mesh
7130 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7131 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7132 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7133 groupsOfOtherMesh, mesh, group );
7136 SMESH::SMESH_Mesh_var mesh_var;
7137 SMESH::SMESH_Group_var group_var;
7140 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7141 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7145 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7147 /*toCopyGroups=*/false,
7148 /*toKeepIDs=*/true);
7150 mesh_var = makeMesh(meshName);
7152 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7153 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7156 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7157 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7159 // group of boundary elements
7160 SMESH_Group* smesh_group = 0;
7161 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7162 if ( strlen( groupName ))
7164 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7165 group_var = mesh_i->CreateGroup( groupType, groupName );
7166 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7167 smesh_group = group_i->GetSmeshGroup();
7170 TIDSortedElemSet elements;
7172 if ( groups.length() > 0 )
7174 for ( int i = 0; i < nbGroups; ++i )
7177 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7179 SMESH::Bnd_Dimension bdim =
7180 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7181 nbAdded += getEditor().MakeBoundaryMesh( elements,
7182 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7185 /*toCopyElements=*/false,
7186 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7187 /*toAddExistingBondary=*/true,
7188 /*aroundElements=*/true);
7194 nbAdded += getEditor().MakeBoundaryMesh( elements,
7195 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7198 /*toCopyElements=*/false,
7199 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7200 /*toAddExistingBondary=*/true);
7202 tgtMesh->GetMeshDS()->Modified();
7204 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7206 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7207 pyDump << "nbAdded, ";
7208 if ( mesh_var->_is_nil() )
7209 pyDump << myMesh_i->_this() << ", ";
7211 pyDump << mesh_var << ", ";
7212 if ( group_var->_is_nil() )
7213 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7215 pyDump << group_var << " = ";
7216 pyDump << this << ".MakeBoundaryElements( "
7217 << "SMESH." << dimName[int(dim)] << ", "
7218 << "'" << groupName << "', "
7219 << "'" << meshName<< "', "
7220 << toCopyAll << ", "
7223 mesh = mesh_var._retn();
7224 group = group_var._retn();
7227 SMESH_CATCH( SMESH::throwCorbaException );
7231 //================================================================================
7233 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7234 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7235 * plane passing through pairs of points specified by each PolySegment structure.
7236 * If there are several paths connecting a pair of points, the shortest path is
7237 * selected by the module. Position of the cutting plane is defined by the two
7238 * points and an optional vector lying on the plane specified by a PolySegment.
7239 * By default the vector is defined by Mesh module as following. A middle point
7240 * of the two given points is computed. The middle point is projected to the mesh.
7241 * The vector goes from the middle point to the projection point. In case of planar
7242 * mesh, the vector is normal to the mesh.
7243 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7244 * Return the used vector and position of the middle point.
7245 * \param [in] groupName - optional name of a group where created mesh segments will
7248 //================================================================================
7250 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7251 const char* theGroupName)
7253 if ( theSegments.length() == 0 )
7254 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7255 if ( myMesh->NbFaces() == 0 )
7256 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7259 initData(/*deleteSearchers=*/false);
7261 SMESHDS_Group* groupDS = 0;
7262 SMESHDS_Mesh* meshDS = getMeshDS();
7263 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7265 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7266 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7267 while ( faceIt->more() )
7268 tmpMesh->Copy( faceIt->next() );
7269 meshDS = tmpMesh->GetMeshDS();
7271 else if ( theGroupName[0] ) // find/create a group of segments
7273 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7274 // while ( !groupDS && grpIt->more() )
7276 // SMESH_Group* group = grpIt->next();
7277 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7278 // strcmp( group->GetName(), theGroupName ) == 0 )
7280 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7285 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7287 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7288 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7292 // convert input polySegments
7293 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7294 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7296 SMESH::PolySegment& segIn = theSegments[ i ];
7297 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7298 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7299 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7300 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7301 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7302 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7305 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7308 segOut.myVector.SetCoord( segIn.vector.PS.x,
7310 segIn.vector.PS.z );
7313 // get a static ElementSearcher
7314 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7315 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7316 if ( !theElementSearcher )
7317 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7320 std::vector<const SMDS_MeshElement*> newEdges;
7321 std::vector<const SMDS_MeshNode*> newNodes;
7322 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7323 groupDS ? &groupDS->SMDSGroup() : 0,
7324 theElementSearcher );
7326 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7328 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7329 assign( newNodes.begin(), newNodes.end() );
7332 if ( myIsPreviewMode )
7334 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7336 SMESH::PolySegment& segOut = theSegments[ i ];
7337 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7338 segOut.vector.PS.x = segIn.myVector.X();
7339 segOut.vector.PS.y = segIn.myVector.Y();
7340 segOut.vector.PS.z = segIn.myVector.Z();
7345 TPythonDump() << "_segments = []";
7346 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7348 SMESH::PolySegment& segIn = theSegments[ i ];
7349 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7350 << segIn.node1ID1 << ", "
7351 << segIn.node1ID2 << ", "
7352 << segIn.node2ID1 << ", "
7353 << segIn.node2ID2 << ", "
7354 << "smeshBuilder.MakeDirStruct( "
7355 << segIn.vector.PS.x << ", "
7356 << segIn.vector.PS.y << ", "
7357 << segIn.vector.PS.z << ")))";
7359 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7362 SMESH_CATCH( SMESH::throwCorbaException );
7366 //================================================================================
7368 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7369 * The slot is constructed by cutting faces by cylindrical surfaces made
7370 * around each segment. Segments are expected to be created by MakePolyLine().
7371 * \return Edges located at the slot boundary
7373 //================================================================================
7375 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7376 CORBA::Double theWidth)
7378 if ( CORBA::is_nil( theSegments ) ||
7379 theSegments->GetType() != SMESH::EDGE )
7380 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7381 if ( myMesh->NbFaces() == 0 )
7382 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7384 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7387 initData(/*deleteSearchers=*/false);
7389 SMESHDS_Mesh* meshDS = getMeshDS();
7391 // get standalone face groups to be updated
7392 std::vector< SMDS_MeshGroup* > faceGroups;
7393 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7394 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7395 for ( ; grIt != allGroups.end(); ++grIt )
7396 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7397 if ( gr->GetType() == SMDSAbs_Face )
7398 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7400 std::vector< SMESH_MeshAlgos::Edge > edges =
7401 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7402 theWidth, meshDS, faceGroups );
7404 resultEdges->length( edges.size() );
7405 for ( size_t i = 0; i < edges.size(); ++i )
7407 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7408 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7409 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7413 SMESH_CATCH( SMESH::throwCorbaException );
7415 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7417 return resultEdges._retn();