1 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : SMESHGUI_ShapeByMeshDlg.cxx
21 // Author : Edward AGAPOV, Open CASCADE S.A.S.
25 #include "SMESHGUI_ShapeByMeshDlg.h"
28 #include "SMESHGUI_GEOMGenUtils.h"
29 #include "SMESHGUI_IdValidator.h"
30 #include "SMESHGUI_MeshUtils.h"
31 #include "SMESHGUI_Utils.h"
32 #include "SMESHGUI_VTKUtils.h"
34 #include <SMDS_Mesh.hxx>
35 #include <SMDS_MeshNode.hxx>
36 #include <SMESH_Actor.h>
38 // SALOME GEOM includes
40 #include <GeometryGUI.h>
42 // SALOME GUI includes
43 #include <LightApp_DataOwner.h>
44 #include <LightApp_SelectionMgr.h>
45 #include <SALOME_ListIO.hxx>
46 #include <SUIT_Desktop.h>
47 #include <SVTK_Selector.h>
48 #include <SVTK_ViewWindow.h>
49 #include <SVTK_ViewModel.h>
50 #include <SalomeApp_Tools.h>
52 // SALOME KERNEL includes
53 #include <SALOMEDSClient_SObject.hxx>
56 #include <TColStd_MapOfInteger.hxx>
57 #include <TopoDS_Shape.hxx>
58 #include <TopExp_Explorer.hxx>
62 #include <QVBoxLayout>
63 #include <QHBoxLayout>
64 #include <QGridLayout>
67 #include <QRadioButton>
68 #include <QButtonGroup>
70 #include <QStringList>
75 enum { EDGE = 0, FACE, VOLUME };
78 * \brief Dialog to publish a sub-shape of the mesh main shape
79 * by selecting mesh elements
81 SMESHGUI_ShapeByMeshDlg::SMESHGUI_ShapeByMeshDlg()
82 : SMESHGUI_Dialog( 0, false, true, OK | Close )
84 setWindowTitle(tr("CAPTION"));
86 QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
87 aDlgLay->setMargin(MARGIN);
88 aDlgLay->setSpacing(SPACING);
90 QFrame* aMainFrame = createMainFrame (mainFrame());
92 aDlgLay->addWidget(aMainFrame);
94 aDlgLay->setStretchFactor(aMainFrame, 1);
97 //=======================================================================
98 // function : createMainFrame()
99 // purpose : Create frame containing dialog's input fields
100 //=======================================================================
101 QFrame* SMESHGUI_ShapeByMeshDlg::createMainFrame (QWidget* theParent)
103 QFrame* aMainGrp = new QFrame(theParent);
104 QGridLayout* aLayout = new QGridLayout(aMainGrp);
105 aLayout->setMargin(0);
106 aLayout->setSpacing(SPACING);
109 myElemTypeBox = new QGroupBox(tr("SMESH_ELEMENT_TYPE"), aMainGrp);
110 myElemTypeGroup = new QButtonGroup(aMainGrp);
111 QHBoxLayout* myElemTypeBoxLayout = new QHBoxLayout(myElemTypeBox);
112 myElemTypeBoxLayout->setMargin(MARGIN);
113 myElemTypeBoxLayout->setSpacing(SPACING);
115 QRadioButton* aEdgeRb = new QRadioButton( tr("SMESH_EDGE"), myElemTypeBox);
116 QRadioButton* aFaceRb = new QRadioButton( tr("SMESH_FACE"), myElemTypeBox);
117 QRadioButton* aVolumeRb = new QRadioButton( tr("SMESH_VOLUME"), myElemTypeBox);
119 myElemTypeBoxLayout->addWidget(aEdgeRb);
120 myElemTypeBoxLayout->addWidget(aFaceRb);
121 myElemTypeBoxLayout->addWidget(aVolumeRb);
122 myElemTypeGroup->addButton(aEdgeRb, 0);
123 myElemTypeGroup->addButton(aFaceRb, 1);
124 myElemTypeGroup->addButton(aVolumeRb, 2);
125 aEdgeRb->setChecked(true);
128 QLabel* anIdLabel = new QLabel( tr("ELEMENT_ID"), aMainGrp );
129 myElementId = new QLineEdit( aMainGrp );
130 myElementId->setValidator( new SMESHGUI_IdValidator( theParent,
131 !myIsMultipleAllowed ? 1 : 0 ) ); // 0 for any number of entities
134 QLabel* aNameLabel = new QLabel( tr("GEOMETRY_NAME"), aMainGrp );
135 myGeomName = new QLineEdit( aMainGrp );
137 aLayout->addWidget(myElemTypeBox, 0, 0, 1, 2);
138 aLayout->addWidget(anIdLabel, 1, 0);
139 aLayout->addWidget(myElementId, 1, 1);
140 aLayout->addWidget(aNameLabel, 2, 0);
141 aLayout->addWidget(myGeomName, 2, 1);
146 //=======================================================================
147 // function : ~SMESHGUI_ShapeByMeshDlg()
148 // purpose : Destructor
149 //=======================================================================
150 SMESHGUI_ShapeByMeshDlg::~SMESHGUI_ShapeByMeshDlg()
154 void SMESHGUI_ShapeByMeshDlg:: setMultipleAllowed( bool isAllowed )
156 myIsMultipleAllowed = isAllowed;
159 //================================================================================
163 //================================================================================
164 SMESHGUI_ShapeByMeshOp::SMESHGUI_ShapeByMeshOp(bool isMultipleAllowed):
165 myIsMultipleAllowed(isMultipleAllowed)
167 if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
168 GeometryGUI::InitGeomGen();
170 myDlg = new SMESHGUI_ShapeByMeshDlg;
171 myDlg->setMultipleAllowed(myIsMultipleAllowed);
173 connect(myDlg->myElemTypeGroup, SIGNAL(buttonClicked(int)), SLOT(onTypeChanged(int)));
174 connect(myDlg->myElementId, SIGNAL(textChanged(const QString&)), SLOT(onElemIdChanged(const QString&)));
178 //=======================================================================
179 // function : startOperation()
180 // purpose : Init dialog fields, connect signals and slots, show dialog
181 //=======================================================================
182 void SMESHGUI_ShapeByMeshOp::startOperation()
184 //SetMesh( SMESH::SMESH_Mesh::_nil() );
185 myIsManualIdEnter = false;
187 SMESHGUI_SelectionOp::startOperation();
189 //activateSelection(); // set filters
190 onSelectionDone(); // desable/enable [ OK ]
195 //================================================================================
199 //================================================================================
200 SMESHGUI_ShapeByMeshOp::~SMESHGUI_ShapeByMeshOp()
206 //================================================================================
208 * \brief Gets dialog of this operation
209 * \retval LightApp_Dialog* - pointer to dialog of this operation
211 //================================================================================
212 LightApp_Dialog* SMESHGUI_ShapeByMeshOp::dlg() const
217 SMESH::SMESH_Mesh_ptr SMESHGUI_ShapeByMeshOp::GetMesh()
222 //=======================================================================
223 // function : GetShape()
224 // purpose : Get published sub-shape
225 //=======================================================================
226 GEOM::GEOM_Object_ptr SMESHGUI_ShapeByMeshOp::GetShape()
228 return myGeomObj.in();
231 //=======================================================================
232 // function : SetMesh()
233 // purpose : Set mesh to dialog
234 //=======================================================================
236 void SMESHGUI_ShapeByMeshOp::SetMesh (SMESH::SMESH_Mesh_ptr thePtr)
238 myMesh = SMESH::SMESH_Mesh::_duplicate(thePtr);
239 myGeomObj = GEOM::GEOM_Object::_nil();
242 std::vector< bool > hasElement (myDlg->myElemTypeGroup->buttons().count(), false);
243 if (!myMesh->_is_nil() )
245 // _PTR(SObject) aSobj = SMESH::FindSObject(myMesh.in());
246 // SUIT_DataOwnerPtr anIObj (new LightApp_DataOwner(aSobj->GetID().c_str()));
248 std::vector< int > nbShapes( TopAbs_SHAPE, 0 );
249 int shapeDim = 0; // max dim with several shapes
250 //if ( /*mySelectionMgr*/ selectionMgr()->isOk(anIObj) ) // check that the mesh has a valid shape
252 _PTR(SObject) aSO = SMESH::FindSObject(myMesh.in());
253 GEOM::GEOM_Object_var mainShape = SMESH::GetGeom(aSO);
254 if ( !mainShape->_is_nil() )
257 if ( GEOMBase::GetShape(mainShape, aShape))
259 TopAbs_ShapeEnum types[4] = { TopAbs_EDGE, TopAbs_FACE, TopAbs_SHELL, TopAbs_SOLID };
260 for ( int dim = 4; dim > 0; --dim ) {
261 TopAbs_ShapeEnum type = types[ dim - 1 ];
262 TopAbs_ShapeEnum avoid = ( type == TopAbs_SHELL ) ? TopAbs_SOLID : TopAbs_SHAPE;
263 TopExp_Explorer exp( aShape, type, avoid );
264 for ( ; nbShapes[ type ] < 2 && exp.More(); exp.Next() )
266 if ( nbShapes[ type ] > 1 ) {
276 if ( nbShapes[ TopAbs_SHELL ] + nbShapes[ TopAbs_SOLID ] > 1 )
278 hasElement[ EDGE ] = shapeDim > 0 && myMesh->NbEdges();
279 hasElement[ FACE ] = shapeDim > 1 && myMesh->NbFaces();
280 hasElement[ VOLUME ] = shapeDim > 2 && myMesh->NbVolumes();
282 myHasSolids = nbShapes[ TopAbs_SOLID ];
285 // disable inexistant elem types
286 for ( int i = 0; i < myDlg->myElemTypeGroup->buttons().count(); ++i ) {
287 if ( QAbstractButton* button = myDlg->myElemTypeGroup->button( i ) )
288 button->setEnabled( hasElement[ i ] );
290 myDlg->myElementId->setEnabled( hasElement[ EDGE ] );
291 myDlg->myGeomName-> setEnabled( hasElement[ EDGE ] );
296 //=======================================================================
297 // function : commitOperation()
298 // purpose : called when "Ok" button pressed.
299 //=======================================================================
301 void SMESHGUI_ShapeByMeshOp::commitOperation()
303 SMESHGUI_SelectionOp::commitOperation();
305 QStringList aListId = myDlg->myElementId->text().split( " ", QString::SkipEmptyParts);
306 if (aListId.count() == 1)
308 int elemID = (aListId.first()).toInt();
309 myGeomObj = GEOM::GEOM_Object::_duplicate(
310 SMESHGUI::GetSMESHGen()->GetGeometryByMeshElement
311 ( myMesh.in(), elemID, myDlg->myGeomName->text().toLatin1().constData()) );
315 GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
316 _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
318 if (geomGen->_is_nil() || !aStudy)
321 GEOM::GEOM_IShapesOperations_var aShapesOp =
322 geomGen->GetIShapesOperations(aStudy->StudyId());
323 if (aShapesOp->_is_nil() )
326 TopAbs_ShapeEnum aGroupType = TopAbs_SHAPE;
328 std::map<double, GEOM::GEOM_Object_var> aGeomObjectsMap;
329 GEOM::GEOM_Object_var aGeomObject;
331 GEOM::GEOM_Object_var aMeshShape = myMesh->GetShapeToMesh();
333 for ( int i = 0; i < aListId.count(); i++ )
336 SMESHGUI::GetSMESHGen()->FindGeometryByMeshElement(myMesh.in(), aListId[i].toInt());
338 if (aGeomObject->_is_nil()) continue;
340 double anId = aShapesOp->GetSubShapeIndex(aMeshShape, aGeomObject);
341 if (aShapesOp->IsDone() && aGeomObjectsMap.find(anId) == aGeomObjectsMap.end())
343 aGeomObjectsMap[anId] = aGeomObject;
345 TopAbs_ShapeEnum aSubShapeType = (TopAbs_ShapeEnum)aGeomObject->GetShapeType();
347 aGroupType = aSubShapeType;
348 else if (aSubShapeType != aGroupType)
349 aGroupType = TopAbs_SHAPE;
353 int aNumberOfGO = aGeomObjectsMap.size();
354 if (aNumberOfGO == 1)
355 myGeomObj = (*aGeomObjectsMap.begin()).second;
356 else if (aNumberOfGO > 1)
358 GEOM::GEOM_IGroupOperations_var aGroupOp =
359 geomGen->GetIGroupOperations(aStudy->StudyId());
360 if(aGroupOp->_is_nil())
363 GEOM::ListOfGO_var aGeomObjects = new GEOM::ListOfGO();
364 aGeomObjects->length( aNumberOfGO );
367 std::map<double, GEOM::GEOM_Object_var>::iterator anIter;
368 for (anIter = aGeomObjectsMap.begin(); anIter!=aGeomObjectsMap.end(); anIter++)
369 aGeomObjects[i++] = (*anIter).second;
371 //create geometry group
372 myGeomObj = aGroupOp->CreateGroup(aMeshShape, aGroupType);
373 aGroupOp->UnionList(myGeomObj, aGeomObjects);
375 if (!aGroupOp->IsDone())
379 // publish the GEOM object in study
380 QString aNewGeomGroupName ( myDlg->myGeomName->text() );
382 SALOMEDS::SObject_var aNewGroupSO =
383 geomGen->AddInStudy(SMESHGUI::GetSMESHGen()->GetCurrentStudy(), myGeomObj,
384 aNewGeomGroupName.toLatin1().data(), aMeshShape);
387 catch (const SALOME::SALOME_Exception& S_ex) {
388 SalomeApp_Tools::QtCatchCorbaException(S_ex);
395 bool SMESHGUI_ShapeByMeshOp::onApply()
400 //=======================================================================
401 // function : onSelectionDone()
402 // purpose : SLOT called when selection changed. Enable/desable [ OK ]
403 //=======================================================================
404 void SMESHGUI_ShapeByMeshOp::onSelectionDone()
406 myDlg->setButtonEnabled( false, QtxDialog::OK );
411 selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
412 if (!myIsMultipleAllowed && aList.Extent() != 1)
415 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
416 if (aMesh->_is_nil() || myMesh->_is_nil() || aMesh->GetId() != myMesh->GetId() )
420 int nbElems = SMESH::GetNameOfSelectedElements(selector(),//myViewWindow->GetSelector(),
421 aList.First(), aString);
423 if (!myIsMultipleAllowed && nbElems != 1 )
425 setElementID( aString );
426 myDlg->setButtonEnabled( true, QtxDialog::OK );
432 //=======================================================================
433 // function : activateSelection()
434 // purpose : Activate selection in accordance with current pattern type
435 //=======================================================================
436 void SMESHGUI_ShapeByMeshOp::activateSelection()
438 selectionMgr()->clearFilters();
439 //SMESH::SetPointRepresentation(false);
441 myDlg->myGeomName->setText("");
444 Selection_Mode mode = EdgeSelection;
445 switch ( myDlg->myElemTypeGroup->checkedId() ) {
447 mode = EdgeSelection; geomName = tr("GEOM_EDGE"); break;
449 mode = FaceSelection; geomName = tr("GEOM_FACE"); break;
451 mode = VolumeSelection; geomName = tr(myHasSolids ? "GEOM_SOLID" : "GEOM_SHELL"); break;
454 if ( selectionMode() != mode )
455 setSelectionMode( mode );
457 myDlg->myGeomName->setText( GEOMBase::GetDefaultName( geomName ));
460 //=======================================================================
461 //function : onTypeChanged
462 //purpose : SLOT. Called when element type changed.
463 //=======================================================================
465 void SMESHGUI_ShapeByMeshOp::onTypeChanged (int theType)
471 //=======================================================================
472 //function : onTypeChanged
473 //purpose : SLOT. Called when element id is entered
474 // Highlight the element whose Ids the user entered manually
475 //=======================================================================
477 void SMESHGUI_ShapeByMeshOp::onElemIdChanged(const QString& theNewText)
479 myDlg->setButtonEnabled( false, QtxDialog::OK );
481 if ( myIsManualIdEnter && !myMesh->_is_nil() )
483 if ( SMESH_Actor* actor = SMESH::FindActorByObject(myMesh) )
485 if ( SMDS_Mesh* aMesh = actor->GetObject()->GetMesh() )
487 SMDSAbs_ElementType type = SMDSAbs_Edge;
488 switch ( myDlg->myElemTypeGroup->checkedId() ) {
489 case EDGE : type = SMDSAbs_Edge; break;
490 case FACE : type = SMDSAbs_Face; break;
491 case VOLUME: type = SMDSAbs_Volume; break;
494 TColStd_MapOfInteger newIndices;
495 QStringList aListId = theNewText.split( " ", QString::SkipEmptyParts);
496 for ( int i = 0; i < aListId.count(); i++ ) {
497 if ( const SMDS_MeshElement * e = aMesh->FindElement( aListId[ i ].toInt() ))
498 if ( e->GetType() == type )
499 newIndices.Add( e->GetID() );
502 if ( !newIndices.IsEmpty() )
504 if (!myIsMultipleAllowed && newIndices.Extent() != 1)
506 if ( SVTK_Selector* s = selector() ) {
507 s->AddOrRemoveIndex( actor->getIO(), newIndices, false );
508 viewWindow()->highlight( actor->getIO(), true, true );
509 myDlg->setButtonEnabled( true, QtxDialog::OK );
517 //=======================================================================
518 //function : setElementID
519 //purpose : programmatically set element id
520 //=======================================================================
522 void SMESHGUI_ShapeByMeshOp::setElementID(const QString& theText)
524 myIsManualIdEnter = false;
525 myDlg->myElementId->setText(theText);
526 myIsManualIdEnter = true;