Salome HOME
IMP: SMESH: Japanese translations
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ShapeByMeshDlg.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : SMESHGUI_ShapeByMeshDlg.cxx
24 // Author : Edward AGAPOV, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_ShapeByMeshDlg.h"
28
29 #include "SMESHGUI.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"
35
36 #include <SMDS_Mesh.hxx>
37 #include <SMDS_MeshNode.hxx>
38 #include <SMESH_Actor.h>
39
40 // SALOME GEOM includes
41 #include <GEOMBase.h>
42 #include <GeometryGUI.h>
43 #include <GEOM_wrap.hxx>
44
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>
54
55 // SALOME KERNEL includes
56 #include <SALOMEDSClient_SObject.hxx>
57 #include <SALOMEDS_Study.hxx>
58 #include <SALOMEDS_wrap.hxx>
59
60 // OCCT includes
61 #include <TColStd_MapOfInteger.hxx>
62 #include <TopoDS_Shape.hxx>
63 #include <TopExp_Explorer.hxx>
64
65 // Qt includes
66 #include <QFrame>
67 #include <QVBoxLayout>
68 #include <QHBoxLayout>
69 #include <QGridLayout>
70 #include <QLineEdit>
71 #include <QLabel>
72 #include <QRadioButton>
73 #include <QButtonGroup>
74 #include <QGroupBox>
75 #include <QStringList>
76
77 #define SPACING 6
78 #define MARGIN  11
79
80 enum { EDGE = 0, FACE, VOLUME };
81
82 /*!
83  * \brief Dialog to publish a sub-shape of the mesh main shape
84  *        by selecting mesh elements
85  */
86 SMESHGUI_ShapeByMeshDlg::SMESHGUI_ShapeByMeshDlg(bool isMultipleAllowed)
87   : SMESHGUI_Dialog( 0, false, true, OK | Close ),
88     myIsMultipleAllowed( isMultipleAllowed )
89 {
90   setWindowTitle(tr("CAPTION"));
91
92   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
93   aDlgLay->setMargin(MARGIN);
94   aDlgLay->setSpacing(SPACING);
95
96   QFrame* aMainFrame = createMainFrame  (mainFrame());
97
98   aDlgLay->addWidget(aMainFrame);
99
100   aDlgLay->setStretchFactor(aMainFrame, 1);
101 }
102
103 //=======================================================================
104 // function : createMainFrame()
105 // purpose  : Create frame containing dialog's input fields
106 //=======================================================================
107 QFrame* SMESHGUI_ShapeByMeshDlg::createMainFrame (QWidget* theParent)
108 {
109   QFrame* aMainGrp = new QFrame(theParent);
110   QGridLayout* aLayout = new QGridLayout(aMainGrp);
111   aLayout->setMargin(0);
112   aLayout->setSpacing(SPACING);
113
114   // elem type
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);
120
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);
124   
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);
132   
133   // element id
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
138
139   // shape name
140   QLabel* aNameLabel = new QLabel( tr("GEOMETRY_NAME"), aMainGrp );
141   myGeomName = new QLineEdit( aMainGrp );
142
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);
148
149   return aMainGrp;
150 }
151
152 //=======================================================================
153 // function : ~SMESHGUI_ShapeByMeshDlg()
154 // purpose  : Destructor
155 //=======================================================================
156 SMESHGUI_ShapeByMeshDlg::~SMESHGUI_ShapeByMeshDlg()
157 {
158 }
159
160 void SMESHGUI_ShapeByMeshDlg:: setMultipleAllowed( bool isAllowed )
161 {
162   myIsMultipleAllowed = isAllowed;
163 }
164
165 //================================================================================
166 /*!
167  * \brief Constructor
168  */
169 //================================================================================
170 SMESHGUI_ShapeByMeshOp::SMESHGUI_ShapeByMeshOp(bool isMultipleAllowed):
171   myIsMultipleAllowed(isMultipleAllowed)
172 {
173   if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
174     GeometryGUI::InitGeomGen();
175
176   myDlg = new SMESHGUI_ShapeByMeshDlg(myIsMultipleAllowed);
177
178   connect(myDlg->myElemTypeGroup, SIGNAL(buttonClicked(int)), SLOT(onTypeChanged(int)));
179   connect(myDlg->myElementId, SIGNAL(textChanged(const QString&)), SLOT(onElemIdChanged(const QString&)));
180 }
181
182
183 //=======================================================================
184 // function : startOperation()
185 // purpose  : Init dialog fields, connect signals and slots, show dialog
186 //=======================================================================
187 void SMESHGUI_ShapeByMeshOp::startOperation()
188 {
189   //SetMesh( SMESH::SMESH_Mesh::_nil() );
190   myIsManualIdEnter = false;
191
192   SMESHGUI_SelectionOp::startOperation();
193
194   //activateSelection(); // set filters
195   onSelectionDone(); // desable/enable [ OK ]
196
197   myDlg->show();
198 }
199
200 //================================================================================
201 /*!
202  * \brief Destructor
203  */
204 //================================================================================
205 SMESHGUI_ShapeByMeshOp::~SMESHGUI_ShapeByMeshOp()
206 {
207   if ( myDlg )
208     delete myDlg;
209 }
210
211 //================================================================================
212 /*!
213  * \brief Gets dialog of this operation
214  * \retval LightApp_Dialog* - pointer to dialog of this operation
215  */
216 //================================================================================
217 LightApp_Dialog* SMESHGUI_ShapeByMeshOp::dlg() const
218 {
219   return myDlg;
220 }
221
222 SMESH::SMESH_Mesh_ptr SMESHGUI_ShapeByMeshOp::GetMesh()
223 {
224   return myMesh;
225 }
226
227 //=======================================================================
228 // function : GetShape()
229 // purpose  : Return published sub-shape, it must be UnRegister()ed!
230 //=======================================================================
231 GEOM::GEOM_Object_ptr SMESHGUI_ShapeByMeshOp::GetShape()
232 {
233   return myGeomObj.in();
234 }
235
236 //=======================================================================
237 // function : SetMesh()
238 // purpose  : Set mesh to dialog
239 //=======================================================================
240
241 void SMESHGUI_ShapeByMeshOp::SetMesh (SMESH::SMESH_Mesh_ptr thePtr)
242 {
243   myMesh    = SMESH::SMESH_Mesh::_duplicate(thePtr);
244   myGeomObj = GEOM::GEOM_Object::_nil();
245   myHasSolids = false;
246
247   std::vector< bool > hasElement (myDlg->myElemTypeGroup->buttons().count(), false);
248   if (!myMesh->_is_nil() )
249     {
250       //     _PTR(SObject) aSobj = SMESH::FindSObject(myMesh.in());
251       //     SUIT_DataOwnerPtr anIObj (new LightApp_DataOwner(aSobj->GetID().c_str()));
252
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
256       {
257         _PTR(SObject) aSO = SMESH::FindSObject(myMesh.in());
258         GEOM::GEOM_Object_var mainShape = SMESH::GetGeom(aSO);
259         if ( !mainShape->_is_nil() ) 
260           {
261             TopoDS_Shape aShape;
262             if ( GEOMBase::GetShape(mainShape, aShape))
263               {
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() )
270                     ++nbShapes[ type ];
271                   if ( nbShapes[ type ] > 1 ) {
272                     shapeDim = dim;
273                     break;
274                   }
275                 }
276               }
277           }
278       }
279       if (shapeDim > 0)
280         {
281           if ( nbShapes[ TopAbs_SHELL ] + nbShapes[ TopAbs_SOLID ] > 1 )
282             shapeDim = 3;
283           hasElement[ EDGE ]   = shapeDim > 0 && myMesh->NbEdges();
284           hasElement[ FACE ]   = shapeDim > 1 && myMesh->NbFaces();
285           hasElement[ VOLUME ] = shapeDim > 2 && myMesh->NbVolumes();
286         }
287       myHasSolids = nbShapes[ TopAbs_SOLID ];
288     }
289
290   // disable inexistant 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 ] );
294   }
295   myDlg->myElementId->setEnabled( hasElement[ EDGE ] );
296   myDlg->myGeomName-> setEnabled( hasElement[ EDGE ] );
297
298   setElementID("");
299 }
300
301 //=======================================================================
302 // function : commitOperation()
303 // purpose  : called when "Ok" button pressed.
304 //=======================================================================
305
306 void SMESHGUI_ShapeByMeshOp::commitOperation()
307 {
308   SMESHGUI_SelectionOp::commitOperation();
309   try {
310     QStringList aListId = myDlg->myElementId->text().split( " ", QString::SkipEmptyParts);
311     if (aListId.count() == 1)
312     {
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().toLatin1().constData()) );
318     }
319     else
320     {
321       GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
322       _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
323
324       if (geomGen->_is_nil() || !aStudy)
325         return;
326
327       GEOM::GEOM_IShapesOperations_wrap aShapesOp =
328         geomGen->GetIShapesOperations(aStudy->StudyId());
329       if (aShapesOp->_is_nil() )
330         return;
331
332       TopAbs_ShapeEnum aGroupType = TopAbs_SHAPE;
333
334       std::map<double, GEOM::GEOM_Object_wrap> aGeomObjectsMap;
335       GEOM::GEOM_Object_wrap aGeomObject;
336
337       GEOM::GEOM_Object_var aMeshShape = myMesh->GetShapeToMesh();
338
339       for ( int i = 0; i < aListId.count(); i++ )
340       {
341         aGeomObject = // received object need UnRegister()!
342           SMESHGUI::GetSMESHGen()->FindGeometryByMeshElement(myMesh.in(), aListId[i].toInt());
343
344         if (aGeomObject->_is_nil()) continue;
345
346         double anId = aShapesOp->GetSubShapeIndex(aMeshShape, aGeomObject);
347         if (aShapesOp->IsDone() && !aGeomObjectsMap.count(anId) )
348         {
349           aGeomObjectsMap[anId] = aGeomObject;
350
351           TopAbs_ShapeEnum aSubShapeType = (TopAbs_ShapeEnum)aGeomObject->GetShapeType();
352           if (i == 0)
353             aGroupType = aSubShapeType;
354           else if (aSubShapeType != aGroupType)
355             aGroupType = TopAbs_SHAPE;
356         }
357       }
358
359       int aNumberOfGO = aGeomObjectsMap.size();
360       if (aNumberOfGO == 1)
361       {
362         aGeomObject = (*aGeomObjectsMap.begin()).second;
363       }
364       else if (aNumberOfGO > 1)
365       {
366         GEOM::GEOM_IGroupOperations_wrap aGroupOp =
367           geomGen->GetIGroupOperations(aStudy->StudyId());
368         if(aGroupOp->_is_nil())
369           return;
370
371         GEOM::ListOfGO_var aGeomObjects = new GEOM::ListOfGO();
372         aGeomObjects->length( aNumberOfGO );
373
374         int i = 0;
375         std::map<double, GEOM::GEOM_Object_wrap>::iterator anIter;
376         for (anIter = aGeomObjectsMap.begin(); anIter!=aGeomObjectsMap.end(); anIter++)
377           aGeomObjects[i++] = (*anIter).second.in();
378
379         //create geometry group
380         aGeomObject = aGroupOp->CreateGroup(aMeshShape, aGroupType);
381         aGroupOp->UnionList(myGeomObj, aGeomObjects);
382
383         if (!aGroupOp->IsDone())
384           return;
385       }
386
387       // publish the GEOM object in study
388       QString aNewGeomGroupName ( myDlg->myGeomName->text() );
389       SALOMEDS::Study_var aStudyVar = _CAST(Study,aStudy)->GetStudy();
390       SALOMEDS::SObject_wrap aNewGroupSO =
391         geomGen->AddInStudy( aStudyVar, aGeomObject, 
392                              aNewGeomGroupName.toLatin1().data(), aMeshShape);
393
394       // get a GEOM_Object already published, which doesn't need UnRegister()
395       CORBA::Object_var obj = aNewGroupSO->GetObject();
396       myGeomObj = GEOM::GEOM_Object::_narrow( obj );
397     }
398   }
399   catch (const SALOME::SALOME_Exception& S_ex) {
400     SalomeApp_Tools::QtCatchCorbaException(S_ex);
401   }
402   catch (...) {
403   }
404
405 }
406
407 bool SMESHGUI_ShapeByMeshOp::onApply()
408 {
409   return true;
410 }
411
412 //=======================================================================
413 // function : onSelectionDone()
414 // purpose  : SLOT called when selection changed. Enable/desable [ OK ]
415 //=======================================================================
416 void SMESHGUI_ShapeByMeshOp::onSelectionDone()
417 {
418   myDlg->setButtonEnabled( false, QtxDialog::OK );
419   setElementID("");
420
421   try {
422     SALOME_ListIO aList;
423     selectionMgr()->selectedObjects(aList, SVTK_Viewer::Type());
424     if (!myIsMultipleAllowed && aList.Extent() != 1)
425       return;
426
427     SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
428     if (aMesh->_is_nil() || myMesh->_is_nil() || aMesh->GetId() != myMesh->GetId() )
429       return;
430
431     QString aString;
432     int nbElems = SMESH::GetNameOfSelectedElements(selector(),//myViewWindow->GetSelector(),
433                                                    aList.First(), aString);
434     if (nbElems > 0) {
435       if (!myIsMultipleAllowed && nbElems != 1 )
436         return;
437       setElementID( aString );
438       myDlg->setButtonEnabled( true, QtxDialog::OK );
439     }
440   } catch (...) {
441   }
442 }
443
444 //=======================================================================
445 // function : activateSelection()
446 // purpose  : Activate selection in accordance with current pattern type
447 //=======================================================================
448 void SMESHGUI_ShapeByMeshOp::activateSelection()
449 {
450   selectionMgr()->clearFilters();
451   //SMESH::SetPointRepresentation(false);
452
453   myDlg->myGeomName->setText("");
454
455   QString geomName;
456   Selection_Mode mode = EdgeSelection;
457   switch ( myDlg->myElemTypeGroup->checkedId() ) {
458   case EDGE  :
459     mode = EdgeSelection;   geomName = tr("GEOM_EDGE"); break;
460   case FACE  :
461     mode = FaceSelection;   geomName = tr("GEOM_FACE"); break;
462   case VOLUME:
463     mode = VolumeSelection; geomName = tr(myHasSolids ? "GEOM_SOLID" : "GEOM_SHELL"); break;
464   default: return;
465   }
466   if ( selectionMode() != mode )
467     setSelectionMode( mode );
468
469   myDlg->myGeomName->setText( GEOMBase::GetDefaultName( geomName ));
470 }
471
472 //=======================================================================
473 //function : onTypeChanged
474 //purpose  : SLOT. Called when element type changed.
475 //=======================================================================
476
477 void SMESHGUI_ShapeByMeshOp::onTypeChanged (int theType)
478 {
479   setElementID("");
480   activateSelection();
481 }
482
483 //=======================================================================
484 //function : onTypeChanged
485 //purpose  : SLOT. Called when element id is entered
486 //           Highlight the element whose Ids the user entered manually
487 //=======================================================================
488
489 void SMESHGUI_ShapeByMeshOp::onElemIdChanged(const QString& theNewText)
490 {
491   myDlg->setButtonEnabled( false, QtxDialog::OK );
492
493   if ( myIsManualIdEnter && !myMesh->_is_nil() )
494   {
495     if ( SMESH_Actor* actor = SMESH::FindActorByObject(myMesh) )
496     {
497       if ( SMDS_Mesh* aMesh = actor->GetObject()->GetMesh() )
498       {
499         SMDSAbs_ElementType type = SMDSAbs_Edge;
500         switch ( myDlg->myElemTypeGroup->checkedId() ) {
501         case EDGE  : type = SMDSAbs_Edge;   break;
502         case FACE  : type = SMDSAbs_Face;   break;
503         case VOLUME: type = SMDSAbs_Volume; break;
504         default: return;
505         }
506         TColStd_MapOfInteger newIndices;
507         QStringList aListId = theNewText.split( " ", QString::SkipEmptyParts);
508         for ( int i = 0; i < aListId.count(); i++ ) {
509           if ( const SMDS_MeshElement * e = aMesh->FindElement( aListId[ i ].toInt() ))
510             if ( e->GetType() == type )
511               newIndices.Add( e->GetID() );
512         }
513         
514         if ( !newIndices.IsEmpty() )
515         {
516           if (!myIsMultipleAllowed && newIndices.Extent() != 1)
517             return;
518           if ( SVTK_Selector* s = selector() ) {
519             s->AddOrRemoveIndex( actor->getIO(), newIndices, false );
520             viewWindow()->highlight( actor->getIO(), true, true );
521             myDlg->setButtonEnabled( true, QtxDialog::OK );
522           }
523         }
524       }
525     }
526   }
527 }
528
529 //=======================================================================
530 //function : setElementID
531 //purpose  : programmatically set element id
532 //=======================================================================
533
534 void SMESHGUI_ShapeByMeshOp::setElementID(const QString& theText)
535 {
536   myIsManualIdEnter = false;
537   myDlg->myElementId->setText(theText);
538   myIsManualIdEnter = true;
539 }