1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_MeshEditor_i.cxx
23 // Author : Nicolas REJNERI
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33 catch ( SALOME::SALOME_Exception & e ) { throw e; }
35 #include "SMESH_MeshEditor_i.hxx"
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_SetIterator.hxx"
46 #include "SMDS_VolumeTool.hxx"
47 #include "SMESHDS_Group.hxx"
48 #include "SMESHDS_GroupOnGeom.hxx"
49 #include "SMESH_ControlsDef.hxx"
50 #include "SMESH_Filter_i.hxx"
51 #include "SMESH_Gen_i.hxx"
52 #include "SMESH_Group.hxx"
53 #include "SMESH_Group_i.hxx"
54 #include "SMESH_MeshAlgos.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PythonDump.hxx"
58 #include "SMESH_subMeshEventListener.hxx"
59 #include "SMESH_subMesh_i.hxx"
61 #include <utilities.h>
62 #include <Utils_ExceptHandlers.hxx>
63 #include <Utils_CorbaException.hxx>
64 #include <SALOMEDS_wrap.hxx>
65 #include <SALOME_GenericObj_i.hh>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRep_Tool.hxx>
69 #include <TopExp_Explorer.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Face.hxx>
77 #include <Standard_Failure.hxx>
78 #include <Standard_ErrorHandler.hxx>
83 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
88 using SMESH::TPythonDump;
91 namespace MeshEditor_I {
93 //=============================================================================
95 * \brief Mesh to apply modifications for preview purposes
97 //=============================================================================
99 struct TPreviewMesh: public SMESH_Mesh
101 SMDSAbs_ElementType myPreviewType; // type to show
103 TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
104 _isShapeToMesh = (_id = 0);
105 _meshDS = new SMESHDS_Mesh( _id, true );
106 myPreviewType = previewElements;
108 //!< Copy a set of elements
109 void Copy(const TIDSortedElemSet & theElements,
110 TIDSortedElemSet& theCopyElements,
111 SMDSAbs_ElementType theSelectType = SMDSAbs_All,
112 SMDSAbs_ElementType theAvoidType = SMDSAbs_All)
114 // loop on theIDsOfElements
115 TIDSortedElemSet::const_iterator eIt = theElements.begin();
116 for ( ; eIt != theElements.end(); ++eIt )
118 const SMDS_MeshElement* anElem = *eIt;
119 if ( !anElem ) continue;
120 SMDSAbs_ElementType type = anElem->GetType();
121 if ( type == theAvoidType ||
122 ( theSelectType != SMDSAbs_All && type != theSelectType ))
124 const SMDS_MeshElement* anElemCopy;
125 if ( type == SMDSAbs_Node)
126 anElemCopy = Copy( cast2Node(anElem) );
128 anElemCopy = Copy( anElem );
130 theCopyElements.insert( theCopyElements.end(), anElemCopy );
134 SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
136 // copy element nodes
137 int anElemNbNodes = anElem->NbNodes();
138 vector< smIdType > anElemNodesID( anElemNbNodes ) ;
139 SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
140 for ( smIdType i = 0; itElemNodes->more(); i++)
142 const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
144 anElemNodesID[i] = anElemNode->GetID();
147 // creates a corresponding element on copied nodes
148 ::SMESH_MeshEditor::ElemFeatures elemType;
149 elemType.Init( anElem, /*basicOnly=*/false );
150 elemType.SetID( anElem->GetID() );
151 SMDS_MeshElement* anElemCopy =
152 ::SMESH_MeshEditor(this).AddElement( anElemNodesID, elemType );
156 SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
158 return _meshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
159 anElemNode->GetID());
163 GetMeshDS()->ClearMesh();
165 void Remove( SMDSAbs_ElementType type )
167 Remove( GetMeshDS()->elementsIterator( type ));
169 void Remove( SMDS_ElemIteratorPtr eIt )
171 while ( eIt->more() )
172 GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
174 };// struct TPreviewMesh
176 static SMESH_NodeSearcher * theNodeSearcher = 0;
177 static SMESH_ElementSearcher * theElementSearcher = 0;
179 //=============================================================================
181 * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
183 //=============================================================================
185 struct TSearchersDeleter : public SMESH_subMeshEventListener
188 string myMeshPartIOR;
190 TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
191 "SMESH_MeshEditor_i::TSearchersDeleter"),
193 //!< Delete theNodeSearcher
196 if ( theNodeSearcher ) { delete theNodeSearcher; } theNodeSearcher = 0;
197 if ( theElementSearcher ) { delete theElementSearcher; } theElementSearcher = 0;
199 typedef map < int, SMESH_subMesh * > TDependsOnMap;
200 //!< The meshod called by submesh: do my main job
201 void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
202 SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
204 if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
206 Unset( sm->GetFather() );
209 //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
210 void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
212 if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
219 myMeshPartIOR = meshPartIOR;
220 SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
222 while ( smIt->more() )
225 sm->SetEventListener( this, 0, sm );
229 //!< delete self from all submeshes
230 void Unset(SMESH_Mesh* mesh)
232 if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
233 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
234 while ( smIt->more() )
235 smIt->next()->DeleteEventListener( this );
240 } theSearchersDeleter;
242 TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
244 TCollection_AsciiString typeStr;
245 switch ( theMirrorType ) {
246 case SMESH::SMESH_MeshEditor::POINT:
247 typeStr = "SMESH.SMESH_MeshEditor.POINT";
249 case SMESH::SMESH_MeshEditor::AXIS:
250 typeStr = "SMESH.SMESH_MeshEditor.AXIS";
253 typeStr = "SMESH.SMESH_MeshEditor.PLANE";
257 //================================================================================
259 * \brief function for conversion of long_array to TIDSortedElemSet
260 * \param IDs - array of IDs
261 * \param aMesh - mesh
262 * \param aMap - collection to fill
263 * \param aType - element type
265 //================================================================================
267 void arrayToSet(const SMESH::smIdType_array & IDs,
268 const SMESHDS_Mesh* aMesh,
269 TIDSortedElemSet& aMap,
270 const SMDSAbs_ElementType aType = SMDSAbs_All,
271 SMDS_MeshElement::Filter* aFilter = NULL)
273 SMDS_MeshElement::NonNullFilter filter1;
274 SMDS_MeshElement::TypeFilter filter2( aType );
276 if ( aFilter == NULL )
277 aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
279 SMDS_MeshElement::Filter & filter = *aFilter;
281 if ( aType == SMDSAbs_Node )
282 for ( CORBA::ULong i = 0; i < IDs.length(); i++ ) {
283 const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
285 aMap.insert( aMap.end(), elem );
288 for ( CORBA::ULong i = 0; i<IDs.length(); i++) {
289 const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
291 aMap.insert( aMap.end(), elem );
295 //================================================================================
297 * \brief Retrieve nodes from SMESH_IDSource
299 //================================================================================
301 void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr theObject,
302 const SMESHDS_Mesh* theMeshDS,
303 TIDSortedNodeSet& theNodeSet)
306 if ( CORBA::is_nil( theObject ) )
308 if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
310 for ( SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator(); nIt->more(); )
311 if ( const SMDS_MeshElement * elem = nIt->next() )
312 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
316 SMESH::array_of_ElementType_var types = theObject->GetTypes();
317 SMESH::smIdType_array_var aElementsId = theObject->GetIDs();
318 if ( types->length() == 1 && types[0] == SMESH::NODE)
320 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
321 if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
322 theNodeSet.insert( theNodeSet.end(), n);
326 for ( CORBA::ULong i = 0; i < aElementsId->length(); i++ )
327 if ( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
328 theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
333 //================================================================================
335 * \brief Returns elements connected to the given elements
337 //================================================================================
339 void getElementsAround(const TIDSortedElemSet& theElements,
340 const SMESHDS_Mesh* theMeshDS,
341 TIDSortedElemSet& theElementsAround)
343 if ( theElements.empty() ) return;
345 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
346 bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
348 theMeshDS->GetMeshInfo().NbElements( elemType ) == (int) theElements.size() )
349 return; // all the elements are in theElements
352 elemType = SMDSAbs_All;
354 vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
356 TIDSortedElemSet::const_iterator elemIt = theElements.begin();
357 for ( ; elemIt != theElements.end(); ++elemIt )
359 const SMDS_MeshElement* e = *elemIt;
360 int i = e->NbCornerNodes();
363 const SMDS_MeshNode* n = e->GetNode( i );
364 if ( !isNodeChecked[ n->GetID() ])
366 isNodeChecked[ n->GetID() ] = true;
367 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
368 while ( invIt->more() )
370 const SMDS_MeshElement* elemAround = invIt->next();
371 if ( !theElements.count( elemAround ))
372 theElementsAround.insert( elemAround );
379 //================================================================================
381 * \brief Return a string used to detect change of mesh part on which theElementSearcher
382 * is going to be used
384 //================================================================================
386 string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
388 if ( SMESH::DownCast<SMESH_Mesh_i*>( theMeshPart ))
390 string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
391 if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
392 // take into account passible group modification
393 partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
394 partIOR += SMESH_Comment( type );
398 } // namespace MeshEditor_I
400 using namespace MeshEditor_I;
402 //=============================================================================
406 //=============================================================================
408 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
410 myMesh( &theMesh->GetImpl() ),
412 myIsPreviewMode ( isPreview ),
418 //================================================================================
422 //================================================================================
424 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
426 PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
427 PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
428 poa->deactivate_object(anObjectId.in());
430 //deleteAuxIDSources();
431 delete myPreviewMesh; myPreviewMesh = 0;
432 delete myPreviewEditor; myPreviewEditor = 0;
435 //================================================================================
437 * \brief Returns the mesh
439 //================================================================================
441 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
443 return myMesh_i->_this();
446 //================================================================================
448 * \brief Clear members
450 //================================================================================
452 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
454 if ( myIsPreviewMode ) {
455 if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
458 if ( deleteSearchers )
459 TSearchersDeleter::Delete();
461 getEditor().GetError().reset();
462 getEditor().ClearLastCreated();
465 //================================================================================
467 * \brief Increment mesh modif time and optionally record that the performed
468 * modification may influence further mesh re-compute.
469 * \param [in] isReComputeSafe - true if the modification does not influence
470 * further mesh re-compute
472 //================================================================================
474 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
476 myMesh->GetMeshDS()->Modified();
477 if ( !isReComputeSafe )
478 myMesh->SetIsModified( true );
481 //================================================================================
483 * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
484 * WARNING: in preview mode call getPreviewMesh() before getEditor()!
486 //================================================================================
488 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
490 if ( myIsPreviewMode && !myPreviewEditor ) {
491 if ( !myPreviewMesh ) getPreviewMesh();
492 myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
494 return myIsPreviewMode ? *myPreviewEditor : myEditor;
497 //================================================================================
499 * \brief Initialize and return myPreviewMesh
500 * \param previewElements - type of elements to show in preview
502 * WARNING: call it once per method!
504 //================================================================================
506 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
508 if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
510 delete myPreviewEditor;
512 delete myPreviewMesh;
513 myPreviewMesh = new TPreviewMesh( previewElements );
515 myPreviewMesh->Clear();
516 return myPreviewMesh;
519 //================================================================================
521 * Return data of mesh edition preview
523 //================================================================================
525 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
528 const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
530 if ( myIsPreviewMode || hasBadElems )
532 list<int> aNodesConnectivity;
533 typedef map<int, int> TNodesMap;
536 SMESHDS_Mesh* aMeshDS;
537 std::unique_ptr< SMESH_MeshPartDS > aMeshPartDS;
539 const list<const SMDS_MeshElement*>& badElems =
540 static_cast<SMESH_BadInputElements*>( getEditor().GetError().get() )->myBadElements;
541 aMeshPartDS.reset( new SMESH_MeshPartDS( badElems ));
542 aMeshDS = aMeshPartDS.get();
545 aMeshDS = getEditor().GetMeshDS();
547 myPreviewData = new SMESH::MeshPreviewStruct();
548 myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
551 SMDSAbs_ElementType previewType = SMDSAbs_All;
553 if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
554 previewType = aPreviewMesh->myPreviewType;
555 switch ( previewType ) {
556 case SMDSAbs_Edge : break;
557 case SMDSAbs_Face : break;
558 case SMDSAbs_Volume: break;
560 if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
564 myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
566 SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
568 while ( itMeshElems->more() ) {
569 const SMDS_MeshElement* aMeshElem = itMeshElems->next();
570 SMDS_NodeIteratorPtr itElemNodes =
571 (( aMeshElem->GetEntityType() == SMDSEntity_Quad_Polygon ) ?
572 aMeshElem->interlacedNodesIterator() :
573 aMeshElem->nodeIterator() );
574 while ( itElemNodes->more() ) {
575 const SMDS_MeshNode* aMeshNode = itElemNodes->next();
576 smIdType aNodeID = aMeshNode->GetID();
577 TNodesMap::iterator anIter = nodesMap.find(aNodeID);
578 if ( anIter == nodesMap.end() ) {
579 // filling the nodes coordinates
580 myPreviewData->nodesXYZ[j].x = aMeshNode->X();
581 myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
582 myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
583 anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
586 aNodesConnectivity.push_back(anIter->second);
589 // filling the elements types
590 SMDSAbs_ElementType aType = aMeshElem->GetType();
591 bool isPoly = aMeshElem->IsPoly();
592 myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
593 myPreviewData->elementTypes[i].isPoly = isPoly;
594 myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
597 myPreviewData->nodesXYZ.length( j );
599 // filling the elements connectivities
600 list<int>::iterator aConnIter = aNodesConnectivity.begin();
601 myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
602 for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
603 myPreviewData->elementConnectivities[i] = *aConnIter;
605 return myPreviewData._retn();
607 SMESH_CATCH( SMESH::throwCorbaException );
611 //================================================================================
613 * \brief Returns list of it's IDs of created nodes
614 * \retval SMESH::long_array* - list of node ID
616 //================================================================================
618 SMESH::smIdType_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
621 SMESH::smIdType_array_var myLastCreatedNodes = new SMESH::smIdType_array();
623 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
624 myLastCreatedNodes->length( aSeq.size() );
625 for ( size_t i = 0; i < aSeq.size(); i++)
626 myLastCreatedNodes[i] = aSeq[i]->GetID();
628 return myLastCreatedNodes._retn();
629 SMESH_CATCH( SMESH::throwCorbaException );
633 //================================================================================
635 * \brief Returns list of it's IDs of created elements
636 * \retval SMESH::long_array* - list of elements' ID
638 //================================================================================
640 SMESH::smIdType_array* SMESH_MeshEditor_i::GetLastCreatedElems()
643 SMESH::smIdType_array_var myLastCreatedElems = new SMESH::smIdType_array();
645 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
646 myLastCreatedElems->length( aSeq.size() );
647 for ( size_t i = 0; i < aSeq.size(); i++ )
648 myLastCreatedElems[i] = aSeq[i]->GetID();
650 return myLastCreatedElems._retn();
651 SMESH_CATCH( SMESH::throwCorbaException );
655 //=======================================================================
656 //function : ClearLastCreated
657 //purpose : Clears sequences of last created elements and nodes
658 //=======================================================================
660 void SMESH_MeshEditor_i::ClearLastCreated()
663 getEditor().ClearLastCreated();
664 SMESH_CATCH( SMESH::throwCorbaException );
667 //=======================================================================
669 * Returns description of an error/warning occurred during the last operation
670 * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
672 //=======================================================================
674 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
677 SMESH::ComputeError_var errOut = new SMESH::ComputeError;
678 SMESH_ComputeErrorPtr& errIn = getEditor().GetError();
679 if ( errIn && !errIn->IsOK() )
681 errOut->code = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
682 errOut->comment = errIn->myComment.c_str();
683 errOut->subShapeID = -1;
684 errOut->hasBadMesh = errIn->HasBadElems();
689 errOut->subShapeID = -1;
690 errOut->hasBadMesh = false;
693 return errOut._retn();
694 SMESH_CATCH( SMESH::throwCorbaException );
698 //=======================================================================
699 //function : MakeIDSource
700 //purpose : Wrap a sequence of ids in a SMESH_IDSource.
701 // Call UnRegister() as you fininsh using it!!
702 //=======================================================================
704 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
705 public virtual SALOME::GenericObj_i
707 SMESH::smIdType_array _ids;
708 SMESH::ElementType _type;
709 SMESH::SMESH_Mesh_ptr _mesh;
710 SMESH::smIdType_array* GetIDs() { return new SMESH::smIdType_array( _ids ); }
711 SMESH::smIdType_array* GetMeshInfo() { return 0; }
712 SMESH::smIdType_array* GetNbElementsByType()
714 SMESH::smIdType_array_var aRes = new SMESH::smIdType_array();
715 aRes->length(SMESH::NB_ELEMENT_TYPES);
716 for (smIdType i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
717 aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
720 SMESH::SMESH_Mesh_ptr GetMesh() { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
721 bool IsMeshInfoCorrect() { return true; }
722 SMESH::array_of_ElementType* GetTypes()
724 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
725 if ( _ids.length() > 0 ) {
729 return types._retn();
731 SALOMEDS::TMPFile* GetVtkUgStream()
733 SALOMEDS::TMPFile_var SeqFile;
734 return SeqFile._retn();
738 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::smIdType_array& ids,
739 SMESH::ElementType type)
741 _IDSource* idSrc = new _IDSource;
742 idSrc->_mesh = myMesh_i->_this();
745 if ( type == SMESH::ALL && ids.length() > 0 )
746 idSrc->_type = myMesh_i->GetElementType( ids[0], true );
748 SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
750 return anIDSourceVar._retn();
753 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
755 return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
758 SMESH::smIdType* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
759 SMESH::smIdType& nbIds)
761 if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
763 nbIds = (SMESH::smIdType) tmpIdSource->_ids.length();
764 return & tmpIdSource->_ids[0];
770 // void SMESH_MeshEditor_i::deleteAuxIDSources()
772 // std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
773 // for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
775 // myAuxIDSources.clear();
778 //=============================================================================
782 //=============================================================================
785 SMESH_MeshEditor_i::RemoveElements(const SMESH::smIdType_array & IDsOfElements)
790 list< smIdType > IdList;
792 for ( CORBA::ULong i = 0; i < IDsOfElements.length(); i++ )
793 IdList.push_back( IDsOfElements[i] );
795 // Update Python script
796 TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
799 bool ret = getEditor().Remove( IdList, false );
801 declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
804 SMESH_CATCH( SMESH::throwCorbaException );
808 //=============================================================================
812 //=============================================================================
814 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::smIdType_array & IDsOfNodes)
819 list< smIdType > IdList;
820 for ( CORBA::ULong i = 0; i < IDsOfNodes.length(); i++)
821 IdList.push_back( IDsOfNodes[i] );
823 // Update Python script
824 TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
826 bool ret = getEditor().Remove( IdList, true );
828 declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
831 SMESH_CATCH( SMESH::throwCorbaException );
835 //=============================================================================
839 //=============================================================================
841 SMESH::smIdType SMESH_MeshEditor_i::RemoveOrphanNodes()
846 // Update Python script
847 TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
849 // Create filter to find all orphan nodes
850 SMESH::Controls::Filter::TIdSequence seq;
851 SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
852 SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
854 // remove orphan nodes (if there are any)
855 list< smIdType > IdList( seq.begin(), seq.end() );
857 SMESH::smIdType nbNodesBefore = myMesh->NbNodes();
858 getEditor().Remove( IdList, true );
859 SMESH::smIdType nbNodesAfter = myMesh->NbNodes();
861 declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
862 return nbNodesBefore - nbNodesAfter;
864 SMESH_CATCH( SMESH::throwCorbaException );
868 //=============================================================================
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 SMESH::smIdType NbNodes = IDsOfNodes.length();
963 SMDS_MeshElement* elem = 0;
966 SMESH::smIdType index1 = IDsOfNodes[0];
967 SMESH::smIdType 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 SMESH::smIdType n1 = IDsOfNodes[0];
977 SMESH::smIdType n2 = IDsOfNodes[1];
978 SMESH::smIdType 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 ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1279 newElems[ i ] = (*eIt)->GetID();
1281 SMESH::SMESH_GroupBase_var groupToFill;
1282 if ( theGroupName && strlen( theGroupName ))
1284 // Get existing group named theGroupName
1285 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1286 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1287 SMESH::SMESH_GroupBase_var group = groups[i];
1288 if ( !group->_is_nil() ) {
1289 CORBA::String_var name = group->GetName();
1290 if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1291 groupToFill = group;
1296 if ( groupToFill->_is_nil() )
1297 groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1298 else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1299 groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1302 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1304 group_i->Add( newElems );
1305 result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1306 pyDump << groupToFill;
1310 result = MakeIDSource( newElems, SMESH::ELEM0D );
1311 pyDump << "elem0DIDs";
1314 pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1315 << theObject << ", '" << theGroupName << "' )";
1317 return result._retn();
1319 SMESH_CATCH( SMESH::throwCorbaException );
1323 //=============================================================================
1325 * \brief Bind a node to a vertex
1326 * \param NodeID - node ID
1327 * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1328 * \retval boolean - false if NodeID or VertexID is invalid
1330 //=============================================================================
1332 void SMESH_MeshEditor_i::SetNodeOnVertex(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 SMESH::smIdType 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 TIDSortedElemSet refFaces = { face };
1700 int nbReori = getEditor().Reorient2D( elements, dirVec, refFaces, /*allowNonManifold=*/true );
1703 declareMeshModified( /*isReComputeSafe=*/false );
1705 TPythonDump() << this << ".Reorient2D( "
1706 << the2Dgroup << ", "
1707 << theDirection << ", "
1709 << thePoint << " )";
1713 SMESH_CATCH( SMESH::throwCorbaException );
1717 //=======================================================================
1718 //function : Reorient2DByNeighbours
1719 //purpose : Reorient faces contained in a list of objectFaces
1720 // equally to faces contained in a list of referenceFaces.
1721 //=======================================================================
1724 SMESH_MeshEditor_i::Reorient2DByNeighbours(const SMESH::ListOfIDSources& theObjectFaces,
1725 const SMESH::ListOfIDSources& theReferenceFaces)
1728 initData(/*deleteSearchers=*/false);
1730 if ( theObjectFaces.length() == 0 )
1734 TIDSortedElemSet objFaces;
1735 bool invalidObjFaces = false;
1736 for ( CORBA::ULong i = 0; i < theObjectFaces.length(); ++i )
1739 if ( !idSourceToSet( theObjectFaces[i], getMeshDS(), objFaces, SMDSAbs_Face,
1740 /*emptyIfIsMesh=*/1, &err ) &&
1741 err == IDSource_INVALID )
1742 invalidObjFaces = true;
1744 if ( objFaces.empty() && invalidObjFaces )
1745 THROW_SALOME_CORBA_EXCEPTION("No valid faces in given groups", SALOME::BAD_PARAM);
1747 // get reference faces
1748 TIDSortedElemSet refFaces;
1749 for ( CORBA::ULong i = 0; i < theReferenceFaces.length(); ++i )
1751 idSourceToSet( theReferenceFaces[i], getMeshDS(), refFaces, SMDSAbs_Face, /*emptyIfIsMesh=*/1 );
1753 if ( refFaces.empty() && theReferenceFaces.length() > 0 )
1754 THROW_SALOME_CORBA_EXCEPTION("Reference faces are invalid", SALOME::BAD_PARAM);
1757 gp_Vec zeroVec( 0,0,0 );
1760 int nbReori = getEditor().Reorient2D( objFaces, zeroVec, refFaces, /*allowNonManifold=*/false );
1763 declareMeshModified( /*isReComputeSafe=*/false );
1765 TPythonDump() << this << ".Reorient2DByNeighbours("
1766 << theObjectFaces << ", "
1767 << theReferenceFaces << ")";
1771 SMESH_CATCH( SMESH::throwCorbaException );
1775 //=======================================================================
1776 //function : Reorient2DBy3D
1777 //purpose : Reorient faces basing on orientation of adjacent volumes.
1778 //=======================================================================
1780 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1781 SMESH::SMESH_IDSource_ptr volumeGroup,
1782 CORBA::Boolean outsideNormal)
1787 TIDSortedElemSet volumes;
1788 IDSource_Error volsError;
1789 idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1792 for ( size_t i = 0; i < faceGroups.length(); ++i )
1794 SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1796 TIDSortedElemSet faces;
1797 IDSource_Error error;
1798 idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1799 if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1800 THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1801 if ( error == IDSource_OK && volsError != IDSource_OK )
1802 THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1804 nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1806 if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1811 declareMeshModified( /*isReComputeSafe=*/false );
1813 TPythonDump() << this << ".Reorient2DBy3D( "
1814 << faceGroups << ", "
1815 << volumeGroup << ", "
1816 << outsideNormal << " )";
1820 SMESH_CATCH( SMESH::throwCorbaException );
1824 //=============================================================================
1826 * \brief Fuse neighbour triangles into quadrangles.
1828 //=============================================================================
1830 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::smIdType_array & IDsOfElements,
1831 SMESH::NumericalFunctor_ptr Criterion,
1832 CORBA::Double MaxAngle)
1837 SMESHDS_Mesh* aMesh = getMeshDS();
1838 TIDSortedElemSet faces,copyFaces;
1839 SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1840 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1841 TIDSortedElemSet* workElements = & faces;
1843 if ( myIsPreviewMode ) {
1844 SMDSAbs_ElementType select = SMDSAbs_Face;
1845 getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1846 workElements = & copyFaces;
1849 SMESH::NumericalFunctor_i* aNumericalFunctor =
1850 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1851 SMESH::Controls::NumericalFunctorPtr aCrit;
1852 if ( !aNumericalFunctor )
1853 aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1855 aCrit = aNumericalFunctor->GetNumericalFunctor();
1857 if ( !myIsPreviewMode ) {
1858 // Update Python script
1859 TPythonDump() << "isDone = " << this << ".TriToQuad( "
1860 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1863 bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1865 declareMeshModified( /*isReComputeSafe=*/!stat );
1868 SMESH_CATCH( SMESH::throwCorbaException );
1872 //=============================================================================
1874 * \brief Fuse neighbour triangles into quadrangles.
1876 //=============================================================================
1878 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1879 SMESH::NumericalFunctor_ptr Criterion,
1880 CORBA::Double MaxAngle)
1885 TPythonDump aTPythonDump; // suppress dump in TriToQuad()
1887 prepareIdSource( theObject );
1888 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
1889 CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1891 if ( !myIsPreviewMode ) {
1892 SMESH::NumericalFunctor_i* aNumericalFunctor =
1893 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1895 // Update Python script
1896 aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1897 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1902 SMESH_CATCH( SMESH::throwCorbaException );
1906 //=============================================================================
1908 * \brief Split quadrangles into triangles.
1910 //=============================================================================
1912 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::smIdType_array & IDsOfElements,
1913 SMESH::NumericalFunctor_ptr Criterion)
1918 SMESHDS_Mesh* aMesh = getMeshDS();
1919 TIDSortedElemSet faces;
1920 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1922 SMESH::NumericalFunctor_i* aNumericalFunctor =
1923 dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1924 SMESH::Controls::NumericalFunctorPtr aCrit;
1925 if ( !aNumericalFunctor )
1926 aCrit.reset( new SMESH::Controls::AspectRatio() );
1928 aCrit = aNumericalFunctor->GetNumericalFunctor();
1931 // Update Python script
1932 TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1934 CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1936 declareMeshModified( /*isReComputeSafe=*/false );
1939 SMESH_CATCH( SMESH::throwCorbaException );
1943 //=============================================================================
1945 * \brief Split quadrangles into triangles.
1947 //=============================================================================
1949 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr theObject,
1950 SMESH::NumericalFunctor_ptr Criterion)
1955 TPythonDump aTPythonDump; // suppress dump in QuadToTri()
1957 prepareIdSource( theObject );
1958 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
1959 CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1961 SMESH::NumericalFunctor_i* aNumericalFunctor =
1962 SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1964 // Update Python script
1965 aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1967 declareMeshModified( /*isReComputeSafe=*/false );
1970 SMESH_CATCH( SMESH::throwCorbaException );
1974 //================================================================================
1976 * \brief Split each of quadrangles into 4 triangles.
1977 * \param [in] theObject - theQuads Container of quadrangles to split.
1979 //================================================================================
1981 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1986 TIDSortedElemSet faces;
1987 if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1989 THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1991 getEditor().QuadTo4Tri( faces );
1992 TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1994 declareMeshModified( /*isReComputeSafe=*/false );
1996 SMESH_CATCH( SMESH::throwCorbaException );
1999 //=============================================================================
2001 * \brief Split quadrangles into triangles.
2003 //=============================================================================
2005 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::smIdType_array & IDsOfElements,
2006 CORBA::Boolean Diag13)
2011 SMESHDS_Mesh* aMesh = getMeshDS();
2012 TIDSortedElemSet faces;
2013 arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
2015 // Update Python script
2016 TPythonDump() << "isDone = " << this << ".SplitQuad( "
2017 << IDsOfElements << ", " << Diag13 << " )";
2019 CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
2021 declareMeshModified( /*isReComputeSafe=*/ !stat );
2024 SMESH_CATCH( SMESH::throwCorbaException );
2028 //=============================================================================
2030 * \brief Split quadrangles into triangles.
2032 //=============================================================================
2034 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
2035 CORBA::Boolean Diag13)
2040 TPythonDump aTPythonDump; // suppress dump in SplitQuad()
2042 prepareIdSource( theObject );
2043 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2044 CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2046 // Update Python script
2047 aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2048 << theObject << ", " << Diag13 << " )";
2050 declareMeshModified( /*isReComputeSafe=*/!isDone );
2053 SMESH_CATCH( SMESH::throwCorbaException );
2058 //=============================================================================
2060 * Find better splitting of the given quadrangle.
2061 * \param IDOfQuad ID of the quadrangle to be split.
2062 * \param Criterion A criterion to choose a diagonal for splitting.
2063 * \return 1 if 1-3 diagonal is better, 2 if 2-4
2064 * diagonal is better, 0 if error occurs.
2066 //=============================================================================
2068 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long IDOfQuad,
2069 SMESH::NumericalFunctor_ptr Criterion)
2074 const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2075 if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2077 SMESH::NumericalFunctor_i* aNumericalFunctor =
2078 dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2079 SMESH::Controls::NumericalFunctorPtr aCrit;
2080 if (aNumericalFunctor)
2081 aCrit = aNumericalFunctor->GetNumericalFunctor();
2083 aCrit.reset(new SMESH::Controls::AspectRatio());
2085 int id = getEditor().BestSplit(quad, aCrit);
2086 declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2090 SMESH_CATCH( SMESH::throwCorbaException );
2094 //================================================================================
2096 * \brief Split volumic elements into tetrahedrons
2098 //================================================================================
2100 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2101 CORBA::Short methodFlags)
2106 ::SMESH_MeshEditor::TFacetOfElem elemSet;
2107 const int noneFacet = -1;
2108 prepareIdSource( elems );
2109 if ( SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME ))
2110 while ( volIt->more() )
2111 elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2113 getEditor().SplitVolumes( elemSet, int( methodFlags ));
2114 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2116 TPythonDump() << this << ".SplitVolumesIntoTetra( "
2117 << elems << ", " << methodFlags << " )";
2119 SMESH_CATCH( SMESH::throwCorbaException );
2122 //================================================================================
2124 * \brief Split hexahedra into triangular prisms
2125 * \param elems - elements to split
2126 * \param facetToSplitNormal - normal used to find a facet of hexahedron
2127 * to split into triangles
2128 * \param methodFlags - flags passing splitting method:
2129 * 1 - split the hexahedron into 2 prisms
2130 * 2 - split the hexahedron into 4 prisms
2132 //================================================================================
2134 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms( SMESH::SMESH_IDSource_ptr elems,
2135 const SMESH::PointStruct & startHexPoint,
2136 const SMESH::DirStruct& facetToSplitNormal,
2137 CORBA::Short methodFlags,
2138 CORBA::Boolean allDomains)
2142 prepareIdSource( elems );
2144 gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2147 gp_Dir( facetToSplitNormal.PS.x,
2148 facetToSplitNormal.PS.y,
2149 facetToSplitNormal.PS.z ));
2150 TIDSortedElemSet elemSet;
2151 prepareIdSource( elems );
2152 SMESH::smIdType_array_var anElementsId = elems->GetIDs();
2153 SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2154 arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2156 ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2157 while ( !elemSet.empty() )
2159 getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2163 ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2164 for ( ; ef != elemFacets.end(); ++ef )
2165 elemSet.erase( ef->first );
2168 if ( methodFlags == 2 )
2169 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2171 methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2173 getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2174 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2176 TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2178 << startHexPoint << ", "
2179 << facetToSplitNormal<< ", "
2180 << methodFlags<< ", "
2181 << allDomains << " )";
2183 SMESH_CATCH( SMESH::throwCorbaException );
2186 //================================================================================
2188 * \brief Split bi-quadratic elements into linear ones without creation of additional nodes:
2189 * - bi-quadratic triangle will be split into 3 linear quadrangles;
2190 * - bi-quadratic quadrangle will be split into 4 linear quadrangles;
2191 * - tri-quadratic hexahedron will be split into 8 linear hexahedra.
2192 * Quadratic elements of lower dimension adjacent to the split bi-quadratic element
2193 * will be split in order to keep the mesh conformal.
2194 * \param elems - elements to split
2196 //================================================================================
2198 void SMESH_MeshEditor_i::SplitBiQuadraticIntoLinear(const SMESH::ListOfIDSources& theElems)
2203 TIDSortedElemSet elemSet;
2204 for ( size_t i = 0; i < theElems.length(); ++i )
2206 SMESH::SMESH_IDSource_ptr elems = theElems[i].in();
2207 SMESH::SMESH_Mesh_var mesh = elems->GetMesh();
2208 if ( mesh->GetId() != myMesh_i->GetId() )
2209 THROW_SALOME_CORBA_EXCEPTION("Wrong mesh of IDSource", SALOME::BAD_PARAM);
2211 idSourceToSet( elems, getMeshDS(), elemSet, SMDSAbs_All );
2213 getEditor().SplitBiQuadraticIntoLinear( elemSet );
2215 declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2217 TPythonDump() << this << ".SplitBiQuadraticIntoLinear( "
2218 << theElems << " )";
2220 SMESH_CATCH( SMESH::throwCorbaException );
2223 //=======================================================================
2226 //=======================================================================
2229 SMESH_MeshEditor_i::Smooth(const SMESH::smIdType_array & IDsOfElements,
2230 const SMESH::smIdType_array & IDsOfFixedNodes,
2231 CORBA::Short MaxNbOfIterations,
2232 CORBA::Double MaxAspectRatio,
2233 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2235 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2236 MaxAspectRatio, Method, false );
2240 //=======================================================================
2241 //function : SmoothParametric
2243 //=======================================================================
2246 SMESH_MeshEditor_i::SmoothParametric(const SMESH::smIdType_array & IDsOfElements,
2247 const SMESH::smIdType_array & IDsOfFixedNodes,
2248 CORBA::Short MaxNbOfIterations,
2249 CORBA::Double MaxAspectRatio,
2250 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2252 return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2253 MaxAspectRatio, Method, true );
2257 //=======================================================================
2258 //function : SmoothObject
2260 //=======================================================================
2263 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr theObject,
2264 const SMESH::smIdType_array & IDsOfFixedNodes,
2265 CORBA::Short MaxNbOfIterations,
2266 CORBA::Double MaxAspectRatio,
2267 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2269 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2270 MaxAspectRatio, Method, false);
2274 //=======================================================================
2275 //function : SmoothParametricObject
2277 //=======================================================================
2280 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr theObject,
2281 const SMESH::smIdType_array & IDsOfFixedNodes,
2282 CORBA::Short MaxNbOfIterations,
2283 CORBA::Double MaxAspectRatio,
2284 SMESH::SMESH_MeshEditor::Smooth_Method Method)
2286 return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2287 MaxAspectRatio, Method, true);
2291 //=============================================================================
2295 //=============================================================================
2298 SMESH_MeshEditor_i::smooth(const SMESH::smIdType_array & IDsOfElements,
2299 const SMESH::smIdType_array & IDsOfFixedNodes,
2300 CORBA::Short MaxNbOfIterations,
2301 CORBA::Double MaxAspectRatio,
2302 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2308 SMESHDS_Mesh* aMesh = getMeshDS();
2310 TIDSortedElemSet elements;
2311 arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2313 set<const SMDS_MeshNode*> fixedNodes;
2314 for ( CORBA::ULong i = 0; i < IDsOfFixedNodes.length(); i++) {
2315 SMESH::smIdType index = IDsOfFixedNodes[i];
2316 const SMDS_MeshNode * node = aMesh->FindNode(index);
2318 fixedNodes.insert( node );
2320 ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2321 if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2322 method = ::SMESH_MeshEditor::CENTROIDAL;
2324 getEditor().Smooth(elements, fixedNodes, method,
2325 MaxNbOfIterations, MaxAspectRatio, IsParametric );
2327 declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2329 // Update Python script
2330 TPythonDump() << "isDone = " << this << "."
2331 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2332 << IDsOfElements << ", " << IDsOfFixedNodes << ", "
2333 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2334 << "SMESH.SMESH_MeshEditor."
2335 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2336 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2340 SMESH_CATCH( SMESH::throwCorbaException );
2344 //=============================================================================
2348 //=============================================================================
2351 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr theObject,
2352 const SMESH::smIdType_array & IDsOfFixedNodes,
2353 CORBA::Short MaxNbOfIterations,
2354 CORBA::Double MaxAspectRatio,
2355 SMESH::SMESH_MeshEditor::Smooth_Method Method,
2361 TPythonDump aTPythonDump; // suppress dump in smooth()
2363 prepareIdSource( theObject );
2364 SMESH::smIdType_array_var anElementsId = theObject->GetIDs();
2365 CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2366 MaxAspectRatio, Method, IsParametric);
2368 // Update Python script
2369 aTPythonDump << "isDone = " << this << "."
2370 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2371 << theObject << ", " << IDsOfFixedNodes << ", "
2372 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2373 << "SMESH.SMESH_MeshEditor."
2374 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2375 "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2379 SMESH_CATCH( SMESH::throwCorbaException );
2383 //=============================================================================
2387 //=============================================================================
2389 void SMESH_MeshEditor_i::RenumberNodes()
2392 // Update Python script
2393 TPythonDump() << this << ".RenumberNodes()";
2395 getMeshDS()->Renumber( true );
2397 SMESH_CATCH( SMESH::throwCorbaException );
2400 //=============================================================================
2404 //=============================================================================
2406 void SMESH_MeshEditor_i::RenumberElements()
2409 // Update Python script
2410 TPythonDump() << this << ".RenumberElements()";
2412 getMeshDS()->Renumber( false );
2414 SMESH_CATCH( SMESH::throwCorbaException );
2417 //=======================================================================
2419 * \brief Return groups by their IDs
2421 //=======================================================================
2423 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2428 myMesh_i->CreateGroupServants();
2429 return myMesh_i->GetGroups( *groupIDs );
2431 SMESH_CATCH( SMESH::throwCorbaException );
2435 //=======================================================================
2436 //function : RotationSweepObjects
2438 //=======================================================================
2440 SMESH::ListOfGroups*
2441 SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
2442 const SMESH::ListOfIDSources & theEdges,
2443 const SMESH::ListOfIDSources & theFaces,
2444 const SMESH::AxisStruct & theAxis,
2445 CORBA::Double theAngleInRadians,
2446 CORBA::Long theNbOfSteps,
2447 CORBA::Double theTolerance,
2448 const bool theMakeGroups)
2453 TIDSortedElemSet elemsNodes[2];
2454 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2455 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2456 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2458 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2459 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2460 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2461 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2463 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2464 bool makeWalls=true;
2465 if ( myIsPreviewMode )
2467 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2468 TPreviewMesh * tmpMesh = getPreviewMesh();
2469 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2470 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2471 workElements = & copyElements[0];
2472 //makeWalls = false; -- faces are needed for preview
2475 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2477 gp_Ax1 Ax1 (gp_Pnt( theAxis.x, theAxis.y, theAxis.z ),
2478 gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2480 ::SMESH_MeshEditor::PGroupIDs groupIds =
2481 getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
2482 theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2484 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2486 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2488 if ( !myIsPreviewMode )
2490 dumpGroupsList( aPythonDump, aGroups );
2491 aPythonDump << this<< ".RotationSweepObjects( "
2496 << TVar( theAngleInRadians ) << ", "
2497 << TVar( theNbOfSteps ) << ", "
2498 << TVar( theTolerance ) << ", "
2499 << theMakeGroups << " )";
2503 getPreviewMesh()->Remove( SMDSAbs_Volume );
2506 return aGroups ? aGroups : new SMESH::ListOfGroups;
2508 SMESH_CATCH( SMESH::throwCorbaException );
2512 namespace MeshEditor_I
2515 * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2517 struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2519 bool myIsExtrusionByNormal;
2521 static int makeFlags( CORBA::Boolean MakeGroups,
2522 CORBA::Boolean ScaleVariation = false,
2523 CORBA::Boolean AngleVariation = false,
2524 CORBA::Boolean ByAverageNormal = false,
2525 CORBA::Boolean UseInputElemsOnly = false,
2526 CORBA::Long Flags = 0,
2527 CORBA::Boolean MakeBoundary = true )
2529 if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2530 if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2531 if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2532 if ( ScaleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
2533 if ( AngleVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_ANGLE_LINEAR_VARIATION;
2534 if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2538 ExtrusionParams(const SMESH::DirStruct & theDir,
2539 CORBA::Long theNbOfSteps,
2540 const SMESH::double_array & theScaleFactors,
2541 CORBA::Boolean theScaleVariation,
2542 const SMESH::double_array & theAngles,
2543 CORBA::Boolean theAngleVariation,
2544 const SMESH::double_array & theBasePoint,
2545 CORBA::Boolean theMakeGroups):
2546 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2550 toList( theScaleFactors ),
2551 toList( theAngles ),
2552 TBasePoint( theBasePoint ),
2553 makeFlags( theMakeGroups, theScaleVariation, theAngleVariation )),
2554 myIsExtrusionByNormal( false )
2558 ExtrusionParams(const SMESH::DirStruct & theDir,
2559 CORBA::Long theNbOfSteps,
2560 CORBA::Boolean theMakeGroups,
2561 CORBA::Long theExtrFlags,
2562 CORBA::Double theSewTolerance):
2563 ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2567 std::list<double>(),
2568 std::list<double>(),
2570 makeFlags( theMakeGroups, false, false, false, false,
2571 theExtrFlags, false ),
2573 myIsExtrusionByNormal( false )
2576 // params for extrusion by normal
2577 ExtrusionParams(CORBA::Double theStepSize,
2578 CORBA::Long theNbOfSteps,
2579 CORBA::Short theDim,
2580 CORBA::Boolean theByAverageNormal,
2581 CORBA::Boolean theUseInputElemsOnly,
2582 CORBA::Boolean theMakeGroups ):
2583 ::SMESH_MeshEditor::ExtrusParam ( theStepSize,
2585 makeFlags( theMakeGroups, false, false,
2586 theByAverageNormal, theUseInputElemsOnly ),
2588 myIsExtrusionByNormal( true )
2594 Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2597 static std::list<double> toList( const SMESH::double_array & theScaleFactors )
2599 std::list<double> scales;
2600 for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
2601 scales.push_back( theScaleFactors[i] );
2607 // structure used to convert SMESH::double_array to gp_XYZ*
2611 TBasePoint( const SMESH::double_array & theBasePoint )
2614 if ( theBasePoint.length() == 3 )
2616 p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
2620 operator const gp_XYZ*() const { return pp; }
2625 //=======================================================================
2627 * \brief Generate dim+1 elements by extrusion of elements along vector
2628 * \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
2629 * \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
2630 * \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
2631 * \param [in] stepVector - vector giving direction and distance of an extrusion step
2632 * \param [in] nbOfSteps - number of elements to generate from one element
2633 * \param [in] toMakeGroups - if true, new elements will be included into new groups
2634 * corresponding to groups the input elements included in.
2635 * \return ListOfGroups - new groups created if \a toMakeGroups is true
2637 //=======================================================================
2639 SMESH::ListOfGroups*
2640 SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
2641 const SMESH::ListOfIDSources & theEdges,
2642 const SMESH::ListOfIDSources & theFaces,
2643 const SMESH::DirStruct & theStepVector,
2644 CORBA::Long theNbOfSteps,
2645 CORBA::Boolean theToMakeGroups,
2646 const SMESH::double_array & theScaleFactors,
2647 CORBA::Boolean theScalesVariation,
2648 const SMESH::double_array & theBasePoint,
2649 const SMESH::double_array & theAngles,
2650 CORBA::Boolean theAnglesVariation)
2655 ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors, theScalesVariation,
2656 theAngles, theAnglesVariation, theBasePoint, theToMakeGroups );
2658 TIDSortedElemSet elemsNodes[2];
2659 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2660 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2661 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2663 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2664 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2665 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2666 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2668 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2669 SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
2670 if ( myIsPreviewMode )
2672 // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
2673 // previewType = SMDSAbs_Edge;
2675 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2676 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2677 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2678 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2679 workElements = & copyElements[0];
2681 params.SetNoGroups();
2683 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2685 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2686 ::SMESH_MeshEditor::PGroupIDs groupIds =
2687 getEditor().ExtrusionSweep( workElements, params, aHistory );
2689 SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
2691 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2693 if ( !myIsPreviewMode )
2695 dumpGroupsList( aPythonDump, aGroups );
2696 aPythonDump << this<< ".ExtrusionSweepObjects( "
2700 << theStepVector << ", "
2701 << TVar( theNbOfSteps ) << ", "
2702 << theToMakeGroups << ", "
2703 << TVar( theScaleFactors ) << ", "
2704 << theScalesVariation << ", "
2705 << TVar( theBasePoint ) << ", "
2706 << TVar( theAngles ) << ", "
2707 << theAnglesVariation << " )";
2711 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2714 return aGroups ? aGroups : new SMESH::ListOfGroups;
2716 SMESH_CATCH( SMESH::throwCorbaException );
2720 //=======================================================================
2721 //function : ExtrusionByNormal
2723 //=======================================================================
2725 SMESH::ListOfGroups*
2726 SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
2727 CORBA::Double stepSize,
2728 CORBA::Long nbOfSteps,
2729 CORBA::Boolean byAverageNormal,
2730 CORBA::Boolean useInputElemsOnly,
2731 CORBA::Boolean makeGroups,
2737 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2739 ExtrusionParams params( stepSize, nbOfSteps, dim,
2740 byAverageNormal, useInputElemsOnly, makeGroups );
2742 SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
2743 if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
2745 SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
2746 if (( elemTypes->length() == 1 ) &&
2747 ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
2748 elemType = ( SMDSAbs_ElementType ) elemTypes[0];
2751 TIDSortedElemSet elemsNodes[2];
2752 for ( int i = 0, nb = objects.length(); i < nb; ++i )
2753 idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
2755 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2756 SMDSAbs_ElementType previewType = SMDSAbs_Face;
2757 if ( myIsPreviewMode )
2759 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2760 TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
2761 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2762 workElements = & copyElements[0];
2764 params.SetNoGroups();
2767 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2768 ::SMESH_MeshEditor::PGroupIDs groupIds =
2769 getEditor().ExtrusionSweep( workElements, params, aHistory );
2771 SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
2773 if (!myIsPreviewMode) {
2774 dumpGroupsList(aPythonDump, aGroups);
2775 aPythonDump << this << ".ExtrusionByNormal( " << objects
2776 << ", " << TVar( stepSize )
2777 << ", " << TVar( nbOfSteps )
2778 << ", " << byAverageNormal
2779 << ", " << useInputElemsOnly
2780 << ", " << makeGroups
2786 getPreviewMesh( previewType )->Remove( SMDSAbs_Volume );
2789 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2791 return aGroups ? aGroups : new SMESH::ListOfGroups;
2793 SMESH_CATCH( SMESH::throwCorbaException );
2797 //=======================================================================
2798 //function : AdvancedExtrusion
2800 //=======================================================================
2802 SMESH::ListOfGroups*
2803 SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::smIdType_array & theIDsOfElements,
2804 const SMESH::DirStruct & theStepVector,
2805 CORBA::Long theNbOfSteps,
2806 CORBA::Long theExtrFlags,
2807 CORBA::Double theSewTolerance,
2808 CORBA::Boolean theMakeGroups)
2813 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2815 ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
2816 theExtrFlags, theSewTolerance );
2818 TIDSortedElemSet elemsNodes[2];
2819 arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
2821 ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
2822 ::SMESH_MeshEditor::PGroupIDs groupIds =
2823 getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
2825 SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
2827 declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2829 if ( !myIsPreviewMode ) {
2830 dumpGroupsList(aPythonDump, aGroups);
2831 aPythonDump << this << ".AdvancedExtrusion( "
2832 << theIDsOfElements << ", "
2833 << theStepVector << ", "
2834 << theNbOfSteps << ", "
2835 << theExtrFlags << ", "
2836 << theSewTolerance << ", "
2837 << theMakeGroups << " )";
2841 getPreviewMesh()->Remove( SMDSAbs_Volume );
2844 return aGroups ? aGroups : new SMESH::ListOfGroups;
2846 SMESH_CATCH( SMESH::throwCorbaException );
2850 //================================================================================
2852 * \brief Convert extrusion error to IDL enum
2854 //================================================================================
2858 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2860 SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::SMESH_MeshEditor::Extrusion_Error e )
2864 RETCASE( EXTR_NO_ELEMENTS );
2865 RETCASE( EXTR_PATH_NOT_EDGE );
2866 RETCASE( EXTR_BAD_PATH_SHAPE );
2867 RETCASE( EXTR_BAD_STARTING_NODE );
2868 RETCASE( EXTR_BAD_ANGLES_NUMBER );
2869 RETCASE( EXTR_CANT_GET_TANGENT );
2871 return SMESH::SMESH_MeshEditor::EXTR_OK;
2875 //=======================================================================
2876 //function : extrusionAlongPath
2878 //=======================================================================
2879 SMESH::ListOfGroups*
2880 SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
2881 const SMESH::ListOfIDSources & theEdges,
2882 const SMESH::ListOfIDSources & theFaces,
2883 SMESH::SMESH_IDSource_ptr thePathObject,
2884 GEOM::GEOM_Object_ptr thePathShape,
2885 SMESH::smIdType theNodeStart,
2886 CORBA::Boolean theHasAngles,
2887 const SMESH::double_array & theAngles,
2888 CORBA::Boolean theAnglesVariation,
2889 CORBA::Boolean theHasRefPoint,
2890 const SMESH::PointStruct & theRefPoint,
2892 const SMESH::double_array & theScaleFactors,
2893 CORBA::Boolean theScalesVariation,
2894 SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
2899 SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
2901 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2902 if ( thePathObject->_is_nil() )
2903 return aGroups._retn();
2906 SMDS_ElemIteratorPtr pathEdgesIterator;
2908 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathObject );
2909 if ( !CORBA::is_nil( thePathShape ) && aMeshImp )
2911 // get a sub-mesh of thePathShape
2912 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2913 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2915 return aGroups._retn();
2917 if ( !aSubMesh->GetSubMeshDS() )
2919 SMESHDS_Mesh * meshDS = aMeshImp->GetImpl().GetMeshDS();
2920 meshDS->AddCompoundSubmesh( aShape, TopAbs_EDGE );
2921 if ( !aSubMesh->GetSubMeshDS() )
2922 return aGroups._retn();
2924 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2925 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2926 if ( !pathEdgesIterator->more() ||
2927 pathEdgesIterator->next()->GetType() != SMDSAbs_Edge )
2928 return aGroups._retn();
2930 pathEdgesIterator = aSubMesh->GetSubMeshDS()->GetElements();
2934 theError = SMESH::SMESH_MeshEditor::EXTR_PATH_NOT_EDGE;
2935 prepareIdSource( thePathObject );
2936 pathEdgesIterator = SMESH_Mesh_i::GetElements( thePathObject, SMESH::EDGE );
2937 if ( !pathEdgesIterator || !pathEdgesIterator->more() )
2938 return aGroups._retn();
2943 SMESH::SMESH_Mesh_var pathMesh = thePathObject->GetMesh();
2944 aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( pathMesh );
2948 theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2949 const SMDS_MeshNode* nodeStart = aMeshImp->GetImpl().GetMeshDS()->FindNode( theNodeStart );
2951 return aGroups._retn();
2954 TIDSortedElemSet elemsNodes[2];
2955 for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
2956 if ( SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE ))
2957 while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
2959 for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
2960 idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
2961 for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
2962 idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
2964 list<double> angles = ExtrusionParams::toList( theAngles );
2965 list<double> scales = ExtrusionParams::toList( theScaleFactors );
2967 gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2968 const gp_Pnt *refPntPtr = theHasRefPoint ? &refPnt : 0;
2970 int nbOldGroups = myMesh->NbGroup();
2972 TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
2973 if ( myIsPreviewMode )
2975 SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2976 TPreviewMesh * tmpMesh = getPreviewMesh();
2977 tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
2978 tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
2979 workElements = & copyElements[0];
2980 theMakeGroups = false;
2983 ::SMESH_MeshEditor::Extrusion_Error error =
2984 getEditor().ExtrusionAlongTrack( workElements,
2985 &(aMeshImp->GetImpl()), pathEdgesIterator, nodeStart,
2986 angles, theAnglesVariation,
2987 scales, theScalesVariation,
2988 refPntPtr, theMakeGroups );
2990 declareMeshModified( /*isReComputeSafe=*/true );
2991 theError = convExtrError( error );
2993 TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
2994 if ( theMakeGroups ) {
2995 list<int> groupIDs = myMesh->GetGroupIds();
2996 list<int>::iterator newBegin = groupIDs.begin();
2997 std::advance( newBegin, nbOldGroups ); // skip old groups
2998 groupIDs.erase( groupIDs.begin(), newBegin );
2999 aGroups = getGroups( & groupIDs );
3000 if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
3003 if ( !myIsPreviewMode ) {
3004 if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
3005 else aPythonDump << "(_noGroups, error) = ";
3006 aPythonDump << this << ".ExtrusionAlongPathObjects( "
3010 << thePathObject << ", "
3011 << thePathShape << ", "
3012 << theNodeStart << ", "
3013 << theHasAngles << ", "
3014 << TVar( theAngles ) << ", "
3015 << theAnglesVariation << ", "
3016 << theHasRefPoint << ", "
3017 << "SMESH.PointStruct( "
3018 << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3019 << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3020 << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
3021 << theMakeGroups << ", "
3022 << TVar( theScaleFactors ) << ", "
3023 << theScalesVariation << " )";
3027 getPreviewMesh()->Remove( SMDSAbs_Volume );
3030 return aGroups._retn();
3032 SMESH_CATCH( SMESH::throwCorbaException );
3036 //================================================================================
3038 * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3039 * of given angles along path steps
3040 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3041 * which proceeds the extrusion
3042 * \param PathShape is shape(edge); as the mesh can be complex, the edge
3043 * is used to define the sub-mesh for the path
3045 //================================================================================
3047 SMESH::double_array*
3048 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMesh,
3049 GEOM::GEOM_Object_ptr thePathShape,
3050 const SMESH::double_array & theAngles)
3052 SMESH::double_array_var aResult = new SMESH::double_array();
3053 int nbAngles = theAngles.length();
3054 if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3056 SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3057 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3058 SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3059 if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3060 return aResult._retn();
3061 smIdType nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3062 if ( nbSteps == nbAngles )
3064 aResult.inout() = theAngles;
3068 aResult->length( nbSteps );
3069 double rAn2St = double( nbAngles ) / double( nbSteps );
3070 double angPrev = 0, angle;
3071 for ( int iSt = 0; iSt < nbSteps; ++iSt )
3073 double angCur = rAn2St * ( iSt+1 );
3074 double angCurFloor = floor( angCur );
3075 double angPrevFloor = floor( angPrev );
3076 if ( angPrevFloor == angCurFloor )
3077 angle = rAn2St * theAngles[ int( angCurFloor ) ];
3080 int iP = int( angPrevFloor );
3081 double angPrevCeil = ceil(angPrev);
3082 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3084 int iC = int( angCurFloor );
3085 if ( iC < nbAngles )
3086 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3088 iP = int( angPrevCeil );
3090 angle += theAngles[ iC ];
3092 aResult[ iSt ] = angle;
3097 // Update Python script
3098 TPythonDump() << "rotAngles = " << theAngles;
3099 TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3100 << thePathMesh << ", "
3101 << thePathShape << ", "
3104 return aResult._retn();
3107 //=======================================================================
3110 //=======================================================================
3112 SMESH::ListOfGroups*
3113 SMESH_MeshEditor_i::mirror(TIDSortedElemSet & theElements,
3114 const SMESH::AxisStruct & theAxis,
3115 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3116 CORBA::Boolean theCopy,
3118 ::SMESH_Mesh* theTargetMesh)
3123 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3124 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3126 if ( theTargetMesh )
3130 switch ( theMirrorType ) {
3131 case SMESH::SMESH_MeshEditor::POINT:
3132 aTrsf.SetMirror( P );
3134 case SMESH::SMESH_MeshEditor::AXIS:
3135 aTrsf.SetMirror( gp_Ax1( P, V ));
3138 aTrsf.SetMirror( gp_Ax2( P, V ));
3141 TIDSortedElemSet copyElements;
3142 TIDSortedElemSet* workElements = & theElements;
3144 if ( myIsPreviewMode )
3146 TPreviewMesh * tmpMesh = getPreviewMesh();
3147 tmpMesh->Copy( theElements, copyElements);
3148 if ( !theCopy && !theTargetMesh )
3150 TIDSortedElemSet elemsAround, elemsAroundCopy;
3151 getElementsAround( theElements, getMeshDS(), elemsAround );
3152 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3154 workElements = & copyElements;
3155 theMakeGroups = false;
3158 ::SMESH_MeshEditor::PGroupIDs groupIds =
3159 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3161 if ( !myIsPreviewMode )
3163 if ( theTargetMesh )
3164 theTargetMesh->GetMeshDS()->Modified();
3166 declareMeshModified( /*isReComputeSafe=*/false );
3169 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3171 SMESH_CATCH( SMESH::throwCorbaException );
3175 //=======================================================================
3178 //=======================================================================
3180 void SMESH_MeshEditor_i::Mirror(const SMESH::smIdType_array & theIDsOfElements,
3181 const SMESH::AxisStruct & theAxis,
3182 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3183 CORBA::Boolean theCopy)
3185 if ( !myIsPreviewMode ) {
3186 TPythonDump() << this << ".Mirror( "
3187 << theIDsOfElements << ", "
3189 << mirrorTypeName(theMirrorType) << ", "
3192 if ( theIDsOfElements.length() > 0 )
3194 TIDSortedElemSet elements;
3195 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3196 mirror(elements, theAxis, theMirrorType, theCopy, false);
3201 //=======================================================================
3202 //function : MirrorObject
3204 //=======================================================================
3206 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr theObject,
3207 const SMESH::AxisStruct & theAxis,
3208 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3209 CORBA::Boolean theCopy)
3211 if ( !myIsPreviewMode ) {
3212 TPythonDump() << this << ".MirrorObject( "
3213 << theObject << ", "
3215 << mirrorTypeName(theMirrorType) << ", "
3218 TIDSortedElemSet elements;
3220 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3222 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3223 mirror(elements, theAxis, theMirrorType, theCopy, false);
3226 //=======================================================================
3227 //function : MirrorMakeGroups
3229 //=======================================================================
3231 SMESH::ListOfGroups*
3232 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3233 const SMESH::AxisStruct& theMirror,
3234 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3236 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3238 SMESH::ListOfGroups * aGroups = 0;
3239 if ( theIDsOfElements.length() > 0 )
3241 TIDSortedElemSet elements;
3242 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3243 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3245 if (!myIsPreviewMode) {
3246 dumpGroupsList(aPythonDump, aGroups);
3247 aPythonDump << this << ".MirrorMakeGroups( "
3248 << theIDsOfElements << ", "
3249 << theMirror << ", "
3250 << mirrorTypeName(theMirrorType) << " )";
3255 //=======================================================================
3256 //function : MirrorObjectMakeGroups
3258 //=======================================================================
3260 SMESH::ListOfGroups*
3261 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3262 const SMESH::AxisStruct& theMirror,
3263 SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3265 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3267 SMESH::ListOfGroups * aGroups = 0;
3268 TIDSortedElemSet elements;
3269 if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3270 aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3272 if (!myIsPreviewMode)
3274 dumpGroupsList(aPythonDump,aGroups);
3275 aPythonDump << this << ".MirrorObjectMakeGroups( "
3276 << theObject << ", "
3277 << theMirror << ", "
3278 << mirrorTypeName(theMirrorType) << " )";
3283 //=======================================================================
3284 //function : MirrorMakeMesh
3286 //=======================================================================
3288 SMESH::SMESH_Mesh_ptr
3289 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3290 const SMESH::AxisStruct& theMirror,
3291 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3292 CORBA::Boolean theCopyGroups,
3293 const char* theMeshName)
3295 SMESH_Mesh_i* mesh_i;
3296 SMESH::SMESH_Mesh_var mesh;
3297 { // open new scope to dump "MakeMesh" command
3298 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3300 TPythonDump pydump; // to prevent dump at mesh creation
3302 mesh = makeMesh( theMeshName );
3303 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3304 if (mesh_i && theIDsOfElements.length() > 0 )
3306 TIDSortedElemSet elements;
3307 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3308 mirror(elements, theMirror, theMirrorType,
3309 false, theCopyGroups, & mesh_i->GetImpl());
3310 mesh_i->CreateGroupServants();
3313 if (!myIsPreviewMode) {
3314 pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3315 << theIDsOfElements << ", "
3316 << theMirror << ", "
3317 << mirrorTypeName(theMirrorType) << ", "
3318 << theCopyGroups << ", '"
3319 << theMeshName << "' )";
3324 if (!myIsPreviewMode && mesh_i)
3325 mesh_i->GetGroups();
3327 return mesh._retn();
3330 //=======================================================================
3331 //function : MirrorObjectMakeMesh
3333 //=======================================================================
3335 SMESH::SMESH_Mesh_ptr
3336 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3337 const SMESH::AxisStruct& theMirror,
3338 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3339 CORBA::Boolean theCopyGroups,
3340 const char* theMeshName)
3342 SMESH_Mesh_i* mesh_i;
3343 SMESH::SMESH_Mesh_var mesh;
3344 { // open new scope to dump "MakeMesh" command
3345 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3347 TPythonDump pydump; // to prevent dump at mesh creation
3349 mesh = makeMesh( theMeshName );
3350 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3351 TIDSortedElemSet elements;
3353 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3355 mirror(elements, theMirror, theMirrorType,
3356 false, theCopyGroups, & mesh_i->GetImpl());
3357 mesh_i->CreateGroupServants();
3359 if (!myIsPreviewMode) {
3360 pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3361 << theObject << ", "
3362 << theMirror << ", "
3363 << mirrorTypeName(theMirrorType) << ", "
3364 << theCopyGroups << ", '"
3365 << theMeshName << "' )";
3370 if (!myIsPreviewMode && mesh_i)
3371 mesh_i->GetGroups();
3373 return mesh._retn();
3376 //=======================================================================
3377 //function : translate
3379 //=======================================================================
3381 SMESH::ListOfGroups*
3382 SMESH_MeshEditor_i::translate(TIDSortedElemSet & theElements,
3383 const SMESH::DirStruct & theVector,
3384 CORBA::Boolean theCopy,
3386 ::SMESH_Mesh* theTargetMesh)
3391 if ( theTargetMesh )
3395 const SMESH::PointStruct * P = &theVector.PS;
3396 aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3398 TIDSortedElemSet copyElements;
3399 TIDSortedElemSet* workElements = &theElements;
3401 if ( myIsPreviewMode )
3403 TPreviewMesh * tmpMesh = getPreviewMesh();
3404 tmpMesh->Copy( theElements, copyElements);
3405 if ( !theCopy && !theTargetMesh )
3407 TIDSortedElemSet elemsAround, elemsAroundCopy;
3408 getElementsAround( theElements, getMeshDS(), elemsAround );
3409 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3411 workElements = & copyElements;
3412 theMakeGroups = false;
3415 ::SMESH_MeshEditor::PGroupIDs groupIds =
3416 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3418 if ( !myIsPreviewMode )
3420 if ( theTargetMesh )
3421 theTargetMesh->GetMeshDS()->Modified();
3423 declareMeshModified( /*isReComputeSafe=*/false );
3426 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3428 SMESH_CATCH( SMESH::throwCorbaException );
3432 //=======================================================================
3433 //function : Translate
3435 //=======================================================================
3437 void SMESH_MeshEditor_i::Translate(const SMESH::smIdType_array & theIDsOfElements,
3438 const SMESH::DirStruct & theVector,
3439 CORBA::Boolean theCopy)
3441 if (!myIsPreviewMode) {
3442 TPythonDump() << this << ".Translate( "
3443 << theIDsOfElements << ", "
3444 << theVector << ", "
3447 if (theIDsOfElements.length()) {
3448 TIDSortedElemSet elements;
3449 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3450 translate(elements, theVector, theCopy, false);
3454 //=======================================================================
3455 //function : TranslateObject
3457 //=======================================================================
3459 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3460 const SMESH::DirStruct & theVector,
3461 CORBA::Boolean theCopy)
3463 if (!myIsPreviewMode) {
3464 TPythonDump() << this << ".TranslateObject( "
3465 << theObject << ", "
3466 << theVector << ", "
3469 TIDSortedElemSet elements;
3471 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3473 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3474 translate(elements, theVector, theCopy, false);
3477 //=======================================================================
3478 //function : TranslateMakeGroups
3480 //=======================================================================
3482 SMESH::ListOfGroups*
3483 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3484 const SMESH::DirStruct& theVector)
3486 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3488 SMESH::ListOfGroups * aGroups = 0;
3489 if (theIDsOfElements.length()) {
3490 TIDSortedElemSet elements;
3491 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3492 aGroups = translate(elements,theVector,true,true);
3494 if (!myIsPreviewMode) {
3495 dumpGroupsList(aPythonDump, aGroups);
3496 aPythonDump << this << ".TranslateMakeGroups( "
3497 << theIDsOfElements << ", "
3498 << theVector << " )";
3503 //=======================================================================
3504 //function : TranslateObjectMakeGroups
3506 //=======================================================================
3508 SMESH::ListOfGroups*
3509 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3510 const SMESH::DirStruct& theVector)
3512 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3514 SMESH::ListOfGroups * aGroups = 0;
3515 TIDSortedElemSet elements;
3516 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3517 aGroups = translate(elements, theVector, true, true);
3519 if (!myIsPreviewMode) {
3520 dumpGroupsList(aPythonDump, aGroups);
3521 aPythonDump << this << ".TranslateObjectMakeGroups( "
3522 << theObject << ", "
3523 << theVector << " )";
3528 //=======================================================================
3529 //function : TranslateMakeMesh
3531 //=======================================================================
3533 SMESH::SMESH_Mesh_ptr
3534 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3535 const SMESH::DirStruct& theVector,
3536 CORBA::Boolean theCopyGroups,
3537 const char* theMeshName)
3539 SMESH_Mesh_i* mesh_i;
3540 SMESH::SMESH_Mesh_var mesh;
3542 { // open new scope to dump "MakeMesh" command
3543 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3545 TPythonDump pydump; // to prevent dump at mesh creation
3547 mesh = makeMesh( theMeshName );
3548 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3550 if ( mesh_i && theIDsOfElements.length() )
3552 TIDSortedElemSet elements;
3553 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3554 translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3555 mesh_i->CreateGroupServants();
3558 if ( !myIsPreviewMode ) {
3559 pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3560 << theIDsOfElements << ", "
3561 << theVector << ", "
3562 << theCopyGroups << ", '"
3563 << theMeshName << "' )";
3568 if (!myIsPreviewMode && mesh_i)
3569 mesh_i->GetGroups();
3571 return mesh._retn();
3574 //=======================================================================
3575 //function : TranslateObjectMakeMesh
3577 //=======================================================================
3579 SMESH::SMESH_Mesh_ptr
3580 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3581 const SMESH::DirStruct& theVector,
3582 CORBA::Boolean theCopyGroups,
3583 const char* theMeshName)
3586 SMESH_Mesh_i* mesh_i;
3587 SMESH::SMESH_Mesh_var mesh;
3588 { // open new scope to dump "MakeMesh" command
3589 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3591 TPythonDump pydump; // to prevent dump at mesh creation
3592 mesh = makeMesh( theMeshName );
3593 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3595 TIDSortedElemSet elements;
3597 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3599 translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3600 mesh_i->CreateGroupServants();
3602 if ( !myIsPreviewMode ) {
3603 pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3604 << theObject << ", "
3605 << theVector << ", "
3606 << theCopyGroups << ", '"
3607 << theMeshName << "' )";
3612 if (!myIsPreviewMode && mesh_i)
3613 mesh_i->GetGroups();
3615 return mesh._retn();
3617 SMESH_CATCH( SMESH::throwCorbaException );
3621 //=======================================================================
3624 //=======================================================================
3626 SMESH::ListOfGroups*
3627 SMESH_MeshEditor_i::rotate(TIDSortedElemSet & theElements,
3628 const SMESH::AxisStruct & theAxis,
3629 CORBA::Double theAngle,
3630 CORBA::Boolean theCopy,
3632 ::SMESH_Mesh* theTargetMesh)
3637 if ( theTargetMesh )
3640 gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3641 gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3644 aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3646 TIDSortedElemSet copyElements;
3647 TIDSortedElemSet* workElements = &theElements;
3648 if ( myIsPreviewMode ) {
3649 TPreviewMesh * tmpMesh = getPreviewMesh();
3650 tmpMesh->Copy( theElements, copyElements );
3651 if ( !theCopy && !theTargetMesh )
3653 TIDSortedElemSet elemsAround, elemsAroundCopy;
3654 getElementsAround( theElements, getMeshDS(), elemsAround );
3655 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3657 workElements = ©Elements;
3658 theMakeGroups = false;
3661 ::SMESH_MeshEditor::PGroupIDs groupIds =
3662 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3664 if ( !myIsPreviewMode)
3666 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3667 else declareMeshModified( /*isReComputeSafe=*/false );
3670 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3672 SMESH_CATCH( SMESH::throwCorbaException );
3676 //=======================================================================
3679 //=======================================================================
3681 void SMESH_MeshEditor_i::Rotate(const SMESH::smIdType_array & theIDsOfElements,
3682 const SMESH::AxisStruct & theAxis,
3683 CORBA::Double theAngle,
3684 CORBA::Boolean theCopy)
3686 if (!myIsPreviewMode) {
3687 TPythonDump() << this << ".Rotate( "
3688 << theIDsOfElements << ", "
3690 << TVar( theAngle ) << ", "
3693 if (theIDsOfElements.length() > 0)
3695 TIDSortedElemSet elements;
3696 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3697 rotate(elements,theAxis,theAngle,theCopy,false);
3701 //=======================================================================
3702 //function : RotateObject
3704 //=======================================================================
3706 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3707 const SMESH::AxisStruct & theAxis,
3708 CORBA::Double theAngle,
3709 CORBA::Boolean theCopy)
3711 if ( !myIsPreviewMode ) {
3712 TPythonDump() << this << ".RotateObject( "
3713 << theObject << ", "
3715 << TVar( theAngle ) << ", "
3718 TIDSortedElemSet elements;
3719 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3720 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3721 rotate(elements,theAxis,theAngle,theCopy,false);
3724 //=======================================================================
3725 //function : RotateMakeGroups
3727 //=======================================================================
3729 SMESH::ListOfGroups*
3730 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::smIdType_array& theIDsOfElements,
3731 const SMESH::AxisStruct& theAxis,
3732 CORBA::Double theAngle)
3734 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3736 SMESH::ListOfGroups * aGroups = 0;
3737 if (theIDsOfElements.length() > 0)
3739 TIDSortedElemSet elements;
3740 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3741 aGroups = rotate(elements,theAxis,theAngle,true,true);
3743 if (!myIsPreviewMode) {
3744 dumpGroupsList(aPythonDump, aGroups);
3745 aPythonDump << this << ".RotateMakeGroups( "
3746 << theIDsOfElements << ", "
3748 << TVar( theAngle ) << " )";
3753 //=======================================================================
3754 //function : RotateObjectMakeGroups
3756 //=======================================================================
3758 SMESH::ListOfGroups*
3759 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3760 const SMESH::AxisStruct& theAxis,
3761 CORBA::Double theAngle)
3763 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3765 SMESH::ListOfGroups * aGroups = 0;
3766 TIDSortedElemSet elements;
3767 if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3768 aGroups = rotate(elements, theAxis, theAngle, true, true);
3770 if (!myIsPreviewMode) {
3771 dumpGroupsList(aPythonDump, aGroups);
3772 aPythonDump << this << ".RotateObjectMakeGroups( "
3773 << theObject << ", "
3775 << TVar( theAngle ) << " )";
3780 //=======================================================================
3781 //function : RotateMakeMesh
3783 //=======================================================================
3785 SMESH::SMESH_Mesh_ptr
3786 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::smIdType_array& theIDsOfElements,
3787 const SMESH::AxisStruct& theAxis,
3788 CORBA::Double theAngleInRadians,
3789 CORBA::Boolean theCopyGroups,
3790 const char* theMeshName)
3793 SMESH::SMESH_Mesh_var mesh;
3794 SMESH_Mesh_i* mesh_i;
3796 { // open new scope to dump "MakeMesh" command
3797 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3799 TPythonDump pydump; // to prevent dump at mesh creation
3801 mesh = makeMesh( theMeshName );
3802 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3804 if ( mesh_i && theIDsOfElements.length() > 0 )
3806 TIDSortedElemSet elements;
3807 arrayToSet(theIDsOfElements, getMeshDS(), elements);
3808 rotate(elements, theAxis, theAngleInRadians,
3809 false, theCopyGroups, & mesh_i->GetImpl());
3810 mesh_i->CreateGroupServants();
3812 if ( !myIsPreviewMode ) {
3813 pydump << mesh << " = " << this << ".RotateMakeMesh( "
3814 << theIDsOfElements << ", "
3816 << TVar( theAngleInRadians ) << ", "
3817 << theCopyGroups << ", '"
3818 << theMeshName << "' )";
3823 if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3824 mesh_i->GetGroups();
3826 return mesh._retn();
3828 SMESH_CATCH( SMESH::throwCorbaException );
3832 //=======================================================================
3833 //function : RotateObjectMakeMesh
3835 //=======================================================================
3837 SMESH::SMESH_Mesh_ptr
3838 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3839 const SMESH::AxisStruct& theAxis,
3840 CORBA::Double theAngleInRadians,
3841 CORBA::Boolean theCopyGroups,
3842 const char* theMeshName)
3845 SMESH::SMESH_Mesh_var mesh;
3846 SMESH_Mesh_i* mesh_i;
3848 {// open new scope to dump "MakeMesh" command
3849 // and then "GetGroups" using SMESH_Mesh::GetGroups()
3851 TPythonDump pydump; // to prevent dump at mesh creation
3852 mesh = makeMesh( theMeshName );
3853 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3855 TIDSortedElemSet elements;
3857 idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3859 rotate(elements, theAxis, theAngleInRadians,
3860 false, theCopyGroups, & mesh_i->GetImpl());
3861 mesh_i->CreateGroupServants();
3863 if ( !myIsPreviewMode ) {
3864 pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3865 << theObject << ", "
3867 << TVar( theAngleInRadians ) << ", "
3868 << theCopyGroups << ", '"
3869 << theMeshName << "' )";
3874 if (!myIsPreviewMode && mesh_i)
3875 mesh_i->GetGroups();
3877 return mesh._retn();
3879 SMESH_CATCH( SMESH::throwCorbaException );
3883 //=======================================================================
3886 //=======================================================================
3888 SMESH::ListOfGroups*
3889 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr theObject,
3890 const SMESH::PointStruct& thePoint,
3891 const SMESH::double_array& theScaleFact,
3892 CORBA::Boolean theCopy,
3894 ::SMESH_Mesh* theTargetMesh)
3898 if ( theScaleFact.length() < 1 )
3899 THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3900 if ( theScaleFact.length() == 2 )
3901 THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3903 if ( theTargetMesh )
3906 TIDSortedElemSet elements;
3907 bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3908 if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3913 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3914 (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3918 // fight against orthogonalization
3919 // aTrsf.SetValues( S[0], 0, 0, thePoint.x * (1-S[0]),
3920 // 0, S[1], 0, thePoint.y * (1-S[1]),
3921 // 0, 0, S[2], thePoint.z * (1-S[2]) );
3922 aTrsf.SetScale( gp::Origin(), 1.0 ); // set form which is used to make group names
3923 gp_XYZ & loc = ( gp_XYZ& ) aTrsf.TranslationPart();
3924 gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
3925 loc.SetCoord( thePoint.x * (1-S[0]),
3926 thePoint.y * (1-S[1]),
3927 thePoint.z * (1-S[2]));
3928 M.SetDiagonal( S[0], S[1], S[2] );
3930 TIDSortedElemSet copyElements;
3931 TIDSortedElemSet* workElements = &elements;
3932 if ( myIsPreviewMode )
3934 TPreviewMesh * tmpMesh = getPreviewMesh();
3935 tmpMesh->Copy( elements, copyElements);
3936 if ( !theCopy && !theTargetMesh )
3938 TIDSortedElemSet elemsAround, elemsAroundCopy;
3939 getElementsAround( elements, getMeshDS(), elemsAround );
3940 tmpMesh->Copy( elemsAround, elemsAroundCopy);
3942 workElements = & copyElements;
3943 theMakeGroups = false;
3946 ::SMESH_MeshEditor::PGroupIDs groupIds =
3947 getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3949 if ( !myIsPreviewMode )
3951 if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
3952 else declareMeshModified( /*isReComputeSafe=*/false );
3954 return theMakeGroups ? getGroups(groupIds.get()) : 0;
3956 SMESH_CATCH( SMESH::throwCorbaException );
3960 //=======================================================================
3963 //=======================================================================
3965 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr theObject,
3966 const SMESH::PointStruct& thePoint,
3967 const SMESH::double_array& theScaleFact,
3968 CORBA::Boolean theCopy)
3970 if ( !myIsPreviewMode ) {
3971 TPythonDump() << this << ".Scale( "
3972 << theObject << ", "
3974 << TVar( theScaleFact ) << ", "
3977 scale(theObject, thePoint, theScaleFact, theCopy, false);
3981 //=======================================================================
3982 //function : ScaleMakeGroups
3984 //=======================================================================
3986 SMESH::ListOfGroups*
3987 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3988 const SMESH::PointStruct& thePoint,
3989 const SMESH::double_array& theScaleFact)
3991 TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3993 SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3994 if (!myIsPreviewMode) {
3995 dumpGroupsList(aPythonDump, aGroups);
3996 aPythonDump << this << ".Scale("
3999 << TVar( theScaleFact ) << ",True,True)";
4005 //=======================================================================
4006 //function : ScaleMakeMesh
4008 //=======================================================================
4010 SMESH::SMESH_Mesh_ptr
4011 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4012 const SMESH::PointStruct& thePoint,
4013 const SMESH::double_array& theScaleFact,
4014 CORBA::Boolean theCopyGroups,
4015 const char* theMeshName)
4017 SMESH_Mesh_i* mesh_i;
4018 SMESH::SMESH_Mesh_var mesh;
4019 { // open new scope to dump "MakeMesh" command
4020 // and then "GetGroups" using SMESH_Mesh::GetGroups()
4022 TPythonDump pydump; // to prevent dump at mesh creation
4023 mesh = makeMesh( theMeshName );
4024 mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4028 scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4029 mesh_i->CreateGroupServants();
4031 if ( !myIsPreviewMode )
4032 pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4033 << theObject << ", "
4035 << TVar( theScaleFact ) << ", "
4036 << theCopyGroups << ", '"
4037 << theMeshName << "' )";
4041 if (!myIsPreviewMode && mesh_i)
4042 mesh_i->GetGroups();
4044 return mesh._retn();
4047 //================================================================================
4049 * \brief Make an offset mesh from a source 2D mesh
4050 * \param [inout] theObject - source mesh. New elements are added to this mesh
4051 * if \a theMeshName is empty.
4052 * \param [in] theValue - offset value
4053 * \param [in] theCopyGroups - to generate groups
4054 * \param [in] theMeshName - optional name of a new mesh
4055 * \param [out] theGroups - new groups
4056 * \return SMESH::SMESH_Mesh_ptr - the modified mesh
4058 //================================================================================
4060 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::Offset( SMESH::SMESH_IDSource_ptr theObject,
4061 CORBA::Double theValue,
4062 CORBA::Boolean theCopyGroups,
4063 CORBA::Boolean theCopyElements,
4064 const char* theMeshName,
4065 SMESH::ListOfGroups_out theGroups)
4070 SMESHDS_Mesh* aMeshDS = getMeshDS();
4072 SMESH::SMESH_Mesh_var mesh_var;
4073 ::SMESH_MeshEditor::PGroupIDs groupIds;
4077 TIDSortedElemSet elements, copyElements;
4078 if ( idSourceToSet( theObject, aMeshDS, elements, SMDSAbs_Face,
4079 /*emptyIfIsMesh=*/ !myIsPreviewMode ))
4082 SMESH_Mesh* tgtMesh = 0;
4083 if ( myIsPreviewMode )
4085 TPreviewMesh * tmpMesh = getPreviewMesh();
4087 tmpMesh->Copy( elements, copyElements );
4088 elements.swap( copyElements );
4089 theCopyGroups = false;
4090 theCopyElements = false;
4095 *theMeshName ? makeMesh( theMeshName ) : SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
4096 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
4097 tgtMesh = & mesh_i->GetImpl();
4099 groupIds = getEditor().Offset( elements, theValue, tgtMesh,
4100 theCopyGroups, theCopyElements, !myIsPreviewMode );
4102 tgtMesh->GetMeshDS()->Modified();
4105 if ( myIsPreviewMode )
4107 //getPreviewMesh()->Remove( SMESHUtils::elemSetIterator( copyElements ));
4111 if ( *theMeshName && mesh_var->NbFaces() == 0 )
4113 // new mesh empty, remove it
4114 SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->getStudyServant();
4115 SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
4116 SALOMEDS::SObject_wrap meshSO = SMESH_Gen_i::GetSMESHGen()->ObjectToSObject( mesh_var );
4117 builder->RemoveObjectWithChildren( meshSO );
4118 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4120 if ( !groupIds ) // nothing changed in the current mesh
4121 THROW_SALOME_CORBA_EXCEPTION("Offset failed", SALOME::INTERNAL_ERROR);
4123 theGroups = theCopyGroups ? getGroups( groupIds.get() ) : new SMESH::ListOfGroups;
4125 // result of Offset() is a tuple (mesh, groups)
4126 if ( mesh_var->_is_nil() ) pyDump << myMesh_i->_this() << ", ";
4127 else pyDump << mesh_var << ", ";
4128 pyDump << theGroups << " = " << this << ".Offset( "
4129 << theObject << ", "
4131 << theCopyGroups << ", "
4132 << theCopyElements << ", "
4133 << "'" << theMeshName<< "')";
4136 return mesh_var._retn();
4138 SMESH_CATCH( SMESH::throwCorbaException );
4139 return SMESH::SMESH_Mesh::_nil();
4142 //=======================================================================
4143 //function : findCoincidentNodes
4145 //=======================================================================
4147 void SMESH_MeshEditor_i::
4148 findCoincidentNodes (TIDSortedNodeSet & Nodes,
4149 CORBA::Double Tolerance,
4150 SMESH::array_of_long_array_out GroupsOfNodes,
4151 CORBA::Boolean SeparateCornersAndMedium)
4153 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4154 getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
4156 GroupsOfNodes = new SMESH::array_of_long_array;
4157 GroupsOfNodes->length( aListOfListOfNodes.size() );
4158 ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4159 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4161 list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4162 list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4163 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4164 aGroup.length( aListOfNodes.size() );
4165 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4166 aGroup[ j ] = (*lIt)->GetID();
4170 //=======================================================================
4171 //function : FindCoincidentNodes
4173 //=======================================================================
4175 void SMESH_MeshEditor_i::
4176 FindCoincidentNodes (CORBA::Double Tolerance,
4177 SMESH::array_of_long_array_out GroupsOfNodes,
4178 CORBA::Boolean SeparateCornersAndMedium)
4183 TIDSortedNodeSet nodes; // no input nodes
4184 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4186 TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4187 << Tolerance << ", "
4188 << SeparateCornersAndMedium << " )";
4190 SMESH_CATCH( SMESH::throwCorbaException );
4193 //=======================================================================
4194 //function : FindCoincidentNodesOnPart
4196 //=======================================================================
4198 void SMESH_MeshEditor_i::
4199 FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
4200 CORBA::Double Tolerance,
4201 SMESH::array_of_long_array_out GroupsOfNodes,
4202 CORBA::Boolean SeparateCornersAndMedium)
4207 TIDSortedNodeSet nodes;
4208 prepareIdSource( theObject );
4209 idSourceToNodeSet( theObject, getMeshDS(), nodes );
4211 findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
4213 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4215 << Tolerance << ", "
4216 << SeparateCornersAndMedium << " )";
4218 SMESH_CATCH( SMESH::throwCorbaException );
4221 //================================================================================
4223 * \brief Finds nodes coincident with Tolerance within Objects excluding nodes within
4224 * ExceptSubMeshOrGroups
4226 //================================================================================
4228 void SMESH_MeshEditor_i::
4229 FindCoincidentNodesOnPartBut(const SMESH::ListOfIDSources& theObjects,
4230 CORBA::Double theTolerance,
4231 SMESH::array_of_long_array_out theGroupsOfNodes,
4232 const SMESH::ListOfIDSources& theExceptSubMeshOrGroups,
4233 CORBA::Boolean theSeparateCornersAndMedium)
4238 TIDSortedNodeSet nodes;
4239 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4241 prepareIdSource( theObjects[i] );
4242 idSourceToNodeSet( theObjects[i], getMeshDS(), nodes );
4244 for ( CORBA::ULong i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4246 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( theExceptSubMeshOrGroups[i],
4248 while ( nodeIt->more() )
4249 nodes.erase( cast2Node( nodeIt->next() ));
4251 findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium );
4253 TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4254 << theObjects <<", "
4255 << theTolerance << ", "
4256 << theExceptSubMeshOrGroups << ", "
4257 << theSeparateCornersAndMedium << " )";
4259 SMESH_CATCH( SMESH::throwCorbaException );
4262 //=======================================================================
4263 //function : MergeNodes
4265 //=======================================================================
4267 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
4268 const SMESH::ListOfIDSources& NodesToKeep,
4269 CORBA::Boolean AvoidMakingHoles)
4274 SMESHDS_Mesh* aMesh = getMeshDS();
4276 TPythonDump aTPythonDump;
4277 aTPythonDump << this << ".MergeNodes([";
4279 TIDSortedNodeSet setOfNodesToKeep;
4280 for ( CORBA::ULong i = 0; i < NodesToKeep.length(); ++i )
4282 prepareIdSource( NodesToKeep[i] );
4283 if ( SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ))
4284 while ( nodeIt->more() )
4285 setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() ));
4288 ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4289 for ( CORBA::ULong i = 0; i < GroupsOfNodes.length(); i++ )
4291 const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4292 aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4293 list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4294 for ( CORBA::ULong j = 0; j < aNodeGroup.length(); j++ )
4296 CORBA::Long index = aNodeGroup[ j ];
4297 if ( const SMDS_MeshNode * node = aMesh->FindNode( index ))
4299 if ( setOfNodesToKeep.count( node ))
4300 aListOfNodes.push_front( node );
4302 aListOfNodes.push_back( node );
4305 if ( aListOfNodes.size() < 2 )
4306 aListOfListOfNodes.pop_back();
4308 if ( i > 0 ) aTPythonDump << ", ";
4309 aTPythonDump << aNodeGroup;
4312 getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
4314 aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
4316 declareMeshModified( /*isReComputeSafe=*/false );
4318 SMESH_CATCH( SMESH::throwCorbaException );
4321 //=======================================================================
4322 //function : FindEqualElements
4324 //=======================================================================
4326 void SMESH_MeshEditor_i::FindEqualElements(const SMESH::ListOfIDSources& theObjects,
4327 const SMESH::ListOfIDSources& theExceptObjects,
4328 SMESH::array_of_long_array_out theGroupsOfElementsID)
4333 theGroupsOfElementsID = new SMESH::array_of_long_array;
4335 TIDSortedElemSet elems;
4336 bool hasOkObject = false;
4337 bool emptyIfIsMesh= ( theObjects.length() == 1 && theExceptObjects.length() == 0 );
4339 for ( CORBA::ULong i = 0; i < theObjects.length(); ++i )
4341 SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow( theObjects[i] );
4342 if ( !( !group->_is_nil() && group->GetType() == SMESH::NODE ))
4343 if ( idSourceToSet( theObjects[i], getMeshDS(), elems, SMDSAbs_All, emptyIfIsMesh ))
4349 for ( CORBA::ULong i = 0; i < theExceptObjects.length(); ++i )
4351 if ( SMDS_ElemIteratorPtr elemIt = myMesh_i->GetElements( theExceptObjects[i], SMESH::ALL ))
4352 while ( elemIt->more() )
4353 elems.erase( elemIt->next() );
4356 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4357 getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4359 theGroupsOfElementsID->length( aListOfListOfElementsID.size() );
4361 ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4362 aListOfListOfElementsID.begin();
4363 for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4365 SMESH::long_array& aGroup = (*theGroupsOfElementsID)[ j ];
4366 list<smIdType>& listOfIDs = *arraysIt;
4367 aGroup.length( listOfIDs.size() );
4368 list<smIdType>::iterator idIt = listOfIDs.begin();
4369 for (smIdType k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4370 aGroup[ k ] = *idIt;
4373 TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4374 << theObjects << ", "
4375 << theExceptObjects << " )";
4378 SMESH_CATCH( SMESH::throwCorbaException );
4381 //=======================================================================
4382 //function : MergeElements
4384 //=======================================================================
4386 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& theGroupsOfElementsID,
4387 const SMESH::ListOfIDSources& theElementsToKeep)
4392 TPythonDump aTPythonDump;
4393 aTPythonDump << this << ".MergeElements( [";
4395 NCollection_Map< int > idsToKeep;
4396 for ( CORBA::ULong i = 0; i < theElementsToKeep.length(); i++ )
4398 if ( CORBA::is_nil( theElementsToKeep[i] ))
4400 SMESH::array_of_ElementType_var elemTypes = theElementsToKeep[i]->GetTypes();
4401 if ( elemTypes->length() == 1 && elemTypes[0] == SMESH::NODE )
4403 SMESH::smIdType_array_var elementsId = theElementsToKeep[i]->GetIDs();
4404 for ( CORBA::ULong j = 0; j < elementsId->length(); ++j )
4405 idsToKeep.Add( elementsId[ j ]);
4408 ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4410 for ( CORBA::ULong i = 0; i < theGroupsOfElementsID.length(); i++ )
4412 const SMESH::long_array& anElemsIDGroup = theGroupsOfElementsID[ i ];
4413 aListOfListOfElementsID.push_back( list< smIdType >() );
4414 list< smIdType >& aListOfElemsID = aListOfListOfElementsID.back();
4415 for ( CORBA::ULong j = 0; j < anElemsIDGroup.length(); j++ )
4417 SMESH::smIdType id = anElemsIDGroup[ j ];
4418 if ( idsToKeep.Contains( id )) aListOfElemsID.push_front( id );
4419 else aListOfElemsID.push_back( id );
4421 if ( aListOfElemsID.size() < 2 )
4422 aListOfListOfElementsID.pop_back();
4423 if ( i > 0 ) aTPythonDump << ", ";
4424 aTPythonDump << anElemsIDGroup;
4427 getEditor().MergeElements(aListOfListOfElementsID);
4429 declareMeshModified( /*isReComputeSafe=*/true );
4431 aTPythonDump << "], " << theElementsToKeep << " )";
4433 SMESH_CATCH( SMESH::throwCorbaException );
4436 //=======================================================================
4437 //function : MergeEqualElements
4439 //=======================================================================
4441 void SMESH_MeshEditor_i::MergeEqualElements()
4446 getEditor().MergeEqualElements();
4448 declareMeshModified( /*isReComputeSafe=*/true );
4450 TPythonDump() << this << ".MergeEqualElements()";
4452 SMESH_CATCH( SMESH::throwCorbaException );
4455 //=============================================================================
4457 * Move the node to a given point
4459 //=============================================================================
4461 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(SMESH::smIdType NodeID,
4467 initData(/*deleteSearchers=*/false);
4469 const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
4473 if ( theNodeSearcher )
4474 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4476 if ( myIsPreviewMode ) // make preview data
4478 // in a preview mesh, make edges linked to a node
4479 TPreviewMesh& tmpMesh = *getPreviewMesh();
4480 TIDSortedElemSet linkedNodes;
4481 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4482 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4483 SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4484 for ( ; nIt != linkedNodes.end(); ++nIt )
4486 SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4487 tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4491 tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4492 // fill preview data
4494 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4495 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4497 getMeshDS()->MoveNode(node, x, y, z);
4499 if ( !myIsPreviewMode )
4501 // Update Python script
4502 TPythonDump() << "isDone = " << this << ".MoveNode( "
4503 << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
4504 declareMeshModified( /*isReComputeSafe=*/false );
4507 SMESH_CATCH( SMESH::throwCorbaException );
4512 //================================================================================
4514 * \brief Return ID of node closest to a given point
4516 //================================================================================
4518 SMESH::smIdType SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4523 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4525 if ( !theNodeSearcher ) {
4526 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4529 if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4530 return node->GetID();
4532 SMESH_CATCH( SMESH::throwCorbaException );
4536 //================================================================================
4538 * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4539 * move the node closest to the point to point's location and return ID of the node
4541 //================================================================================
4543 SMESH::smIdType SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4546 SMESH::smIdType theNodeID)
4549 // We keep theNodeSearcher until any mesh modification:
4550 // 1) initData() deletes theNodeSearcher at any edition,
4551 // 2) TSearchersDeleter - at any mesh compute event and mesh change
4553 initData(/*deleteSearchers=*/false);
4555 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4557 smIdType nodeID = theNodeID;
4558 const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
4559 if ( !node ) // preview moving node
4561 if ( !theNodeSearcher ) {
4562 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
4565 node = theNodeSearcher->FindClosestTo( p );
4568 nodeID = node->GetID();
4569 if ( myIsPreviewMode ) // make preview data
4571 // in a preview mesh, make edges linked to a node
4572 TPreviewMesh tmpMesh = *getPreviewMesh();
4573 TIDSortedElemSet linkedNodes;
4574 ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4575 TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4576 for ( ; nIt != linkedNodes.end(); ++nIt )
4578 SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4579 tmpMesh.Copy( &edge );
4582 node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4584 tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4585 // fill preview data
4587 else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4589 theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4593 getMeshDS()->MoveNode(node, x, y, z);
4597 if ( !myIsPreviewMode )
4599 TPythonDump() << "nodeID = " << this
4600 << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4601 << ", " << nodeID << " )";
4603 declareMeshModified( /*isReComputeSafe=*/false );
4608 SMESH_CATCH( SMESH::throwCorbaException );
4612 //=======================================================================
4614 * Return elements of given type where the given point is IN or ON.
4616 * 'ALL' type means elements of any type excluding nodes
4618 //=======================================================================
4620 SMESH::smIdType_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double x,
4623 SMESH::ElementType type)
4626 SMESH::smIdType_array_var res = new SMESH::smIdType_array;
4627 vector< const SMDS_MeshElement* > foundElems;
4629 theSearchersDeleter.Set( myMesh );
4630 if ( !theElementSearcher ) {
4631 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4633 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4634 SMDSAbs_ElementType( type ),
4636 res->length( foundElems.size() );
4637 for ( size_t i = 0; i < foundElems.size(); ++i )
4638 res[i] = foundElems[i]->GetID();
4642 SMESH_CATCH( SMESH::throwCorbaException );
4646 //=======================================================================
4647 //function : FindAmongElementsByPoint
4648 //purpose : Searching among the given elements, return elements of given type
4649 // where the given point is IN or ON.
4650 // 'ALL' type means elements of any type excluding nodes
4651 //=======================================================================
4653 SMESH::smIdType_array*
4654 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4658 SMESH::ElementType type)
4661 SMESH::smIdType_array_var res = new SMESH::smIdType_array;
4663 prepareIdSource( elementIDs );
4664 if ( type != SMESH::NODE )
4666 SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4667 if ( types->length() == 1 && // a part contains only nodes or 0D elements
4668 ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
4669 type != types[0] ) // but search of elements of dim > 0
4673 SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4674 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4675 if ( mesh_i != myMesh_i )
4677 SMESH::SMESH_MeshEditor_var editor=
4678 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4679 return editor->FindAmongElementsByPoint( elementIDs, x,y,z, type );
4682 if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh
4683 return FindElementsByPoint( x,y,z, type );
4685 TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4687 theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
4688 if ( !theElementSearcher )
4690 // create a searcher from elementIDs
4691 SMDS_ElemIteratorPtr elemIt;
4692 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( elementIDs ))
4694 //prepareIdSource( elementIDs );
4695 elemIt = myMesh_i->GetElements( elementIDs, type );
4699 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4702 vector< const SMDS_MeshElement* > foundElems;
4704 theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4705 SMDSAbs_ElementType( type ),
4707 res->length( foundElems.size() );
4708 for ( size_t i = 0; i < foundElems.size(); ++i )
4709 res[i] = foundElems[i]->GetID();
4713 SMESH_CATCH( SMESH::throwCorbaException );
4717 //=======================================================================
4718 //function : ProjectPoint
4719 //purpose : Project a point to a mesh object.
4720 // Return ID of an element of given type where the given point is projected
4721 // and coordinates of the projection point.
4722 // In the case if nothing found, return -1 and []
4723 //=======================================================================
4725 SMESH::smIdType SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
4728 SMESH::ElementType type,
4729 SMESH::SMESH_IDSource_ptr meshObject,
4730 SMESH::double_array_out projecton)
4732 if ( CORBA::is_nil( meshObject ))
4733 THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
4737 SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
4738 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4739 if ( mesh_i != myMesh_i )
4741 SMESH::SMESH_MeshEditor_var editor=
4742 myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
4743 return editor->ProjectPoint( x,y,z, type, meshObject, projecton );
4747 theSearchersDeleter.Set( myMesh, getPartIOR( meshObject, type ));
4748 if ( !theElementSearcher )
4750 // create a searcher from meshObject
4752 SMDS_ElemIteratorPtr elemIt;
4753 if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
4755 prepareIdSource( meshObject );
4756 elemIt = myMesh_i->GetElements( meshObject, type );
4760 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
4763 const SMDS_MeshElement* elem = 0;
4764 gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
4765 SMDSAbs_ElementType( type ),
4768 projecton = new SMESH::double_array();
4769 if ( elem && !elem->IsNull() )
4771 projecton->length( 3 );
4772 projecton[0] = pProj.X();
4773 projecton[1] = pProj.Y();
4774 projecton[2] = pProj.Z();
4775 return elem->GetID();
4778 SMESH_CATCH( SMESH::throwCorbaException );
4782 //=======================================================================
4783 //function : GetPointState
4784 //purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4785 // TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4786 //=======================================================================
4788 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4793 theSearchersDeleter.Set( myMesh );
4794 if ( !theElementSearcher ) {
4795 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
4797 return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4799 SMESH_CATCH( SMESH::throwCorbaException );
4803 //=======================================================================
4804 //function : IsManifold
4805 //purpose : Check if a 2D mesh is manifold
4806 //=======================================================================
4808 CORBA::Boolean SMESH_MeshEditor_i::IsManifold()
4810 bool isManifold = true;
4813 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4814 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4816 /*closedOnly=*/true,
4818 SMESH_CATCH( SMESH::throwCorbaException );
4823 //=======================================================================
4824 //function : IsCoherentOrientation2D
4825 //purpose : Check if orientation of 2D elements is coherent
4826 //=======================================================================
4828 CORBA::Boolean SMESH_MeshEditor_i::IsCoherentOrientation2D()
4830 bool isGoodOri = true;
4833 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4834 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(),
4836 /*closedOnly=*/true,
4839 SMESH_CATCH( SMESH::throwCorbaException );
4844 //=======================================================================
4845 //function : Get1DBranches
4846 //purpose : Partition given 1D elements into groups of contiguous edges.
4847 // A node where number of meeting edges != 2 is a group end.
4848 // An optional startNode is used to orient groups it belongs to.
4849 //return : a list of edge groups and a list of corresponding node groups.
4850 // If a group is closed, the first and last nodes of the group are same.
4851 //=======================================================================
4853 SMESH::array_of_long_array*
4854 SMESH_MeshEditor_i::Get1DBranches( SMESH::SMESH_IDSource_ptr theEdges,
4855 SMESH::smIdType theStartNode,
4856 SMESH::array_of_long_array_out theNodeGroups )
4858 if ( CORBA::is_nil( theEdges ))
4859 THROW_SALOME_CORBA_EXCEPTION("Get1DBranches(): NULL group given", SALOME::BAD_PARAM);
4861 SMESH::array_of_long_array_var edgeGroupArray = new SMESH::array_of_long_array;
4862 theNodeGroups = new SMESH::array_of_long_array;
4866 prepareIdSource( theEdges );
4868 SMESH_MeshAlgos::TElemGroupVector edgeBranches;
4869 SMESH_MeshAlgos::TNodeGroupVector nodeBranches;
4870 SMESH_MeshAlgos::Get1DBranches( SMESH_Mesh_i::GetElements( theEdges, SMESH::EDGE ),
4873 getMeshDS()->FindNode( theStartNode ));
4875 edgeGroupArray->length( edgeBranches.size() );
4876 for ( size_t iG = 0; iG < edgeBranches.size(); ++iG )
4878 edgeGroupArray[ iG ].length( edgeBranches[ iG ].size() );
4879 for ( size_t i = 0; i < edgeBranches[ iG ].size(); ++i )
4880 edgeGroupArray[ iG ][ i ] = edgeBranches[ iG ][ i ]->GetID();
4883 theNodeGroups->length( nodeBranches.size() );
4884 for ( size_t iG = 0; iG < nodeBranches.size(); ++iG )
4886 theNodeGroups[ iG ].length( nodeBranches[ iG ].size() );
4887 for ( size_t i = 0; i < nodeBranches[ iG ].size(); ++i )
4888 theNodeGroups[ iG ][ i ] = nodeBranches[ iG ][ i ]->GetID();
4891 SMESH_CATCH( SMESH::throwCorbaException );
4893 return edgeGroupArray._retn();
4896 //=======================================================================
4897 //function : FindSharpEdges
4898 //purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
4899 //=======================================================================
4901 SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
4902 CORBA::Boolean theAddExisting)
4904 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
4909 std::vector< SMESH_MeshAlgos::Edge > edges =
4910 SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
4912 if ( myIsPreviewMode ) // fill a preview mesh with edges
4914 TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
4915 SMDS_Mesh* meshDS = mesh->GetMeshDS();
4916 for ( size_t i = 0; i < edges.size(); ++i )
4918 SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
4919 SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4920 SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
4921 if ( edges[i]._medium )
4923 xyz1.Set( edges[i]._medium );
4924 SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
4925 mesh->GetMeshDS()->AddEdge( n1, n2, nm );
4929 mesh->GetMeshDS()->AddEdge( n1, n2 );
4935 resultEdges->length( edges.size() );
4936 for ( size_t i = 0; i < edges.size(); ++i )
4938 resultEdges[ i ].node1 = edges[i]._node1->GetID();
4939 resultEdges[ i ].node2 = edges[i]._node2->GetID();
4940 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
4943 SMESH_CATCH( SMESH::throwCorbaException );
4944 return resultEdges._retn();
4947 //=======================================================================
4948 //function : FindFreeBorders
4949 //purpose : Returns all or only closed FreeBorder's.
4950 //=======================================================================
4952 SMESH::ListOfFreeBorders* SMESH_MeshEditor_i::FindFreeBorders(CORBA::Boolean closedOnly)
4954 SMESH::ListOfFreeBorders_var resBorders = new SMESH::ListOfFreeBorders;
4957 SMESH_MeshAlgos::TFreeBorderVec foundFreeBordes;
4958 SMESH_MeshAlgos::FindFreeBorders( *getMeshDS(), foundFreeBordes, closedOnly );
4960 resBorders->length( foundFreeBordes.size() );
4961 for ( size_t i = 0; i < foundFreeBordes.size(); ++i )
4963 const SMESH_MeshAlgos::TFreeBorder& bordNodes = foundFreeBordes[i];
4964 SMESH::FreeBorder& bordOut = resBorders[i];
4965 bordOut.nodeIDs.length( bordNodes.size() );
4966 for ( size_t iN = 0; iN < bordNodes.size(); ++iN )
4967 bordOut.nodeIDs[ iN ] = bordNodes[ iN ]->GetID();
4970 SMESH_CATCH( SMESH::throwCorbaException );
4972 return resBorders._retn();
4975 //=======================================================================
4976 //function : FillHole
4977 //purpose : Fill with 2D elements a hole defined by a FreeBorder.
4978 //=======================================================================
4980 SMESH::SMESH_Group_ptr
4981 SMESH_MeshEditor_i::FillHole(const SMESH::FreeBorder& theHole,
4982 const char* theGroupName)
4986 if ( theHole.nodeIDs.length() < 4 )
4987 THROW_SALOME_CORBA_EXCEPTION("A hole should be bound by at least 3 nodes", SALOME::BAD_PARAM);
4988 if ( theHole.nodeIDs[0] != theHole.nodeIDs[ theHole.nodeIDs.length()-1 ] )
4989 THROW_SALOME_CORBA_EXCEPTION("Not closed hole boundary. "
4990 "First and last nodes must be same", SALOME::BAD_PARAM);
4992 SMESH_MeshAlgos::TFreeBorder bordNodes;
4993 bordNodes.resize( theHole.nodeIDs.length() );
4994 for ( size_t iN = 0; iN < theHole.nodeIDs.length(); ++iN )
4996 bordNodes[ iN ] = getMeshDS()->FindNode( theHole.nodeIDs[ iN ]);
4997 if ( !bordNodes[ iN ] )
4998 THROW_SALOME_CORBA_EXCEPTION(SMESH_Comment("Node #") << theHole.nodeIDs[ iN ]
4999 << " does not exist", SALOME::BAD_PARAM);
5004 // prepare a preview mesh
5005 MeshEditor_I::TPreviewMesh* previewMesh = 0;
5006 SMDS_Mesh* meshDS = getMeshDS();
5007 if ( myIsPreviewMode )
5009 // copy faces sharing nodes of theHole
5010 TIDSortedElemSet holeFaces;
5011 previewMesh = getPreviewMesh( SMDSAbs_Face );
5012 for ( size_t i = 0; i < bordNodes.size(); ++i )
5014 SMDS_ElemIteratorPtr fIt = bordNodes[i]->GetInverseElementIterator( SMDSAbs_Face );
5015 while ( fIt->more() )
5017 const SMDS_MeshElement* face = fIt->next();
5018 if ( holeFaces.insert( face ).second )
5019 previewMesh->Copy( face );
5021 bordNodes[i] = previewMesh->GetMeshDS()->FindNode( bordNodes[i]->GetID() );
5022 ASSERT( bordNodes[i] );
5024 meshDS = previewMesh->GetMeshDS();
5028 std::vector<const SMDS_MeshElement*> newFaces;
5029 SMESH_MeshAlgos::FillHole( bordNodes, *meshDS, newFaces );
5031 if ( myIsPreviewMode )
5034 previewMesh->Clear();
5035 for ( size_t i = 0; i < newFaces.size(); ++i )
5036 previewMesh->Copy( newFaces[i] );
5040 // return new faces via a group
5041 SMESH::SMESH_Group_var group;
5042 if ( theGroupName && theGroupName[0] && !newFaces.empty() )
5044 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5045 for ( CORBA::ULong i = 0; i < groups->length(); ++i )
5047 SMESH::SMESH_GroupBase_var g = groups[ i ];
5048 if ( g->GetType() != SMESH::FACE ) continue;
5049 SMESH::SMESH_Group_var standalone = SMESH::SMESH_Group::_narrow( g );
5050 if ( standalone->_is_nil() ) continue;
5051 CORBA::String_var name = g->GetName();
5052 if ( strcmp( theGroupName, name.in() ) == 0 )
5058 if ( group->_is_nil() )
5059 group = myMesh_i->CreateGroup( SMESH::FACE, theGroupName );
5061 if ( !group->_is_nil() )
5063 SMESH_GroupBase_i * grpI = SMESH::DownCast< SMESH_GroupBase_i* >( group );
5064 SMESHDS_Group* grpDS = static_cast< SMESHDS_Group* >( grpI->GetGroupDS() );
5065 for ( size_t i = 0; i < newFaces.size(); ++i )
5066 grpDS->Add( newFaces[ i ]);
5071 getEditor().ClearLastCreated();
5072 SMESH_SequenceOfElemPtr& aSeq =
5073 const_cast<SMESH_SequenceOfElemPtr&>( getEditor().GetLastCreatedElems() );
5074 aSeq.swap( newFaces );
5077 if ( group->_is_nil() ) pyDump << "_group = ";
5078 else pyDump << group << " = ";
5079 pyDump << this << ".FillHole( SMESH.FreeBorder(" << theHole.nodeIDs << " ))";
5081 return group._retn();
5084 SMESH_CATCH( SMESH::throwCorbaException );
5086 return SMESH::SMESH_Group::_nil();
5089 //=======================================================================
5090 //function : convError
5092 //=======================================================================
5094 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5096 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5100 RETCASE( SEW_BORDER1_NOT_FOUND );
5101 RETCASE( SEW_BORDER2_NOT_FOUND );
5102 RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5103 RETCASE( SEW_BAD_SIDE_NODES );
5104 RETCASE( SEW_VOLUMES_TO_SPLIT );
5105 RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5106 RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5107 RETCASE( SEW_BAD_SIDE1_NODES );
5108 RETCASE( SEW_BAD_SIDE2_NODES );
5109 RETCASE( SEW_INTERNAL_ERROR );
5111 return SMESH::SMESH_MeshEditor::SEW_OK;
5114 //=======================================================================
5116 * Returns groups of FreeBorder's coincident within the given tolerance.
5117 * If the tolerance <= 0.0 then one tenth of an average size of elements adjacent
5118 * to free borders being compared is used.
5120 //=======================================================================
5122 SMESH::CoincidentFreeBorders*
5123 SMESH_MeshEditor_i::FindCoincidentFreeBorders(CORBA::Double tolerance)
5125 SMESH::CoincidentFreeBorders_var aCFB = new SMESH::CoincidentFreeBorders;
5129 SMESH_MeshAlgos::CoincidentFreeBorders cfb;
5130 SMESH_MeshAlgos::FindCoincidentFreeBorders( *getMeshDS(), tolerance, cfb );
5132 // copy free borders
5133 aCFB->borders.length( cfb._borders.size() );
5134 for ( size_t i = 0; i < cfb._borders.size(); ++i )
5136 SMESH_MeshAlgos::TFreeBorder& nodes = cfb._borders[i];
5137 SMESH::FreeBorder& aBRD = aCFB->borders[i];
5138 aBRD.nodeIDs.length( nodes.size() );
5139 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5140 aBRD.nodeIDs[ iN ] = nodes[ iN ]->GetID();
5143 // copy coincident parts
5144 aCFB->coincidentGroups.length( cfb._coincidentGroups.size() );
5145 for ( size_t i = 0; i < cfb._coincidentGroups.size(); ++i )
5147 SMESH_MeshAlgos::TCoincidentGroup& grp = cfb._coincidentGroups[i];
5148 SMESH::FreeBordersGroup& aGRP = aCFB->coincidentGroups[i];
5149 aGRP.length( grp.size() );
5150 for ( size_t iP = 0; iP < grp.size(); ++iP )
5152 SMESH_MeshAlgos::TFreeBorderPart& part = grp[ iP ];
5153 SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5154 aPART.border = part._border;
5155 aPART.node1 = part._node1;
5156 aPART.node2 = part._node2;
5157 aPART.nodeLast = part._nodeLast;
5160 SMESH_CATCH( SMESH::doNothing );
5162 TPythonDump() << "CoincidentFreeBorders = "
5163 << this << ".FindCoincidentFreeBorders( " << tolerance << " )";
5165 return aCFB._retn();
5168 //=======================================================================
5170 * Sew FreeBorder's of each group
5172 //=======================================================================
5174 CORBA::Short SMESH_MeshEditor_i::
5175 SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
5176 CORBA::Boolean createPolygons,
5177 CORBA::Boolean createPolyhedra)
5179 CORBA::Short nbSewed = 0;
5181 SMESH_MeshAlgos::TFreeBorderVec groups;
5182 SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
5184 // check the input and collect nodes
5185 for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
5187 borderNodes.clear();
5188 const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
5189 for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
5191 const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
5192 if ( aPART.border < 0 || aPART.border >= (int) freeBorders.borders.length() )
5193 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::border index", SALOME::BAD_PARAM);
5195 const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
5197 if ( aPART.node1 < 0 || aPART.node1 > (int) aBRD.nodeIDs.length() )
5198 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node1", SALOME::BAD_PARAM);
5199 if ( aPART.node2 < 0 || aPART.node2 > (int) aBRD.nodeIDs.length() )
5200 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::node2", SALOME::BAD_PARAM);
5201 if ( aPART.nodeLast < 0 || aPART.nodeLast > (int) aBRD.nodeIDs.length() )
5202 THROW_SALOME_CORBA_EXCEPTION("Invalid FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5204 // do not keep these nodes for further sewing as nodes can be removed by the sewing
5205 const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
5206 const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
5207 const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
5209 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node1", SALOME::BAD_PARAM);
5211 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
5213 THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
5215 borderNodes.push_back( n1 );
5216 borderNodes.push_back( n2 );
5217 borderNodes.push_back( n3 );
5219 groups.push_back( borderNodes );
5222 // SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
5223 // to get nodes that replace other nodes during merge we create 0D elements
5224 // on each node and MergeNodes() will replace underlying nodes of 0D elements by
5227 vector< const SMDS_MeshElement* > tmp0Delems;
5228 for ( size_t i = 0; i < groups.size(); ++i )
5230 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5231 for ( size_t iN = 0; iN < nodes.size(); ++iN )
5233 SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
5235 tmp0Delems.push_back( it0D->next() );
5237 tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
5241 // cout << endl << "INIT" << endl;
5242 // for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5244 // cout << i << " ";
5245 // if ( i % 3 == 0 ) cout << "^ ";
5246 // tmp0Delems[i]->GetNode(0)->Print( cout );
5251 ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
5253 for ( size_t i = 0; i < groups.size(); ++i )
5255 bool isBordToBord = true;
5256 bool groupSewed = false;
5257 SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
5258 for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
5260 const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
5261 const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
5262 const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
5264 const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
5265 const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
5266 const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
5268 if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
5271 // TIDSortedElemSet emptySet, avoidSet;
5272 // if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, emptySet, avoidSet))
5274 // cout << "WRONG 2nd 1" << endl;
5275 // n0->Print( cout );
5276 // n1->Print( cout );
5278 // if ( !SMESH_MeshAlgos::FindFaceInSet( n3, n4, emptySet, avoidSet))
5280 // cout << "WRONG 2nd 2" << endl;
5281 // n3->Print( cout );
5282 // n4->Print( cout );
5285 if ( !isBordToBord )
5287 n1 = n2; // at border-to-side sewing only last side node (n1) is needed
5288 n2 = 0; // and n2 is not used
5290 // 1st border moves to 2nd
5291 res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
5293 /*2ndIsFreeBorder=*/ isBordToBord,
5294 createPolygons, createPolyhedra);
5295 groupSewed = ( res == ok );
5297 isBordToBord = false;
5298 // cout << endl << "SEWED GROUP " << i << " PART " << iN / 3 << endl;
5299 // for ( size_t t = 0; t < tmp0Delems.size(); ++t )
5301 // cout << t << " ";
5302 // if ( t % 3 == 0 ) cout << "^ ";
5303 // tmp0Delems[t]->GetNode(0)->Print( cout );
5306 i0D += nodes.size();
5307 nbSewed += groupSewed;
5310 TPythonDump() << "nbSewed = " << this << ".SewCoincidentFreeBorders( "
5311 << freeBorders << ", "
5312 << createPolygons << ", "
5313 << createPolyhedra << " )";
5315 SMESH_CATCH( SMESH::doNothing );
5317 declareMeshModified( /*isReComputeSafe=*/false );
5319 // remove tmp 0D elements
5321 set< const SMDS_MeshElement* > removed0D;
5322 for ( size_t i = 0; i < tmp0Delems.size(); ++i )
5324 if ( removed0D.insert( tmp0Delems[i] ).second )
5325 getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
5327 SMESH_CATCH( SMESH::throwCorbaException );
5332 //=======================================================================
5333 //function : SewFreeBorders
5335 //=======================================================================
5337 SMESH::SMESH_MeshEditor::Sew_Error
5338 SMESH_MeshEditor_i::SewFreeBorders(SMESH::smIdType FirstNodeID1,
5339 SMESH::smIdType SecondNodeID1,
5340 SMESH::smIdType LastNodeID1,
5341 SMESH::smIdType FirstNodeID2,
5342 SMESH::smIdType SecondNodeID2,
5343 SMESH::smIdType LastNodeID2,
5344 CORBA::Boolean CreatePolygons,
5345 CORBA::Boolean CreatePolyedrs)
5350 SMESHDS_Mesh* aMesh = getMeshDS();
5352 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5353 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5354 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5355 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5356 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
5357 const SMDS_MeshNode* aSide2ThirdNode = aMesh->FindNode( LastNodeID2 );
5359 if (!aBorderFirstNode ||
5360 !aBorderSecondNode||
5362 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5363 if (!aSide2FirstNode ||
5364 !aSide2SecondNode ||
5366 return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5368 TPythonDump() << "error = " << this << ".SewFreeBorders( "
5369 << FirstNodeID1 << ", "
5370 << SecondNodeID1 << ", "
5371 << LastNodeID1 << ", "
5372 << FirstNodeID2 << ", "
5373 << SecondNodeID2 << ", "
5374 << LastNodeID2 << ", "
5375 << CreatePolygons<< ", "
5376 << CreatePolyedrs<< " )";
5378 SMESH::SMESH_MeshEditor::Sew_Error error =
5379 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5390 declareMeshModified( /*isReComputeSafe=*/false );
5393 SMESH_CATCH( SMESH::throwCorbaException );
5394 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5398 //=======================================================================
5399 //function : SewConformFreeBorders
5401 //=======================================================================
5403 SMESH::SMESH_MeshEditor::Sew_Error
5404 SMESH_MeshEditor_i::SewConformFreeBorders(SMESH::smIdType FirstNodeID1,
5405 SMESH::smIdType SecondNodeID1,
5406 SMESH::smIdType LastNodeID1,
5407 SMESH::smIdType FirstNodeID2,
5408 SMESH::smIdType SecondNodeID2)
5413 SMESHDS_Mesh* aMesh = getMeshDS();
5415 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeID1 );
5416 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5417 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeID1 );
5418 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeID2 );
5419 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( SecondNodeID2 );
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_BORDER2_NOT_FOUND;
5430 TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5431 << FirstNodeID1 << ", "
5432 << SecondNodeID1 << ", "
5433 << LastNodeID1 << ", "
5434 << FirstNodeID2 << ", "
5435 << SecondNodeID2 << " )";
5437 SMESH::SMESH_MeshEditor::Sew_Error error =
5438 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5447 declareMeshModified( /*isReComputeSafe=*/false );
5450 SMESH_CATCH( SMESH::throwCorbaException );
5451 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5455 //=======================================================================
5456 //function : SewBorderToSide
5458 //=======================================================================
5460 SMESH::SMESH_MeshEditor::Sew_Error
5461 SMESH_MeshEditor_i::SewBorderToSide(SMESH::smIdType FirstNodeIDOnFreeBorder,
5462 SMESH::smIdType SecondNodeIDOnFreeBorder,
5463 SMESH::smIdType LastNodeIDOnFreeBorder,
5464 SMESH::smIdType FirstNodeIDOnSide,
5465 SMESH::smIdType LastNodeIDOnSide,
5466 CORBA::Boolean CreatePolygons,
5467 CORBA::Boolean CreatePolyedrs)
5472 SMESHDS_Mesh* aMesh = getMeshDS();
5474 const SMDS_MeshNode* aBorderFirstNode = aMesh->FindNode( FirstNodeIDOnFreeBorder );
5475 const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5476 const SMDS_MeshNode* aBorderLastNode = aMesh->FindNode( LastNodeIDOnFreeBorder );
5477 const SMDS_MeshNode* aSide2FirstNode = aMesh->FindNode( FirstNodeIDOnSide );
5478 const SMDS_MeshNode* aSide2SecondNode = aMesh->FindNode( LastNodeIDOnSide );
5479 const SMDS_MeshNode* aSide2ThirdNode = 0;
5481 if (!aBorderFirstNode ||
5482 !aBorderSecondNode||
5484 return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5485 if (!aSide2FirstNode ||
5487 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5489 TPythonDump() << "error = " << this << ".SewBorderToSide( "
5490 << FirstNodeIDOnFreeBorder << ", "
5491 << SecondNodeIDOnFreeBorder << ", "
5492 << LastNodeIDOnFreeBorder << ", "
5493 << FirstNodeIDOnSide << ", "
5494 << LastNodeIDOnSide << ", "
5495 << CreatePolygons << ", "
5496 << CreatePolyedrs << ") ";
5498 SMESH::SMESH_MeshEditor::Sew_Error error =
5499 convError( getEditor().SewFreeBorder (aBorderFirstNode,
5509 declareMeshModified( /*isReComputeSafe=*/false );
5512 SMESH_CATCH( SMESH::throwCorbaException );
5513 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5517 //=======================================================================
5518 //function : SewSideElements
5520 //=======================================================================
5522 SMESH::SMESH_MeshEditor::Sew_Error
5523 SMESH_MeshEditor_i::SewSideElements(const SMESH::smIdType_array& IDsOfSide1Elements,
5524 const SMESH::smIdType_array& IDsOfSide2Elements,
5525 SMESH::smIdType NodeID1OfSide1ToMerge,
5526 SMESH::smIdType NodeID1OfSide2ToMerge,
5527 SMESH::smIdType NodeID2OfSide1ToMerge,
5528 SMESH::smIdType NodeID2OfSide2ToMerge)
5533 SMESHDS_Mesh* aMesh = getMeshDS();
5535 const SMDS_MeshNode* aFirstNode1ToMerge = aMesh->FindNode( NodeID1OfSide1ToMerge );
5536 const SMDS_MeshNode* aFirstNode2ToMerge = aMesh->FindNode( NodeID1OfSide2ToMerge );
5537 const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5538 const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5540 if (!aFirstNode1ToMerge ||
5541 !aFirstNode2ToMerge )
5542 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5543 if (!aSecondNode1ToMerge||
5544 !aSecondNode2ToMerge)
5545 return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5547 TIDSortedElemSet aSide1Elems, aSide2Elems;
5548 arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5549 arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5551 TPythonDump() << "error = " << this << ".SewSideElements( "
5552 << IDsOfSide1Elements << ", "
5553 << IDsOfSide2Elements << ", "
5554 << NodeID1OfSide1ToMerge << ", "
5555 << NodeID1OfSide2ToMerge << ", "
5556 << NodeID2OfSide1ToMerge << ", "
5557 << NodeID2OfSide2ToMerge << ")";
5559 SMESH::SMESH_MeshEditor::Sew_Error error =
5560 convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5563 aSecondNode1ToMerge,
5564 aSecondNode2ToMerge));
5566 declareMeshModified( /*isReComputeSafe=*/false );
5569 SMESH_CATCH( SMESH::throwCorbaException );
5570 return SMESH::SMESH_MeshEditor::Sew_Error(0);
5573 //================================================================================
5575 * \brief Set new nodes for given element
5576 * \param ide - element id
5577 * \param newIDs - new node ids
5578 * \retval CORBA::Boolean - true if result is OK
5580 //================================================================================
5582 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(SMESH::smIdType ide,
5583 const SMESH::smIdType_array& newIDs)
5588 const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5589 if ( !elem ) return false;
5591 int nbn = newIDs.length();
5592 vector<const SMDS_MeshNode*> aNodes(nbn);
5593 for ( int i = 0; i < nbn; i++ ) {
5594 const SMDS_MeshNode* aNode = getMeshDS()->FindNode( newIDs[ i ]);
5597 aNodes[ i ] = aNode;
5599 TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5600 << ide << ", " << newIDs << " )";
5602 bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], aNodes.size() );
5604 declareMeshModified( /*isReComputeSafe=*/ !res );
5608 SMESH_CATCH( SMESH::throwCorbaException );
5612 //=======================================================================
5614 * \brief Makes a part of the mesh quadratic or bi-quadratic
5616 //=======================================================================
5618 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean theForce3d,
5619 CORBA::Boolean theToBiQuad,
5620 SMESH::SMESH_IDSource_ptr theObject)
5625 TIDSortedElemSet elems;
5627 if ( !( elemsOK = CORBA::is_nil( theObject )))
5629 elemsOK = idSourceToSet( theObject, getMeshDS(), elems,
5630 SMDSAbs_All, /*emptyIfIsMesh=*/true );
5634 if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5635 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5637 if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5638 else getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5640 declareMeshModified( /*isReComputeSafe=*/false );
5643 SMESH_CATCH( SMESH::throwCorbaException );
5646 //=======================================================================
5647 //function : ConvertFromQuadratic
5649 //=======================================================================
5651 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5656 CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5657 TPythonDump() << this << ".ConvertFromQuadratic()";
5658 declareMeshModified( /*isReComputeSafe=*/!isDone );
5661 SMESH_CATCH( SMESH::throwCorbaException );
5665 //=======================================================================
5666 //function : ConvertToQuadratic
5668 //=======================================================================
5670 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5672 convertToQuadratic( theForce3d, false );
5673 TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5676 //================================================================================
5678 * \brief Makes a part of the mesh quadratic
5680 //================================================================================
5682 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean theForce3d,
5683 SMESH::SMESH_IDSource_ptr theObject)
5685 convertToQuadratic( theForce3d, false, theObject );
5686 TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5689 //================================================================================
5691 * \brief Makes a part of the mesh bi-quadratic
5693 //================================================================================
5695 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean theForce3d,
5696 SMESH::SMESH_IDSource_ptr theObject)
5698 convertToQuadratic( theForce3d, true, theObject );
5699 TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5702 //================================================================================
5704 * \brief Makes a part of the mesh linear
5706 //================================================================================
5708 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5715 TIDSortedElemSet elems;
5716 if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5718 if ( elems.empty() )
5720 ConvertFromQuadratic();
5722 else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5724 THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5728 getEditor().ConvertFromQuadratic(elems);
5731 declareMeshModified( /*isReComputeSafe=*/false );
5733 pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5735 SMESH_CATCH( SMESH::throwCorbaException );
5738 //=======================================================================
5739 //function : makeMesh
5740 //purpose : create a named imported mesh
5741 //=======================================================================
5743 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5745 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5746 SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5747 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( mesh );
5748 gen->SetName( meshSO, theMeshName, "Mesh" );
5749 gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5751 return mesh._retn();
5754 //=======================================================================
5755 //function : dumpGroupsList
5757 //=======================================================================
5759 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump & theDumpPython,
5760 const SMESH::ListOfGroups * theGroupList)
5762 bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5763 if ( isDumpGroupList )
5764 theDumpPython << theGroupList << " = ";
5767 //================================================================================
5769 \brief Generates the unique group name.
5770 \param thePrefix name prefix
5773 //================================================================================
5775 std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
5777 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5778 set<std::string> groupNames;
5780 // Get existing group names
5781 for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5782 SMESH::SMESH_GroupBase_var aGroup = groups[i];
5783 if (CORBA::is_nil(aGroup))
5786 CORBA::String_var name = aGroup->GetName();
5787 groupNames.insert( name.in() );
5791 std::string name = thePrefix;
5794 while (!groupNames.insert(name).second)
5795 name = SMESH_Comment( thePrefix ) << "_" << index++;
5800 //================================================================================
5802 * \brief Prepare SMESH_IDSource for work
5804 //================================================================================
5806 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5808 if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5810 SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5811 filter->SetMesh( mesh );
5814 //================================================================================
5816 * \brief Retrieve elements of given type from SMESH_IDSource
5818 //================================================================================
5820 bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr theIDSource,
5821 const SMESHDS_Mesh* theMeshDS,
5822 TIDSortedElemSet& theElemSet,
5823 const SMDSAbs_ElementType theType,
5824 const bool emptyIfIsMesh,
5825 IDSource_Error* error)
5828 if ( error ) *error = IDSource_OK;
5830 if ( CORBA::is_nil( theIDSource ))
5832 if ( error ) *error = IDSource_INVALID;
5835 if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
5837 if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
5838 *error = IDSource_EMPTY;
5841 if ( getMeshDS() == theMeshDS ) // check if theIDSource belongs to myMesh
5843 SMESH::SMESH_Mesh_var mesh = theIDSource->GetMesh();
5844 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5845 if ( mesh_i && mesh_i != myMesh_i )
5848 *error = IDSource_INVALID;
5852 prepareIdSource( theIDSource );
5853 SMESH::smIdType_array_var anIDs = theIDSource->GetIDs();
5854 if ( anIDs->length() == 0 )
5856 if ( error ) *error = IDSource_EMPTY;
5859 SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
5860 if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5862 if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
5864 arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
5868 if ( error ) *error = IDSource_INVALID;
5874 arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
5875 if ( bool(anIDs->length()) != bool(theElemSet.size()))
5877 if ( error ) *error = IDSource_INVALID;
5884 //================================================================================
5886 * \brief Duplicates given elements, i.e. creates new elements based on the
5887 * same nodes as the given ones.
5888 * \param theElements - container of elements to duplicate.
5889 * \param theGroupName - a name of group to contain the generated elements.
5890 * If a group with such a name already exists, the new elements
5891 * are added to the existing group, else a new group is created.
5892 * If \a theGroupName is empty, new elements are not added
5894 * \return a group where the new elements are added. NULL if theGroupName == "".
5897 //================================================================================
5899 SMESH::SMESH_Group_ptr
5900 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5901 const char* theGroupName)
5903 SMESH::SMESH_Group_var newGroup;
5910 TIDSortedElemSet elems;
5911 if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5913 getEditor().DoubleElements( elems );
5915 if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().empty() )
5918 SMESH::ElementType type =
5919 SMESH::ElementType( getEditor().GetLastCreatedElems()[0]->GetType() );
5920 // find existing group
5921 SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5922 for ( size_t i = 0; i < groups->length(); ++i )
5923 if ( groups[i]->GetType() == type )
5925 CORBA::String_var name = groups[i]->GetName();
5926 if ( strcmp( name, theGroupName ) == 0 ) {
5927 newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5931 // create a new group
5932 if ( newGroup->_is_nil() )
5933 newGroup = myMesh_i->CreateGroup( type, theGroupName );
5935 if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5937 SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5938 const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5939 for ( size_t i = 0; i < aSeq.size(); i++ )
5940 groupDS->SMDSGroup().Add( aSeq[i] );
5945 if ( !newGroup->_is_nil() )
5946 pyDump << newGroup << " = ";
5947 pyDump << this << ".DoubleElements( "
5948 << theElements << ", " << "'" << theGroupName <<"')";
5950 SMESH_CATCH( SMESH::throwCorbaException );
5952 return newGroup._retn();
5955 //================================================================================
5957 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5958 \param theNodes - identifiers of nodes to be doubled
5959 \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5960 nodes. If list of element identifiers is empty then nodes are doubled but
5961 they not assigned to elements
5962 \return TRUE if operation has been completed successfully, FALSE otherwise
5963 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5965 //================================================================================
5967 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::smIdType_array& theNodes,
5968 const SMESH::smIdType_array& theModifiedElems )
5973 list< int > aListOfNodes;
5975 for ( i = 0, n = theNodes.length(); i < n; i++ )
5976 aListOfNodes.push_back( theNodes[ i ] );
5978 list< int > aListOfElems;
5979 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5980 aListOfElems.push_back( theModifiedElems[ i ] );
5982 bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5984 declareMeshModified( /*isReComputeSafe=*/ !aResult );
5986 // Update Python script
5987 TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5991 SMESH_CATCH( SMESH::throwCorbaException );
5995 //================================================================================
5997 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5998 This method provided for convenience works as DoubleNodes() described above.
5999 \param theNodeId - identifier of node to be doubled.
6000 \param theModifiedElems - identifiers of elements to be updated.
6001 \return TRUE if operation has been completed successfully, FALSE otherwise
6002 \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6004 //================================================================================
6006 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( SMESH::smIdType theNodeId,
6007 const SMESH::smIdType_array& theModifiedElems )
6010 SMESH::smIdType_array_var aNodes = new SMESH::smIdType_array;
6011 aNodes->length( 1 );
6012 aNodes[ 0 ] = theNodeId;
6014 TPythonDump pyDump; // suppress dump by the next line
6016 CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6018 pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6022 SMESH_CATCH( SMESH::throwCorbaException );
6026 //================================================================================
6028 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6029 This method provided for convenience works as DoubleNodes() described above.
6030 \param theNodes - group of nodes to be doubled.
6031 \param theModifiedElems - group of elements to be updated.
6032 \return TRUE if operation has been completed successfully, FALSE otherwise
6033 \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6035 //================================================================================
6037 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6038 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6041 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6044 SMESH::smIdType_array_var aNodes = theNodes->GetListOfID();
6045 SMESH::smIdType_array_var aModifiedElems;
6046 if ( !CORBA::is_nil( theModifiedElems ) )
6047 aModifiedElems = theModifiedElems->GetListOfID();
6049 aModifiedElems = new SMESH::smIdType_array;
6051 TPythonDump pyDump; // suppress dump by the next line
6053 bool done = DoubleNodes( aNodes, aModifiedElems );
6055 pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6059 SMESH_CATCH( SMESH::throwCorbaException );
6063 //================================================================================
6065 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6066 * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6067 * \param theNodes - group of nodes to be doubled.
6068 * \param theModifiedElems - group of elements to be updated.
6069 * \return a new group with newly created nodes
6070 * \sa DoubleNodeGroup()
6072 //================================================================================
6074 SMESH::SMESH_Group_ptr
6075 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6076 SMESH::SMESH_GroupBase_ptr theModifiedElems )
6079 SMESH::SMESH_Group_var aNewGroup;
6081 if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6082 return aNewGroup._retn();
6085 SMESH::smIdType_array_var aNodes = theNodes->GetListOfID();
6086 SMESH::smIdType_array_var aModifiedElems;
6087 if ( !CORBA::is_nil( theModifiedElems ) )
6088 aModifiedElems = theModifiedElems->GetListOfID();
6090 aModifiedElems = new SMESH::smIdType_array;
6091 aModifiedElems->length( 0 );
6094 TPythonDump pyDump; // suppress dump by the next line
6096 bool aResult = DoubleNodes( aNodes, aModifiedElems );
6099 // Create group with newly created nodes
6100 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6101 if (anIds->length() > 0) {
6102 std::string anUnindexedName (theNodes->GetName());
6103 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6104 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6105 aNewGroup->Add(anIds);
6106 pyDump << aNewGroup << " = ";
6110 pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6111 << theModifiedElems << " )";
6113 return aNewGroup._retn();
6115 SMESH_CATCH( SMESH::throwCorbaException );
6119 //================================================================================
6121 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6122 This method provided for convenience works as DoubleNodes() described above.
6123 \param theNodes - list of groups of nodes to be doubled
6124 \param theModifiedElems - list of groups of elements to be updated.
6125 \return TRUE if operation has been completed successfully, FALSE otherwise
6126 \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6128 //================================================================================
6130 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6131 const SMESH::ListOfGroups& theModifiedElems )
6136 std::list< int > aNodes;
6137 smIdType i, n, j, m;
6138 for ( i = 0, n = theNodes.length(); i < n; i++ )
6140 SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6141 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6143 SMESH::smIdType_array_var aCurr = aGrp->GetListOfID();
6144 for ( j = 0, m = aCurr->length(); j < m; j++ )
6145 aNodes.push_back( aCurr[ j ] );
6149 std::list< int > anElems;
6150 for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6152 SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6153 if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6155 SMESH::smIdType_array_var aCurr = aGrp->GetListOfID();
6156 for ( j = 0, m = aCurr->length(); j < m; j++ )
6157 anElems.push_back( aCurr[ j ] );
6161 bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6163 declareMeshModified( /*isReComputeSafe=*/false );
6165 TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6169 SMESH_CATCH( SMESH::throwCorbaException );
6173 //================================================================================
6175 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6176 * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6177 * \param theNodes - group of nodes to be doubled.
6178 * \param theModifiedElems - group of elements to be updated.
6179 * \return a new group with newly created nodes
6180 * \sa DoubleNodeGroups()
6182 //================================================================================
6184 SMESH::SMESH_Group_ptr
6185 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6186 const SMESH::ListOfGroups& theModifiedElems )
6188 SMESH::SMESH_Group_var aNewGroup;
6190 TPythonDump pyDump; // suppress dump by the next line
6192 bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6196 // Create group with newly created nodes
6197 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6198 if (anIds->length() > 0) {
6199 std::string anUnindexedName (theNodes[0]->GetName());
6200 std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
6201 aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6202 aNewGroup->Add(anIds);
6203 pyDump << aNewGroup << " = ";
6207 pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6208 << theModifiedElems << " )";
6210 return aNewGroup._retn();
6214 //================================================================================
6216 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6217 \param theElems - the list of elements (edges or faces) to be replicated
6218 The nodes for duplication could be found from these elements
6219 \param theNodesNot - list of nodes to NOT replicate
6220 \param theAffectedElems - the list of elements (cells and edges) to which the
6221 replicated nodes should be associated to.
6222 \return TRUE if operation has been completed successfully, FALSE otherwise
6223 \sa DoubleNodeGroup(), DoubleNodeGroups()
6225 //================================================================================
6227 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::smIdType_array& theElems,
6228 const SMESH::smIdType_array& theNodesNot,
6229 const SMESH::smIdType_array& theAffectedElems )
6234 SMESHDS_Mesh* aMeshDS = getMeshDS();
6235 TIDSortedElemSet anElems, aNodes, anAffected;
6236 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6237 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6238 arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6240 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6242 // Update Python script
6243 TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6244 << theNodesNot << ", " << theAffectedElems << " )";
6246 declareMeshModified( /*isReComputeSafe=*/false );
6249 SMESH_CATCH( SMESH::throwCorbaException );
6253 //================================================================================
6255 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6256 \param theElems - the list of elements (edges or faces) to be replicated
6257 The nodes for duplication could be found from these elements
6258 \param theNodesNot - list of nodes to NOT replicate
6259 \param theShape - shape to detect affected elements (element which geometric center
6260 located on or inside shape).
6261 The replicated nodes should be associated to affected elements.
6262 \return TRUE if operation has been completed successfully, FALSE otherwise
6263 \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6265 //================================================================================
6267 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::smIdType_array& theElems,
6268 const SMESH::smIdType_array& theNodesNot,
6269 GEOM::GEOM_Object_ptr theShape )
6275 SMESHDS_Mesh* aMeshDS = getMeshDS();
6276 TIDSortedElemSet anElems, aNodes;
6277 arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6278 arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6280 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6281 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6283 // Update Python script
6284 TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6285 << theNodesNot << ", " << theShape << " )";
6287 declareMeshModified( /*isReComputeSafe=*/false );
6290 SMESH_CATCH( SMESH::throwCorbaException );
6294 //================================================================================
6296 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6297 \param theElems - group of of elements (edges or faces) to be replicated
6298 \param theNodesNot - group of nodes not to replicated
6299 \param theAffectedElems - group of elements to which the replicated nodes
6300 should be associated to.
6301 \return TRUE if operation has been completed successfully, FALSE otherwise
6302 \sa DoubleNodes(), DoubleNodeGroups()
6304 //================================================================================
6307 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6308 SMESH::SMESH_GroupBase_ptr theNodesNot,
6309 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6312 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6318 SMESHDS_Mesh* aMeshDS = getMeshDS();
6319 TIDSortedElemSet anElems, aNodes, anAffected;
6320 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6321 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6322 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6324 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6326 // Update Python script
6327 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6328 << theNodesNot << ", " << theAffectedElems << " )";
6330 declareMeshModified( /*isReComputeSafe=*/false );
6333 SMESH_CATCH( SMESH::throwCorbaException );
6337 //================================================================================
6339 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6340 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6341 * \param theElems - group of of elements (edges or faces) to be replicated
6342 * \param theNodesNot - group of nodes not to replicated
6343 * \param theAffectedElems - group of elements to which the replicated nodes
6344 * should be associated to.
6345 * \return a new group with newly created elements
6346 * \sa DoubleNodeElemGroup()
6348 //================================================================================
6350 SMESH::SMESH_Group_ptr
6351 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6352 SMESH::SMESH_GroupBase_ptr theNodesNot,
6353 SMESH::SMESH_GroupBase_ptr theAffectedElems)
6356 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6360 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6361 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6363 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6365 << theNodesNot << ", "
6366 << theAffectedElems << " )";
6368 return elemGroup._retn();
6371 //================================================================================
6373 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6374 * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6375 * \param theElems - group of of elements (edges or faces) to be replicated
6376 * \param theNodesNot - group of nodes not to replicated
6377 * \param theAffectedElems - group of elements to which the replicated nodes
6378 * should be associated to.
6379 * \return a new group with newly created elements
6380 * \sa DoubleNodeElemGroup()
6382 //================================================================================
6384 SMESH::ListOfGroups*
6385 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6386 SMESH::SMESH_GroupBase_ptr theNodesNot,
6387 SMESH::SMESH_GroupBase_ptr theAffectedElems,
6388 CORBA::Boolean theElemGroupNeeded,
6389 CORBA::Boolean theNodeGroupNeeded)
6392 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6393 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6394 aTwoGroups->length( 2 );
6396 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6397 return aTwoGroups._retn();
6402 SMESHDS_Mesh* aMeshDS = getMeshDS();
6403 TIDSortedElemSet anElems, aNodes, anAffected;
6404 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6405 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6406 idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6409 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6411 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6417 // Create group with newly created elements
6418 CORBA::String_var elemGroupName = theElems->GetName();
6419 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6420 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6422 SMESH::smIdType_array_var anIds = GetLastCreatedElems();
6423 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6424 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6425 aNewElemGroup->Add(anIds);
6427 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6429 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6430 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6431 aNewNodeGroup->Add(anIds);
6435 // Update Python script
6438 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6439 else pyDump << aNewElemGroup << ", ";
6440 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6441 else pyDump << aNewNodeGroup << " ] = ";
6443 pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6444 << theNodesNot << ", "
6445 << theAffectedElems << ", "
6446 << theElemGroupNeeded << ", "
6447 << theNodeGroupNeeded <<" )";
6449 aTwoGroups[0] = aNewElemGroup._retn();
6450 aTwoGroups[1] = aNewNodeGroup._retn();
6451 return aTwoGroups._retn();
6453 SMESH_CATCH( SMESH::throwCorbaException );
6457 //================================================================================
6459 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6460 \param theElems - group of of elements (edges or faces) to be replicated
6461 \param theNodesNot - group of nodes not to replicated
6462 \param theShape - shape to detect affected elements (element which geometric center
6463 located on or inside shape).
6464 The replicated nodes should be associated to affected elements.
6465 \return TRUE if operation has been completed successfully, FALSE otherwise
6466 \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6468 //================================================================================
6471 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6472 SMESH::SMESH_GroupBase_ptr theNodesNot,
6473 GEOM::GEOM_Object_ptr theShape )
6476 if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6482 SMESHDS_Mesh* aMeshDS = getMeshDS();
6483 TIDSortedElemSet anElems, aNodes, anAffected;
6484 idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6485 idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6487 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6488 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6491 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6493 // Update Python script
6494 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6495 << theNodesNot << ", " << theShape << " )";
6498 SMESH_CATCH( SMESH::throwCorbaException );
6502 //================================================================================
6504 * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6505 * \param [in] theGrpList - groups
6506 * \param [in] theMeshDS - mesh
6507 * \param [out] theElemSet - set of elements
6508 * \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6510 //================================================================================
6512 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6513 SMESHDS_Mesh* theMeshDS,
6514 TIDSortedElemSet& theElemSet,
6515 const bool theIsNodeGrp)
6517 for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6519 SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6520 if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6521 : aGrp->GetType() != SMESH::NODE ) )
6523 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6524 arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6529 //================================================================================
6531 \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6532 This method provided for convenience works as DoubleNodes() described above.
6533 \param theElems - list of groups of elements (edges or faces) to be replicated
6534 \param theNodesNot - list of groups of nodes not to replicated
6535 \param theAffectedElems - group of elements to which the replicated nodes
6536 should be associated to.
6537 \return TRUE if operation has been completed successfully, FALSE otherwise
6538 \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6540 //================================================================================
6543 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6544 const SMESH::ListOfGroups& theNodesNot,
6545 const SMESH::ListOfGroups& theAffectedElems)
6551 SMESHDS_Mesh* aMeshDS = getMeshDS();
6552 TIDSortedElemSet anElems, aNodes, anAffected;
6553 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6554 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6555 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6557 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6559 // Update Python script
6560 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6561 << &theNodesNot << ", " << &theAffectedElems << " )";
6563 declareMeshModified( /*isReComputeSafe=*/false );
6566 SMESH_CATCH( SMESH::throwCorbaException );
6570 //================================================================================
6572 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6573 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6574 \param theElems - list of groups of elements (edges or faces) to be replicated
6575 \param theNodesNot - list of groups of nodes not to replicated
6576 \param theAffectedElems - group of elements to which the replicated nodes
6577 should be associated to.
6578 * \return a new group with newly created elements
6579 * \sa DoubleNodeElemGroups()
6581 //================================================================================
6583 SMESH::SMESH_Group_ptr
6584 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6585 const SMESH::ListOfGroups& theNodesNot,
6586 const SMESH::ListOfGroups& theAffectedElems)
6589 SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6593 SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6594 SMESH::SMESH_Group_var elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6596 pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6598 << theNodesNot << ", "
6599 << theAffectedElems << " )";
6601 return elemGroup._retn();
6604 //================================================================================
6606 * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6607 * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6608 \param theElems - list of groups of elements (edges or faces) to be replicated
6609 \param theNodesNot - list of groups of nodes not to replicated
6610 \param theAffectedElems - group of elements to which the replicated nodes
6611 should be associated to.
6612 * \return a new group with newly created elements
6613 * \sa DoubleNodeElemGroups()
6615 //================================================================================
6617 SMESH::ListOfGroups*
6618 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6619 const SMESH::ListOfGroups& theNodesNot,
6620 const SMESH::ListOfGroups& theAffectedElems,
6621 CORBA::Boolean theElemGroupNeeded,
6622 CORBA::Boolean theNodeGroupNeeded)
6625 SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6626 SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6627 aTwoGroups->length( 2 );
6632 SMESHDS_Mesh* aMeshDS = getMeshDS();
6633 TIDSortedElemSet anElems, aNodes, anAffected;
6634 listOfGroupToSet(theElems, aMeshDS, anElems, false );
6635 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6636 listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6638 bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6640 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6645 // Create group with newly created elements
6646 CORBA::String_var elemGroupName = theElems[0]->GetName();
6647 std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
6648 if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
6650 SMESH::smIdType_array_var anIds = GetLastCreatedElems();
6651 SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6652 aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6653 aNewElemGroup->Add(anIds);
6655 if ( !getEditor().GetLastCreatedNodes().empty() && theNodeGroupNeeded )
6657 SMESH::smIdType_array_var anIds = GetLastCreatedNodes();
6658 aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6659 aNewNodeGroup->Add(anIds);
6663 // Update Python script
6666 if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6667 else pyDump << aNewElemGroup << ", ";
6668 if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6669 else pyDump << aNewNodeGroup << " ] = ";
6671 pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6672 << &theNodesNot << ", "
6673 << &theAffectedElems << ", "
6674 << theElemGroupNeeded << ", "
6675 << theNodeGroupNeeded << " )";
6677 aTwoGroups[0] = aNewElemGroup._retn();
6678 aTwoGroups[1] = aNewNodeGroup._retn();
6679 return aTwoGroups._retn();
6681 SMESH_CATCH( SMESH::throwCorbaException );
6685 //================================================================================
6687 \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6688 This method provided for convenience works as DoubleNodes() described above.
6689 \param theElems - list of groups of elements (edges or faces) to be replicated
6690 \param theNodesNot - list of groups of nodes not to replicated
6691 \param theShape - shape to detect affected elements (element which geometric center
6692 located on or inside shape).
6693 The replicated nodes should be associated to affected elements.
6694 \return TRUE if operation has been completed successfully, FALSE otherwise
6695 \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6697 //================================================================================
6700 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6701 const SMESH::ListOfGroups& theNodesNot,
6702 GEOM::GEOM_Object_ptr theShape )
6708 SMESHDS_Mesh* aMeshDS = getMeshDS();
6709 TIDSortedElemSet anElems, aNodes;
6710 listOfGroupToSet(theElems, aMeshDS, anElems,false );
6711 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6713 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6714 bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6716 // Update Python script
6717 TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6718 << &theNodesNot << ", " << theShape << " )";
6720 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6723 SMESH_CATCH( SMESH::throwCorbaException );
6727 //================================================================================
6729 \brief Identify the elements that will be affected by node duplication (actual
6730 duplication is not performed.
6731 This method is the first step of DoubleNodeElemGroupsInRegion.
6732 \param theElems - list of groups of elements (edges or faces) to be replicated
6733 \param theNodesNot - list of groups of nodes not to replicate
6734 \param theShape - shape to detect affected elements (element which geometric center
6735 located on or inside shape).
6736 The replicated nodes should be associated to affected elements.
6737 \return groups of affected elements
6738 \sa DoubleNodeElemGroupsInRegion()
6740 //================================================================================
6741 SMESH::ListOfGroups*
6742 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6743 const SMESH::ListOfGroups& theNodesNot,
6744 GEOM::GEOM_Object_ptr theShape )
6747 SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6748 SMESH::SMESH_Group_var aNewEdgeGroup = SMESH::SMESH_Group::_nil();
6749 SMESH::SMESH_Group_var aNewFaceGroup = SMESH::SMESH_Group::_nil();
6750 SMESH::SMESH_Group_var aNewVolumeGroup = SMESH::SMESH_Group::_nil();
6754 ::SMESH_MeshEditor aMeshEditor(myMesh);
6756 SMESHDS_Mesh* aMeshDS = getMeshDS();
6757 TIDSortedElemSet anElems, aNodes;
6758 bool isNodeGrp = theElems.length() ? theElems[0]->GetType() == SMESH::NODE : false;
6759 listOfGroupToSet(theElems, aMeshDS, anElems, isNodeGrp);
6760 listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6762 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6763 TIDSortedElemSet anAffected;
6764 bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6766 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6769 if ( aResult && anAffected.size() > 0 )
6771 SMESH::smIdType_array_var volumeIds = new SMESH::smIdType_array;
6772 SMESH::smIdType_array_var faceIds = new SMESH::smIdType_array;
6773 SMESH::smIdType_array_var edgeIds = new SMESH::smIdType_array;
6774 volumeIds->length( anAffected.size() );
6775 faceIds ->length( anAffected.size() );
6776 edgeIds ->length( anAffected.size() );
6781 TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6782 for (; eIt != anAffected.end(); ++eIt)
6784 const SMDS_MeshElement* anElem = *eIt;
6785 smIdType elemId = anElem->GetID();
6786 switch ( anElem->GetType() ) {
6787 case SMDSAbs_Volume: volumeIds[ivol++] = elemId; break;
6788 case SMDSAbs_Face: faceIds[iface++] = elemId; break;
6789 case SMDSAbs_Edge: edgeIds[iedge++] = elemId; break;
6793 volumeIds->length(ivol);
6794 faceIds->length(iface);
6795 edgeIds->length(iedge);
6800 aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
6801 GenerateGroupName("affectedVolumes").c_str());
6802 aNewVolumeGroup->Add(volumeIds);
6803 aListOfGroups->length( nbGroups+1 );
6804 aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
6808 aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
6809 GenerateGroupName("affectedFaces").c_str());
6810 aNewFaceGroup->Add(faceIds);
6811 aListOfGroups->length( nbGroups+1 );
6812 aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
6816 aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
6817 GenerateGroupName("affectedEdges").c_str());
6818 aNewEdgeGroup->Add(edgeIds);
6819 aListOfGroups->length( nbGroups+1 );
6820 aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
6824 // Update Python script
6826 pyDump << aListOfGroups << " = " << this << ".AffectedElemGroupsInRegion( "
6827 << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6829 return aListOfGroups._retn();
6831 SMESH_CATCH( SMESH::throwCorbaException );
6835 //================================================================================
6837 \brief Generated skin mesh (containing 2D cells) from 3D mesh
6838 The created 2D mesh elements based on nodes of free faces of boundary volumes
6839 \return TRUE if operation has been completed successfully, FALSE otherwise
6841 //================================================================================
6843 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6848 bool aResult = getEditor().Make2DMeshFrom3D();
6850 TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6852 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6855 SMESH_CATCH( SMESH::throwCorbaException );
6859 //================================================================================
6861 * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6862 * The list of groups must contain at least two groups. The groups have to be disjoint:
6863 * no common element into two different groups.
6864 * The nodes of the internal faces at the boundaries of the groups are doubled.
6865 * Optionally, the internal faces are replaced by flat elements.
6866 * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6867 * The flat elements are stored in groups of volumes.
6868 * These groups are named according to the position of the group in the list:
6869 * 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.
6870 * 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.
6871 * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6872 * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6873 * \param theDomains - list of groups of volumes
6874 * \param createJointElems - if TRUE, create the elements
6875 * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
6876 * the boundary between \a theDomains and the rest mesh
6877 * \return TRUE if operation has been completed successfully, FALSE otherwise
6879 //================================================================================
6882 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6883 CORBA::Boolean createJointElems,
6884 CORBA::Boolean onAllBoundaries )
6891 SMESHDS_Mesh* aMeshDS = getMeshDS();
6893 // MESSAGE("theDomains.length = "<<theDomains.length());
6894 if ( theDomains.length() <= 1 && !onAllBoundaries )
6895 THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6897 vector<TIDSortedElemSet> domains;
6898 domains.resize( theDomains.length() );
6900 for ( int i = 0, n = theDomains.length(); i < n; i++ )
6902 SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6903 if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6905 // if ( aGrp->GetType() != SMESH::VOLUME )
6906 // THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6907 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6908 arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6912 isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
6913 // TODO publish the groups of flat elements in study
6915 declareMeshModified( /*isReComputeSafe=*/ !isOK );
6917 // Update Python script
6918 TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6919 << ", " << createJointElems << ", " << onAllBoundaries << " )";
6921 SMESH_CATCH( SMESH::throwCorbaException );
6923 myMesh_i->CreateGroupServants(); // publish created groups if any
6928 //================================================================================
6930 * \brief Double nodes on some external faces and create flat elements.
6931 * Flat elements are mainly used by some types of mechanic calculations.
6933 * Each group of the list must be constituted of faces.
6934 * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6935 * @param theGroupsOfFaces - list of groups of faces
6936 * @return TRUE if operation has been completed successfully, FALSE otherwise
6938 //================================================================================
6941 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6946 SMESHDS_Mesh* aMeshDS = getMeshDS();
6948 vector<TIDSortedElemSet> faceGroups;
6951 for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6953 SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6954 if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6956 TIDSortedElemSet faceGroup;
6958 faceGroups.push_back(faceGroup);
6959 SMESH::smIdType_array_var anIDs = aGrp->GetIDs();
6960 arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6964 bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6965 // TODO publish the groups of flat elements in study
6967 declareMeshModified( /*isReComputeSafe=*/ !aResult );
6969 // Update Python script
6970 TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6973 SMESH_CATCH( SMESH::throwCorbaException );
6977 //================================================================================
6979 * \brief Identify all the elements around a geom shape, get the faces delimiting
6982 * Build groups of volume to remove, groups of faces to replace on the skin of the
6983 * object, groups of faces to remove inside the object, (idem edges).
6984 * Build ordered list of nodes at the border of each group of faces to replace
6985 * (to be used to build a geom subshape).
6987 //================================================================================
6989 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
6990 GEOM::GEOM_Object_ptr theShape,
6991 const char* groupName,
6992 const SMESH::double_array& theNodesCoords,
6993 SMESH::array_of_long_array_out GroupsOfNodes)
6998 std::vector<std::vector<int> > aListOfListOfNodes;
6999 ::SMESH_MeshEditor aMeshEditor( myMesh );
7001 theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7002 if ( !theNodeSearcher )
7003 theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7005 vector<double> nodesCoords;
7006 for ( CORBA::ULong i = 0; i < theNodesCoords.length(); i++)
7008 nodesCoords.push_back( theNodesCoords[i] );
7011 TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7012 aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7013 nodesCoords, aListOfListOfNodes);
7015 GroupsOfNodes = new SMESH::array_of_long_array;
7016 GroupsOfNodes->length( aListOfListOfNodes.size() );
7017 std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7018 for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7020 vector<int>& aListOfNodes = *llIt;
7021 vector<int>::iterator lIt = aListOfNodes.begin();;
7022 SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7023 aGroup.length( aListOfNodes.size() );
7024 for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7025 aGroup[ j ] = (*lIt);
7027 TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7030 << ", '" << groupName << "', "
7031 << theNodesCoords << " )";
7033 SMESH_CATCH( SMESH::throwCorbaException );
7036 // issue 20749 ===================================================================
7038 * \brief Creates missing boundary elements
7039 * \param elements - elements whose boundary is to be checked
7040 * \param dimension - defines type of boundary elements to create
7041 * \param groupName - a name of group to store created boundary elements in,
7042 * "" means not to create the group
7043 * \param meshName - a name of new mesh to store created boundary elements in,
7044 * "" means not to create the new mesh
7045 * \param toCopyElements - if true, the checked elements will be copied into the new mesh
7046 * \param toCopyExistingBondary - if true, not only new but also pre-existing
7047 * boundary elements will be copied into the new mesh
7048 * \param group - returns the create group, if any
7049 * \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7051 // ================================================================================
7053 SMESH::SMESH_Mesh_ptr
7054 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7055 SMESH::Bnd_Dimension dim,
7056 const char* groupName,
7057 const char* meshName,
7058 CORBA::Boolean toCopyElements,
7059 CORBA::Boolean toCopyExistingBondary,
7060 SMESH::SMESH_Group_out group)
7065 if ( dim > SMESH::BND_1DFROM2D )
7066 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7068 SMESHDS_Mesh* aMeshDS = getMeshDS();
7070 SMESH::SMESH_Mesh_var mesh_var;
7071 SMESH::SMESH_Group_var group_var;
7075 TIDSortedElemSet elements;
7076 SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7077 if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7081 strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7082 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7084 SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7086 // group of new boundary elements
7087 SMESH_Group* smesh_group = 0;
7088 if ( strlen(groupName) )
7090 group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7091 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7092 smesh_group = group_i->GetSmeshGroup();
7096 getEditor().MakeBoundaryMesh( elements,
7097 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7101 toCopyExistingBondary);
7104 smesh_mesh->GetMeshDS()->Modified();
7107 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7109 // result of MakeBoundaryMesh() is a tuple (mesh, group)
7110 if ( mesh_var->_is_nil() )
7111 pyDump << myMesh_i->_this() << ", ";
7113 pyDump << mesh_var << ", ";
7114 if ( group_var->_is_nil() )
7115 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7117 pyDump << group_var << " = ";
7118 pyDump << this << ".MakeBoundaryMesh( "
7120 << "SMESH." << dimName[int(dim)] << ", "
7121 << "'" << groupName << "', "
7122 << "'" << meshName<< "', "
7123 << toCopyElements << ", "
7124 << toCopyExistingBondary << ")";
7126 group = group_var._retn();
7127 return mesh_var._retn();
7129 SMESH_CATCH( SMESH::throwCorbaException );
7130 return SMESH::SMESH_Mesh::_nil();
7133 //================================================================================
7135 * \brief Creates missing boundary elements
7136 * \param dimension - defines type of boundary elements to create
7137 * \param groupName - a name of group to store all boundary elements in,
7138 * "" means not to create the group
7139 * \param meshName - a name of a new mesh, which is a copy of the initial
7140 * mesh + created boundary elements; "" means not to create the new mesh
7141 * \param toCopyAll - if true, the whole initial mesh will be copied into
7142 * the new mesh else only boundary elements will be copied into the new mesh
7143 * \param groups - optional groups of elements to make boundary around
7144 * \param mesh - returns the mesh where elements were added to
7145 * \param group - returns the created group, if any
7146 * \retval long - number of added boundary elements
7148 //================================================================================
7150 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7151 const char* groupName,
7152 const char* meshName,
7153 CORBA::Boolean toCopyAll,
7154 const SMESH::ListOfIDSources& groups,
7155 SMESH::SMESH_Mesh_out mesh,
7156 SMESH::SMESH_Group_out group)
7161 if ( dim > SMESH::BND_1DFROM2D )
7162 THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7164 // separate groups belonging to this and other mesh
7165 SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7166 SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7167 groupsOfThisMesh ->length( groups.length() );
7168 groupsOfOtherMesh->length( groups.length() );
7169 int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7170 for ( CORBA::ULong i = 0; i < groups.length(); ++i )
7172 SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7173 if ( !m->_is_nil() && myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7174 groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7176 groupsOfThisMesh[ nbGroups++ ] = groups[i];
7177 if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7178 THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
7180 groupsOfThisMesh->length( nbGroups );
7181 groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7186 if ( nbGroupsOfOtherMesh > 0 )
7188 // process groups belonging to another mesh
7189 SMESH::SMESH_Mesh_var otherMesh = groupsOfOtherMesh[0]->GetMesh();
7190 SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7191 nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7192 groupsOfOtherMesh, mesh, group );
7195 SMESH::SMESH_Mesh_var mesh_var;
7196 SMESH::SMESH_Group_var group_var;
7199 mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7200 const bool toCopyMesh = ( strlen( meshName ) > 0 );
7204 mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7206 /*toCopyGroups=*/false,
7207 /*toKeepIDs=*/true);
7209 mesh_var = makeMesh(meshName);
7211 SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7212 SMESH_Mesh* tgtMesh = &mesh_i->GetImpl();
7215 SMESH_Mesh* srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7216 SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7218 // group of boundary elements
7219 SMESH_Group* smesh_group = 0;
7220 SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7221 if ( strlen( groupName ))
7223 SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7224 group_var = mesh_i->CreateGroup( groupType, groupName );
7225 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7226 smesh_group = group_i->GetSmeshGroup();
7229 TIDSortedElemSet elements;
7231 if ( groups.length() > 0 )
7233 for ( int i = 0; i < nbGroups; ++i )
7236 if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7238 SMESH::Bnd_Dimension bdim =
7239 ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7240 nbAdded += getEditor().MakeBoundaryMesh( elements,
7241 ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7244 /*toCopyElements=*/false,
7245 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7246 /*toAddExistingBondary=*/true,
7247 /*aroundElements=*/true);
7253 nbAdded += getEditor().MakeBoundaryMesh( elements,
7254 ::SMESH_MeshEditor::Bnd_Dimension(dim),
7257 /*toCopyElements=*/false,
7258 /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7259 /*toAddExistingBondary=*/true);
7261 tgtMesh->GetMeshDS()->Modified();
7263 const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7265 // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7266 pyDump << "nbAdded, ";
7267 if ( mesh_var->_is_nil() )
7268 pyDump << myMesh_i->_this() << ", ";
7270 pyDump << mesh_var << ", ";
7271 if ( group_var->_is_nil() )
7272 pyDump << "_NoneGroup = "; // assignment to None is forbidden
7274 pyDump << group_var << " = ";
7275 pyDump << this << ".MakeBoundaryElements( "
7276 << "SMESH." << dimName[int(dim)] << ", "
7277 << "'" << groupName << "', "
7278 << "'" << meshName<< "', "
7279 << toCopyAll << ", "
7282 mesh = mesh_var._retn();
7283 group = group_var._retn();
7286 SMESH_CATCH( SMESH::throwCorbaException );
7290 //================================================================================
7292 * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7293 * the initial mesh. Positions of new nodes are found by cutting the mesh by the
7294 * plane passing through pairs of points specified by each PolySegment structure.
7295 * If there are several paths connecting a pair of points, the shortest path is
7296 * selected by the module. Position of the cutting plane is defined by the two
7297 * points and an optional vector lying on the plane specified by a PolySegment.
7298 * By default the vector is defined by Mesh module as following. A middle point
7299 * of the two given points is computed. The middle point is projected to the mesh.
7300 * The vector goes from the middle point to the projection point. In case of planar
7301 * mesh, the vector is normal to the mesh.
7302 * \param [inout] segments - PolySegment's defining positions of cutting planes.
7303 * Return the used vector and position of the middle point.
7304 * \param [in] groupName - optional name of a group where created mesh segments will
7307 //================================================================================
7309 void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
7310 const char* theGroupName)
7312 if ( theSegments.length() == 0 )
7313 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7314 if ( myMesh->NbFaces() == 0 )
7315 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7318 initData(/*deleteSearchers=*/false);
7320 SMESHDS_Group* groupDS = 0;
7321 SMESHDS_Mesh* meshDS = getMeshDS();
7322 if ( myIsPreviewMode ) // copy faces to the tmp mesh
7324 TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
7325 SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
7326 while ( faceIt->more() )
7327 tmpMesh->Copy( faceIt->next() );
7328 meshDS = tmpMesh->GetMeshDS();
7330 else if ( theGroupName[0] ) // find/create a group of segments
7332 // SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
7333 // while ( !groupDS && grpIt->more() )
7335 // SMESH_Group* group = grpIt->next();
7336 // if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
7337 // strcmp( group->GetName(), theGroupName ) == 0 )
7339 // groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
7344 SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
7346 if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
7347 groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
7351 // convert input polySegments
7352 SMESH_MeshAlgos::TListOfPolySegments segments( theSegments.length() );
7353 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7355 SMESH::PolySegment& segIn = theSegments[ i ];
7356 SMESH_MeshAlgos::PolySegment& segOut = segments[ i ];
7357 segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
7358 segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
7359 segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
7360 segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
7361 segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
7364 segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
7367 segOut.myVector.SetCoord( segIn.vector.PS.x,
7369 segIn.vector.PS.z );
7372 // get a static ElementSearcher
7373 SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
7374 theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
7375 if ( !theElementSearcher )
7376 theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
7379 std::vector<const SMDS_MeshElement*> newEdges;
7380 std::vector<const SMDS_MeshNode*> newNodes;
7381 SMESH_MeshAlgos::MakePolyLine( meshDS, segments, newEdges, newNodes,
7382 groupDS ? &groupDS->SMDSGroup() : 0,
7383 theElementSearcher );
7385 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedElems() ).
7387 const_cast< SMESH_SequenceOfElemPtr& >( getEditor().GetLastCreatedNodes() ).
7388 assign( newNodes.begin(), newNodes.end() );
7391 if ( myIsPreviewMode )
7393 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7395 SMESH::PolySegment& segOut = theSegments[ i ];
7396 SMESH_MeshAlgos::PolySegment& segIn = segments[ i ];
7397 segOut.vector.PS.x = segIn.myVector.X();
7398 segOut.vector.PS.y = segIn.myVector.Y();
7399 segOut.vector.PS.z = segIn.myVector.Z();
7404 TPythonDump() << "_segments = []";
7405 for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
7407 SMESH::PolySegment& segIn = theSegments[ i ];
7408 TPythonDump() << "_segments.append( SMESH.PolySegment( "
7409 << segIn.node1ID1 << ", "
7410 << segIn.node1ID2 << ", "
7411 << segIn.node2ID1 << ", "
7412 << segIn.node2ID2 << ", "
7413 << "smeshBuilder.MakeDirStruct( "
7414 << segIn.vector.PS.x << ", "
7415 << segIn.vector.PS.y << ", "
7416 << segIn.vector.PS.z << ")))";
7418 TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
7421 SMESH_CATCH( SMESH::throwCorbaException );
7425 //================================================================================
7427 * \brief Create a slot of given width around given 1D elements lying on a triangle mesh.
7428 * The slot is constructed by cutting faces by cylindrical surfaces made
7429 * around each segment. Segments are expected to be created by MakePolyLine().
7430 * \return Edges located at the slot boundary
7432 //================================================================================
7434 SMESH::ListOfEdges* SMESH_MeshEditor_i::MakeSlot(SMESH::SMESH_GroupBase_ptr theSegments,
7435 CORBA::Double theWidth)
7437 if ( CORBA::is_nil( theSegments ) ||
7438 theSegments->GetType() != SMESH::EDGE )
7439 THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
7440 if ( myMesh->NbFaces() == 0 )
7441 THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
7443 SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
7446 initData(/*deleteSearchers=*/false);
7448 SMESHDS_Mesh* meshDS = getMeshDS();
7450 // get standalone face groups to be updated
7451 std::vector< SMDS_MeshGroup* > faceGroups;
7452 const std::set<SMESHDS_GroupBase*>& allGroups = meshDS->GetGroups();
7453 std::set<SMESHDS_GroupBase*>::const_iterator grIt = allGroups.begin();
7454 for ( ; grIt != allGroups.end(); ++grIt )
7455 if ( const SMESHDS_Group* gr = dynamic_cast< const SMESHDS_Group* >( *grIt ))
7456 if ( gr->GetType() == SMDSAbs_Face )
7457 faceGroups.push_back( & const_cast< SMESHDS_Group* >( gr )->SMDSGroup() );
7459 std::vector< SMESH_MeshAlgos::Edge > edges =
7460 SMESH_MeshAlgos::MakeSlot( SMESH_Mesh_i::GetElements( theSegments, SMESH::EDGE ),
7461 theWidth, meshDS, faceGroups );
7463 resultEdges->length( edges.size() );
7464 for ( size_t i = 0; i < edges.size(); ++i )
7466 resultEdges[ i ].node1 = edges[i]._node1->GetID();
7467 resultEdges[ i ].node2 = edges[i]._node2->GetID();
7468 resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
7472 SMESH_CATCH( SMESH::throwCorbaException );
7474 TSearchersDeleter::Delete(); // face searcher becomes invalid as some faces were removed
7476 return resultEdges._retn();