1 // Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : SMESHGUI_ShapeByMeshDlg.cxx
24 // Author : Edward AGAPOV, Open CASCADE S.A.S.
27 #include "SMESHGUI_ShapeByMeshDlg.h"
30 #include "SMESHGUI_GEOMGenUtils.h"
31 #include "SMESHGUI_IdValidator.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
36 #include <SMDS_Mesh.hxx>
37 #include <SMDS_MeshNode.hxx>
38 #include <SMESH_Actor.h>
40 // SALOME GEOM includes
42 #include <GeometryGUI.h>
43 #include <GEOM_wrap.hxx>
45 // SALOME GUI includes
46 #include <LightApp_DataOwner.h>
47 #include <LightApp_SelectionMgr.h>
48 #include <SALOME_ListIO.hxx>
49 #include <SUIT_Desktop.h>
50 #include <SVTK_Selector.h>
51 #include <SVTK_ViewWindow.h>
52 #include <SVTK_ViewModel.h>
53 #include <SalomeApp_Tools.h>
55 // SALOME KERNEL includes
56 #include <SALOMEDSClient_SObject.hxx>
57 #include <SALOMEDS_Study.hxx>
58 #include <SALOMEDS_wrap.hxx>
61 #include <TColStd_MapOfInteger.hxx>
62 #include <TopoDS_Shape.hxx>
63 #include <TopExp_Explorer.hxx>
67 #include <QVBoxLayout>
68 #include <QHBoxLayout>
69 #include <QGridLayout>
72 #include <QRadioButton>
73 #include <QButtonGroup>
75 #include <QStringList>
80 enum { EDGE = 0, FACE, VOLUME };
83 * \brief Dialog to publish a sub-shape of the mesh main shape
84 * by selecting mesh elements
86 SMESHGUI_ShapeByMeshDlg::SMESHGUI_ShapeByMeshDlg(bool isMultipleAllowed)
87 : SMESHGUI_Dialog( 0, false, true, OK | Close ),
88 myIsMultipleAllowed( isMultipleAllowed )
90 setWindowTitle(tr("CAPTION"));
92 QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
93 aDlgLay->setMargin(MARGIN);
94 aDlgLay->setSpacing(SPACING);
96 QFrame* aMainFrame = createMainFrame (mainFrame());
98 aDlgLay->addWidget(aMainFrame);
100 aDlgLay->setStretchFactor(aMainFrame, 1);
103 //=======================================================================
104 // function : createMainFrame()
105 // purpose : Create frame containing dialog's input fields
106 //=======================================================================
107 QFrame* SMESHGUI_ShapeByMeshDlg::createMainFrame (QWidget* theParent)
109 QFrame* aMainGrp = new QFrame(theParent);
110 QGridLayout* aLayout = new QGridLayout(aMainGrp);
111 aLayout->setMargin(0);
112 aLayout->setSpacing(SPACING);
115 myElemTypeBox = new QGroupBox(tr("SMESH_ELEMENT_TYPE"), aMainGrp);
116 myElemTypeGroup = new QButtonGroup(aMainGrp);
117 QHBoxLayout* myElemTypeBoxLayout = new QHBoxLayout(myElemTypeBox);
118 myElemTypeBoxLayout->setMargin(MARGIN);
119 myElemTypeBoxLayout->setSpacing(SPACING);
121 QRadioButton* aEdgeRb = new QRadioButton( tr("SMESH_EDGE"), myElemTypeBox);
122 QRadioButton* aFaceRb = new QRadioButton( tr("SMESH_FACE"), myElemTypeBox);
123 QRadioButton* aVolumeRb = new QRadioButton( tr("SMESH_VOLUME"), myElemTypeBox);
125 myElemTypeBoxLayout->addWidget(aEdgeRb);
126 myElemTypeBoxLayout->addWidget(aFaceRb);
127 myElemTypeBoxLayout->addWidget(aVolumeRb);
128 myElemTypeGroup->addButton(aEdgeRb, 0);
129 myElemTypeGroup->addButton(aFaceRb, 1);
130 myElemTypeGroup->addButton(aVolumeRb, 2);
131 aEdgeRb->setChecked(true);
134 QLabel* anIdLabel = new QLabel( tr("ELEMENT_ID"), aMainGrp );
135 myElementId = new QLineEdit( aMainGrp );
136 myElementId->setValidator( new SMESHGUI_IdValidator( theParent,
137 !myIsMultipleAllowed ? 1 : 0 ) ); // 0 for any number of entities
140 QLabel* aNameLabel = new QLabel( tr("GEOMETRY_NAME"), aMainGrp );
141 myGeomName = new QLineEdit( aMainGrp );
143 aLayout->addWidget(myElemTypeBox, 0, 0, 1, 2);
144 aLayout->addWidget(anIdLabel, 1, 0);
145 aLayout->addWidget(myElementId, 1, 1);
146 aLayout->addWidget(aNameLabel, 2, 0);
147 aLayout->addWidget(myGeomName, 2, 1);
152 //=======================================================================
153 // function : ~SMESHGUI_ShapeByMeshDlg()
154 // purpose : Destructor
155 //=======================================================================
156 SMESHGUI_ShapeByMeshDlg::~SMESHGUI_ShapeByMeshDlg()
160 void SMESHGUI_ShapeByMeshDlg:: setMultipleAllowed( bool isAllowed )
162 myIsMultipleAllowed = isAllowed;
165 //================================================================================
169 //================================================================================
170 SMESHGUI_ShapeByMeshOp::SMESHGUI_ShapeByMeshOp(bool isMultipleAllowed):
171 myIsMultipleAllowed(isMultipleAllowed)
173 if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
174 GeometryGUI::InitGeomGen();
176 myDlg = new SMESHGUI_ShapeByMeshDlg(myIsMultipleAllowed);
178 connect(myDlg->myElemTypeGroup, SIGNAL(buttonClicked(int)), SLOT(onTypeChanged(int)));
179 connect(myDlg->myElementId, SIGNAL(textChanged(const QString&)), SLOT(onElemIdChanged(const QString&)));
183 //=======================================================================
184 // function : startOperation()
185 // purpose : Init dialog fields, connect signals and slots, show dialog
186 //=======================================================================
187 void SMESHGUI_ShapeByMeshOp::startOperation()
189 //SetMesh( SMESH::SMESH_Mesh::_nil() );
190 myIsManualIdEnter = false;
192 SMESHGUI_SelectionOp::startOperation();
194 //activateSelection(); // set filters
195 onSelectionDone(); // desable/enable [ OK ]
200 //================================================================================
204 //================================================================================
205 SMESHGUI_ShapeByMeshOp::~SMESHGUI_ShapeByMeshOp()
211 //================================================================================
213 * \brief Gets dialog of this operation
214 * \retval LightApp_Dialog* - pointer to dialog of this operation
216 //================================================================================
217 LightApp_Dialog* SMESHGUI_ShapeByMeshOp::dlg() const
222 SMESH::SMESH_Mesh_ptr SMESHGUI_ShapeByMeshOp::GetMesh()
227 //=======================================================================
228 // function : GetShape()
229 // purpose : Return published sub-shape, it must be UnRegister()ed!
230 //=======================================================================
231 GEOM::GEOM_Object_ptr SMESHGUI_ShapeByMeshOp::GetShape()
233 return myGeomObj.in();
236 //=======================================================================
237 // function : SetMesh()
238 // purpose : Set mesh to dialog
239 //=======================================================================
241 void SMESHGUI_ShapeByMeshOp::SetMesh (SMESH::SMESH_Mesh_ptr thePtr)
243 myMesh = SMESH::SMESH_Mesh::_duplicate(thePtr);
244 myGeomObj = GEOM::GEOM_Object::_nil();
247 std::vector< bool > hasElement (myDlg->myElemTypeGroup->buttons().count(), false);
248 if (!myMesh->_is_nil() )
250 // _PTR(SObject) aSobj = SMESH::FindSObject(myMesh.in());
251 // SUIT_DataOwnerPtr anIObj (new LightApp_DataOwner(aSobj->GetID().c_str()));
253 std::vector< int > nbShapes( TopAbs_SHAPE, 0 );
254 int shapeDim = 0; // max dim with several shapes
255 //if ( /*mySelectionMgr*/ selectionMgr()->isOk(anIObj) ) // check that the mesh has a valid shape
257 _PTR(SObject) aSO = SMESH::FindSObject(myMesh.in());
258 GEOM::GEOM_Object_var mainShape = SMESH::GetGeom(aSO);
259 if ( !mainShape->_is_nil() )
262 if ( GEOMBase::GetShape(mainShape, aShape))
264 TopAbs_ShapeEnum types[4] = { TopAbs_EDGE, TopAbs_FACE, TopAbs_SHELL, TopAbs_SOLID };
265 for ( int dim = 4; dim > 0; --dim ) {
266 TopAbs_ShapeEnum type = types[ dim - 1 ];
267 TopAbs_ShapeEnum avoid = ( type == TopAbs_SHELL ) ? TopAbs_SOLID : TopAbs_SHAPE;
268 TopExp_Explorer exp( aShape, type, avoid );
269 for ( ; nbShapes[ type ] < 2 && exp.More(); exp.Next() )
271 if ( nbShapes[ type ] > 1 ) {
281 if ( nbShapes[ TopAbs_SHELL ] + nbShapes[ TopAbs_SOLID ] > 1 )
283 hasElement[ EDGE ] = shapeDim > 0 && myMesh->NbEdges();
284 hasElement[ FACE ] = shapeDim > 1 && myMesh->NbFaces();
285 hasElement[ VOLUME ] = shapeDim > 2 && myMesh->NbVolumes();
287 myHasSolids = nbShapes[ TopAbs_SOLID ];
290 // disable inexistent elem types
291 for ( int i = 0; i < myDlg->myElemTypeGroup->buttons().count(); ++i ) {
292 if ( QAbstractButton* button = myDlg->myElemTypeGroup->button( i ) )
293 button->setEnabled( hasElement[ i ] );
295 myDlg->myElementId->setEnabled( hasElement[ EDGE ] );
296 myDlg->myGeomName-> setEnabled( hasElement[ EDGE ] );
301 //=======================================================================
302 // function : commitOperation()
303 // purpose : called when "Ok" button pressed.
304 //=======================================================================
306 void SMESHGUI_ShapeByMeshOp::commitOperation()
308 SMESHGUI_SelectionOp::commitOperation();
310 QStringList aListId = myDlg->myElementId->text().split( " ", QString::SkipEmptyParts);
311 if (aListId.count() == 1)
313 int elemID = (aListId.first()).toInt();
314 // GEOM_Object is published -> no need to UnRegister()
315 myGeomObj = GEOM::GEOM_Object::_duplicate
316 (SMESHGUI::GetSMESHGen()->GetGeometryByMeshElement
317 ( myMesh.in(), elemID, myDlg->myGeomName->text().toUtf8().constData()) );
321 GEOM::GEOM_Object_var aMeshShape = myMesh->GetShapeToMesh();
323 GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen( aMeshShape );
324 if ( geomGen->_is_nil() )
327 GEOM::GEOM_IShapesOperations_wrap aShapesOp = geomGen->GetIShapesOperations();
328 if ( aShapesOp->_is_nil() )
331 TopAbs_ShapeEnum aGroupType = TopAbs_SHAPE;
333 std::map<int, GEOM::GEOM_Object_wrap> aGeomObjectsMap;
334 GEOM::GEOM_Object_wrap aGeomObject;
336 for ( int i = 0; i < aListId.count(); i++ )
338 aGeomObject = // received object need UnRegister()!
339 SMESHGUI::GetSMESHGen()->FindGeometryByMeshElement(myMesh.in(), aListId[i].toInt());
341 if (aGeomObject->_is_nil()) continue;
343 int anId = aShapesOp->GetSubShapeIndex(aMeshShape, aGeomObject);
344 if (aShapesOp->IsDone() && !aGeomObjectsMap.count(anId) )
346 aGeomObjectsMap[anId] = aGeomObject;
348 TopAbs_ShapeEnum aSubShapeType = (TopAbs_ShapeEnum)aGeomObject->GetShapeType();
350 aGroupType = aSubShapeType;
351 else if (aSubShapeType != aGroupType)
352 aGroupType = TopAbs_SHAPE;
356 int aNumberOfGO = aGeomObjectsMap.size();
357 if (aNumberOfGO == 1)
359 aGeomObject = (*aGeomObjectsMap.begin()).second;
361 else if (aNumberOfGO > 1)
363 GEOM::GEOM_IGroupOperations_wrap aGroupOp = geomGen->GetIGroupOperations();
364 if ( aGroupOp->_is_nil() )
367 GEOM::ListOfGO_var aGeomObjects = new GEOM::ListOfGO();
368 aGeomObjects->length( aNumberOfGO );
371 std::map<int, GEOM::GEOM_Object_wrap>::iterator anIter;
372 for (anIter = aGeomObjectsMap.begin(); anIter!=aGeomObjectsMap.end(); anIter++)
373 aGeomObjects[i++] = GEOM::GEOM_Object::_duplicate( (*anIter).second.in() );
375 //create geometry group
376 aGeomObject = aGroupOp->CreateGroup(aMeshShape, aGroupType);
377 aGroupOp->UnionList(aGeomObject, aGeomObjects);
379 if ( !aGroupOp->IsDone() )
383 // publish the GEOM object in study
384 QString aNewGeomGroupName ( myDlg->myGeomName->text() );
385 SALOMEDS::SObject_wrap aNewGroupSO =
386 geomGen->AddInStudy( aGeomObject,
387 aNewGeomGroupName.toUtf8().data(), aMeshShape);
389 // get a GEOM_Object already published, which doesn't need UnRegister()
390 CORBA::Object_var obj = aNewGroupSO->GetObject();
391 myGeomObj = GEOM::GEOM_Object::_narrow( obj );
394 catch (const SALOME::SALOME_Exception& S_ex) {
395 SalomeApp_Tools::QtCatchCorbaException(S_ex);
402 bool SMESHGUI_ShapeByMeshOp::onApply()
407 //=======================================================================
408 // function : onSelectionDone()
409 // purpose : SLOT called when selection changed. Enable/desable [ OK ]
410 //=======================================================================
411 void SMESHGUI_ShapeByMeshOp::onSelectionDone()
413 myDlg->setButtonEnabled( false, QtxDialog::OK );
418 selectionMgr()->selectedObjects(aList);
419 if ( aList.IsEmpty() || ( !myIsMultipleAllowed && aList.Extent() != 1) )
422 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
423 if (aMesh->_is_nil() || myMesh->_is_nil() || aMesh->GetId() != myMesh->GetId() )
427 int nbElems = SMESH::GetNameOfSelectedElements(selector(),//myViewWindow->GetSelector(),
428 aList.First(), aString);
430 if (!myIsMultipleAllowed && nbElems != 1 )
432 setElementID( aString );
433 myDlg->setButtonEnabled( true, QtxDialog::OK );
439 //=======================================================================
440 // function : activateSelection()
441 // purpose : Activate selection in accordance with current pattern type
442 //=======================================================================
443 void SMESHGUI_ShapeByMeshOp::activateSelection()
445 selectionMgr()->clearFilters();
446 //SMESH::SetPointRepresentation(false);
448 myDlg->myGeomName->setText("");
451 Selection_Mode mode = EdgeSelection;
452 switch ( myDlg->myElemTypeGroup->checkedId() ) {
454 mode = EdgeSelection; geomName = tr("GEOM_EDGE"); break;
456 mode = FaceSelection; geomName = tr("GEOM_FACE"); break;
458 mode = VolumeSelection; geomName = tr(myHasSolids ? "GEOM_SOLID" : "GEOM_SHELL"); break;
461 if ( selectionMode() != mode )
462 setSelectionMode( mode );
464 myDlg->myGeomName->setText( GEOMBase::GetDefaultName( geomName ));
467 //=======================================================================
468 //function : onTypeChanged
469 //purpose : SLOT. Called when element type changed.
470 //=======================================================================
472 void SMESHGUI_ShapeByMeshOp::onTypeChanged (int /*theType*/)
478 //=======================================================================
479 //function : onTypeChanged
480 //purpose : SLOT. Called when element id is entered
481 // Highlight the element whose Ids the user entered manually
482 //=======================================================================
484 void SMESHGUI_ShapeByMeshOp::onElemIdChanged(const QString& theNewText)
486 myDlg->setButtonEnabled( false, QtxDialog::OK );
488 if ( myIsManualIdEnter && !myMesh->_is_nil() )
490 if ( SMESH_Actor* actor = SMESH::FindActorByObject(myMesh) )
492 if ( SMDS_Mesh* aMesh = actor->GetObject()->GetMesh() )
494 SMDSAbs_ElementType type = SMDSAbs_Edge;
495 switch ( myDlg->myElemTypeGroup->checkedId() ) {
496 case EDGE : type = SMDSAbs_Edge; break;
497 case FACE : type = SMDSAbs_Face; break;
498 case VOLUME: type = SMDSAbs_Volume; break;
501 SVTK_TVtkIDsMap newIndices;
502 QStringList aListId = theNewText.split( " ", QString::SkipEmptyParts);
503 for ( int i = 0; i < aListId.count(); i++ ) {
504 if ( const SMDS_MeshElement * e = aMesh->FindElement( aListId[ i ].toInt() ))
505 if ( e->GetType() == type )
506 newIndices.Add( e->GetID() );
509 if ( !newIndices.IsEmpty() )
511 if (!myIsMultipleAllowed && newIndices.Extent() != 1)
513 if ( SVTK_Selector* s = selector() ) {
514 s->AddOrRemoveIndex( actor->getIO(), newIndices, false );
515 viewWindow()->highlight( actor->getIO(), true, true );
516 myDlg->setButtonEnabled( true, QtxDialog::OK );
524 //=======================================================================
525 //function : setElementID
526 //purpose : programmatically set element id
527 //=======================================================================
529 void SMESHGUI_ShapeByMeshOp::setElementID(const QString& theText)
531 myIsManualIdEnter = false;
532 myDlg->myElementId->setText(theText);
533 myIsManualIdEnter = true;