Salome HOME
0020321: EDF : Some windows do not appear depending on the platform (MinimumSizeHint())
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ClippingDlg.cxx
1 //  Copyright (C) 2007-2008  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 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_ClippingDlg.cxx
24 // Author : Nicolas REJNERI, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_ClippingDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_SpinBox.h"
33
34 #include <SMESH_Actor.h>
35 #include <SMESH_ActorUtils.h>
36
37 // SALOME GUI includes
38 #include <SUIT_Desktop.h>
39 #include <SUIT_Session.h>
40 #include <SUIT_OverrideCursor.h>
41 #include <SUIT_MessageBox.h>
42 #include <SUIT_ResourceMgr.h>
43
44 #include <SALOME_ListIO.hxx>
45
46 #include <LightApp_Application.h>
47 #include <LightApp_SelectionMgr.h>
48
49 #include <SVTK_ViewWindow.h>
50
51 // Qt includes
52 #include <QLabel>
53 #include <QPushButton>
54 #include <QComboBox>
55 #include <QCheckBox>
56 #include <QVBoxLayout>
57 #include <QHBoxLayout>
58 #include <QGridLayout>
59 #include <QGroupBox>
60 #include <QKeyEvent>
61
62 // VTK includes
63 #include <vtkMath.h>
64 #include <vtkPlane.h>
65 #include <vtkDataSet.h>
66 #include <vtkDataSetMapper.h>
67 #include <vtkPlaneSource.h>
68 #include <vtkProperty.h>
69
70 #define SPACING 6
71 #define MARGIN  11
72
73 class OrientedPlane: public vtkPlane
74 {
75   SVTK_ViewWindow* myViewWindow;
76
77   vtkDataSetMapper* myMapper;
78
79 public:
80   static OrientedPlane *New()
81   {
82     return new OrientedPlane();
83   }
84   static OrientedPlane *New(SVTK_ViewWindow* theViewWindow)
85   {
86     return new OrientedPlane(theViewWindow);
87   }
88   vtkTypeMacro (OrientedPlane, vtkPlane);
89
90   SMESH::Orientation myOrientation;
91   float myDistance;
92   double myAngle[2];
93
94   vtkPlaneSource* myPlaneSource;
95   SALOME_Actor *myActor;
96
97   void SetOrientation (SMESH::Orientation theOrientation) { myOrientation = theOrientation; }
98   SMESH::Orientation GetOrientation() { return myOrientation; }
99
100   void SetDistance (float theDistance) { myDistance = theDistance; }
101   float GetDistance() { return myDistance; }
102
103   void ShallowCopy (OrientedPlane* theOrientedPlane)
104   {
105     SetNormal(theOrientedPlane->GetNormal());
106     SetOrigin(theOrientedPlane->GetOrigin());
107
108     myOrientation = theOrientedPlane->GetOrientation();
109     myDistance = theOrientedPlane->GetDistance();
110
111     myAngle[0] = theOrientedPlane->myAngle[0];
112     myAngle[1] = theOrientedPlane->myAngle[1];
113
114     myPlaneSource->SetNormal(theOrientedPlane->myPlaneSource->GetNormal());
115     myPlaneSource->SetOrigin(theOrientedPlane->myPlaneSource->GetOrigin());
116     myPlaneSource->SetPoint1(theOrientedPlane->myPlaneSource->GetPoint1());
117     myPlaneSource->SetPoint2(theOrientedPlane->myPlaneSource->GetPoint2());
118   }
119
120 protected:
121   OrientedPlane(SVTK_ViewWindow* theViewWindow):
122     myViewWindow(theViewWindow),
123     myOrientation(SMESH::XY),
124     myDistance(0.5)
125   {
126     Init();
127     myViewWindow->AddActor(myActor);
128   }
129
130   OrientedPlane():
131     myOrientation(SMESH::XY),
132     myViewWindow(NULL),
133     myDistance(0.5)
134   {
135     Init();
136   }
137
138   void Init()
139   {
140     myPlaneSource = vtkPlaneSource::New();
141
142     myAngle[0] = myAngle[1] = 0.0;
143
144     // Create and display actor
145     myMapper = vtkDataSetMapper::New();
146     myMapper->SetInput(myPlaneSource->GetOutput());
147
148     myActor = SALOME_Actor::New();
149     myActor->VisibilityOff();
150     myActor->PickableOff();
151     myActor->SetInfinitive(true);
152     myActor->SetMapper(myMapper);
153
154     vtkFloatingPointType anRGB[3];
155     vtkProperty* aProp = vtkProperty::New();
156     SMESH::GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) );
157     aProp->SetColor(anRGB[0],anRGB[1],anRGB[2]);
158     aProp->SetOpacity(0.75);
159     myActor->SetProperty(aProp);
160     aProp->Delete();
161
162     vtkProperty* aBackProp = vtkProperty::New();
163     SMESH::GetColor( "SMESH", "backface_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 0, 255 ) );
164     aBackProp->SetColor(anRGB[0],anRGB[1],anRGB[2]);
165     aBackProp->SetOpacity(0.75);
166     myActor->SetBackfaceProperty(aBackProp);
167     aBackProp->Delete();
168   }
169
170   ~OrientedPlane(){
171     myViewWindow->RemoveActor(myActor);
172     myActor->Delete();
173     
174     myMapper->RemoveAllInputs();
175     myMapper->Delete();
176
177     // commented: porting to vtk 5.0
178     //    myPlaneSource->UnRegisterAllOutputs();
179     myPlaneSource->Delete();
180   };
181
182 private:
183   // Not implemented.
184   OrientedPlane (const OrientedPlane&);
185   void operator= (const OrientedPlane&);
186
187 };
188
189 struct TSetVisiblity {
190   TSetVisiblity(int theIsVisible): myIsVisible(theIsVisible){}
191   void operator()(SMESH::TVTKPlane& theOrientedPlane){
192     theOrientedPlane->myActor->SetVisibility(myIsVisible);
193   }
194   int myIsVisible;
195 };
196
197 //=================================================================================
198 // used in SMESHGUI::restoreVisualParameters() to avoid
199 // declaration of OrientedPlane outside of SMESHGUI_ClippingDlg.cxx
200 //=================================================================================
201 void SMESHGUI_ClippingDlg::AddPlane (SMESH_Actor*         theActor,
202                                      SVTK_ViewWindow*     theViewWindow,
203                                      SMESH::Orientation   theOrientation,
204                                      double               theDistance,
205                                      vtkFloatingPointType theAngle[2])
206 {
207   OrientedPlane* aPlane = OrientedPlane::New(theViewWindow);
208
209   aPlane->myAngle[0] = theAngle[0];
210   aPlane->myAngle[1] = theAngle[1];
211
212   aPlane->SetOrientation(theOrientation);
213   aPlane->SetDistance(theDistance);
214
215   vtkFloatingPointType aNormal[3];
216   vtkFloatingPointType aDir[2][3] = {{0, 0, 0}, {0, 0, 0}};
217   {
218     static double aCoeff = vtkMath::Pi()/180.0;
219
220     vtkFloatingPointType anU[2] = {cos(aCoeff * theAngle[0]), cos(aCoeff * theAngle[1])};
221     vtkFloatingPointType aV[2] = {sqrt(1.0 - anU[0]*anU[0]), sqrt(1.0 - anU[1]*anU[1])};
222     aV[0] = theAngle[0] > 0? aV[0]: -aV[0];
223     aV[1] = theAngle[1] > 0? aV[1]: -aV[1];
224
225     switch (theOrientation) {
226     case SMESH::XY:
227       aDir[0][1] = anU[0];
228       aDir[0][2] = aV[0];
229
230       aDir[1][0] = anU[1];
231       aDir[1][2] = aV[1];
232
233       break;
234     case SMESH::YZ:
235       aDir[0][2] = anU[0];
236       aDir[0][0] = aV[0];
237
238       aDir[1][1] = anU[1];
239       aDir[1][0] = aV[1];
240
241       break;
242     case SMESH::ZX:
243       aDir[0][0] = anU[0];
244       aDir[0][1] = aV[0];
245
246       aDir[1][2] = anU[1];
247       aDir[1][1] = aV[1];
248
249       break;
250     }
251
252     vtkMath::Cross(aDir[1],aDir[0],aNormal);
253     vtkMath::Normalize(aNormal);
254     vtkMath::Cross(aNormal,aDir[1],aDir[0]);
255   }
256
257   // ???
258   theActor->SetPlaneParam(aNormal, theDistance, aPlane);
259
260   vtkDataSet* aDataSet = theActor->GetInput();
261   vtkFloatingPointType *aPnt = aDataSet->GetCenter();
262
263   vtkFloatingPointType* anOrigin = aPlane->GetOrigin();
264   vtkFloatingPointType aDel = aDataSet->GetLength()/2.0;
265
266   vtkFloatingPointType aDelta[2][3] = {{aDir[0][0]*aDel, aDir[0][1]*aDel, aDir[0][2]*aDel},
267                                        {aDir[1][0]*aDel, aDir[1][1]*aDel, aDir[1][2]*aDel}};
268   vtkFloatingPointType aParam, aPnt0[3], aPnt1[3], aPnt2[3];
269
270   vtkFloatingPointType aPnt01[3] = {aPnt[0] - aDelta[0][0] - aDelta[1][0],
271                                     aPnt[1] - aDelta[0][1] - aDelta[1][1],
272                                     aPnt[2] - aDelta[0][2] - aDelta[1][2]};
273   vtkFloatingPointType aPnt02[3] = {aPnt01[0] + aNormal[0],
274                                     aPnt01[1] + aNormal[1],
275                                     aPnt01[2] + aNormal[2]};
276   vtkPlane::IntersectWithLine(aPnt01,aPnt02,aNormal,anOrigin,aParam,aPnt0);
277
278   vtkFloatingPointType aPnt11[3] = {aPnt[0] - aDelta[0][0] + aDelta[1][0],
279                                     aPnt[1] - aDelta[0][1] + aDelta[1][1],
280                                     aPnt[2] - aDelta[0][2] + aDelta[1][2]};
281   vtkFloatingPointType aPnt12[3] = {aPnt11[0] + aNormal[0],
282                                     aPnt11[1] + aNormal[1],
283                                     aPnt11[2] + aNormal[2]};
284   vtkPlane::IntersectWithLine(aPnt11,aPnt12,aNormal,anOrigin,aParam,aPnt1);
285
286   vtkFloatingPointType aPnt21[3] = {aPnt[0] + aDelta[0][0] - aDelta[1][0],
287                                     aPnt[1] + aDelta[0][1] - aDelta[1][1],
288                                     aPnt[2] + aDelta[0][2] - aDelta[1][2]};
289   vtkFloatingPointType aPnt22[3] = {aPnt21[0] + aNormal[0],
290                                     aPnt21[1] + aNormal[1],
291                                     aPnt21[2] + aNormal[2]};
292   vtkPlane::IntersectWithLine(aPnt21,aPnt22,aNormal,anOrigin,aParam,aPnt2);
293
294   vtkPlaneSource* aPlaneSource = aPlane->myPlaneSource;
295   aPlaneSource->SetNormal(aNormal[0],aNormal[1],aNormal[2]);
296   aPlaneSource->SetOrigin(aPnt0[0],aPnt0[1],aPnt0[2]);
297   aPlaneSource->SetPoint1(aPnt1[0],aPnt1[1],aPnt1[2]);
298   aPlaneSource->SetPoint2(aPnt2[0],aPnt2[1],aPnt2[2]);
299
300   theActor->AddClippingPlane(aPlane);
301   aPlane->Delete();
302 }
303
304 //=================================================================================
305 // used in SMESHGUI::restoreVisualParameters() to avoid
306 // declaration of OrientedPlane outside of SMESHGUI_ClippingDlg.cxx
307 //=================================================================================
308 void SMESHGUI_ClippingDlg::GetPlaneParam (SMESH_Actor*          theActor,
309                                           int                   thePlaneIndex,
310                                           SMESH::Orientation&   theOrientation,
311                                           double&               theDistance,
312                                           vtkFloatingPointType* theAngle)
313 {
314   if (vtkPlane* aPln = theActor->GetClippingPlane(thePlaneIndex)) {
315     if (OrientedPlane* aPlane = OrientedPlane::SafeDownCast(aPln)) {
316       theOrientation = aPlane->GetOrientation();
317       theDistance = aPlane->GetDistance();
318       theAngle[0] = aPlane->myAngle[0];
319       theAngle[1] = aPlane->myAngle[1];
320     }
321   }
322 }
323
324 //=================================================================================
325 // class    : SMESHGUI_ClippingDlg()
326 // purpose  :
327 //
328 //=================================================================================
329 SMESHGUI_ClippingDlg::SMESHGUI_ClippingDlg( SMESHGUI* theModule ):
330   QDialog( SMESH::GetDesktop(theModule) ),
331   mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
332   mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
333   mySMESHGUI(theModule)
334 {
335   setModal( false );
336   setAttribute( Qt::WA_DeleteOnClose, true );
337   setWindowTitle(tr("SMESH_CLIPPING_TITLE"));
338   setSizeGripEnabled(true);
339
340   QVBoxLayout* SMESHGUI_ClippingDlgLayout = new QVBoxLayout(this);
341   SMESHGUI_ClippingDlgLayout->setSpacing(SPACING);
342   SMESHGUI_ClippingDlgLayout->setMargin(MARGIN);
343
344   // Controls for selecting, creating, deleting planes
345   QGroupBox* GroupPlanes = new QGroupBox(tr("Clipping planes"), this);
346   QHBoxLayout* GroupPlanesLayout = new QHBoxLayout(GroupPlanes);
347   GroupPlanesLayout->setSpacing(SPACING);
348   GroupPlanesLayout->setMargin(MARGIN);
349
350   ComboBoxPlanes = new QComboBox(GroupPlanes);
351
352   buttonNew = new QPushButton(tr("SMESH_BUT_NEW"), GroupPlanes);
353
354   buttonDelete = new QPushButton(tr("SMESH_BUT_DELETE"), GroupPlanes);
355
356   GroupPlanesLayout->addWidget(ComboBoxPlanes);
357   GroupPlanesLayout->addStretch();
358   GroupPlanesLayout->addWidget(buttonNew);
359   GroupPlanesLayout->addWidget(buttonDelete);
360
361   // Controls for defining plane parameters
362   QGroupBox* GroupParameters = new QGroupBox(tr("SMESH_PARAMETERS"), this);
363   QGridLayout* GroupParametersLayout = new QGridLayout(GroupParameters);
364   GroupParametersLayout->setSpacing(SPACING);
365   GroupParametersLayout->setMargin(MARGIN);
366
367   TextLabelOrientation = new QLabel(tr("SMESH_ORIENTATION"), GroupParameters);
368
369   ComboBoxOrientation = new QComboBox(GroupParameters);
370
371   TextLabelDistance = new QLabel(tr("SMESH_DISTANCE"), GroupParameters);
372
373   SpinBoxDistance = new SMESHGUI_SpinBox(GroupParameters);
374
375   TextLabelRot1 = new QLabel(tr("Rotation around X (Y to Z):"), GroupParameters);
376
377   SpinBoxRot1 = new SMESHGUI_SpinBox(GroupParameters);
378
379   TextLabelRot2 = new QLabel(tr("Rotation around Y (X to Z):"), GroupParameters);
380
381   SpinBoxRot2 = new SMESHGUI_SpinBox(GroupParameters);
382
383   PreviewCheckBox = new QCheckBox(tr("Show preview"), GroupParameters);
384   PreviewCheckBox->setChecked(true);
385
386   AutoApplyCheckBox = new QCheckBox(tr("Auto Apply"), GroupParameters);
387   AutoApplyCheckBox->setChecked(false);
388
389   GroupParametersLayout->addWidget(TextLabelOrientation, 0, 0);
390   GroupParametersLayout->addWidget(ComboBoxOrientation,  0, 1);
391   GroupParametersLayout->addWidget(TextLabelDistance,    1, 0);
392   GroupParametersLayout->addWidget(SpinBoxDistance,      1, 1);
393   GroupParametersLayout->addWidget(TextLabelRot1,        2, 0);
394   GroupParametersLayout->addWidget(SpinBoxRot1,          2, 1);
395   GroupParametersLayout->addWidget(TextLabelRot2,        3, 0);
396   GroupParametersLayout->addWidget(SpinBoxRot2,          3, 1);
397   GroupParametersLayout->addWidget(PreviewCheckBox,      4, 0);
398   GroupParametersLayout->addWidget(AutoApplyCheckBox,    4, 1);
399
400   // Controls for "Ok", "Apply" and "Close" button
401   QGroupBox* GroupButtons = new QGroupBox(this);
402   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
403   GroupButtonsLayout->setSpacing(SPACING);
404   GroupButtonsLayout->setMargin(MARGIN);
405   
406   buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
407   buttonOk->setAutoDefault(true);
408   buttonOk->setDefault(true);
409   buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
410   buttonApply->setAutoDefault(true);
411   buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
412   buttonCancel->setAutoDefault(true);
413   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
414   buttonHelp->setAutoDefault(true);
415   GroupButtonsLayout->addWidget(buttonOk);
416   GroupButtonsLayout->addSpacing(10);
417   GroupButtonsLayout->addWidget(buttonApply);
418   GroupButtonsLayout->addSpacing(10);
419   GroupButtonsLayout->addStretch();
420   GroupButtonsLayout->addWidget(buttonCancel);
421   GroupButtonsLayout->addWidget(buttonHelp);
422
423   SMESHGUI_ClippingDlgLayout->addWidget(GroupPlanes);
424   SMESHGUI_ClippingDlgLayout->addWidget(GroupParameters);
425   SMESHGUI_ClippingDlgLayout->addWidget(GroupButtons);
426
427   // Initial state
428   SpinBoxDistance->RangeStepAndValidator(0.0, 1.0, 0.01, 3);
429   SpinBoxRot1->RangeStepAndValidator(-180.0, 180.0, 1, 3);
430   SpinBoxRot2->RangeStepAndValidator(-180.0, 180.0, 1, 3);
431
432   ComboBoxOrientation->addItem(tr("|| X-Y"));
433   ComboBoxOrientation->addItem(tr("|| Y-Z"));
434   ComboBoxOrientation->addItem(tr("|| Z-X"));
435
436   SpinBoxDistance->SetValue(0.5);
437
438   myActor = 0;
439   myIsSelectPlane = false;
440   onSelectionChanged();
441
442   myHelpFileName = "clipping_page.html";
443
444   // signals and slots connections :
445   connect(ComboBoxPlanes, SIGNAL(activated(int)), this, SLOT(onSelectPlane(int)));
446   connect(buttonNew, SIGNAL(clicked()), this, SLOT(ClickOnNew()));
447   connect(buttonDelete, SIGNAL(clicked()), this, SLOT(ClickOnDelete()));
448   connect(ComboBoxOrientation, SIGNAL(activated(int)), this, SLOT(onSelectOrientation(int)));
449   connect(SpinBoxDistance, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam()));
450   connect(SpinBoxRot1, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam()));
451   connect(SpinBoxRot2, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam()));
452   connect(PreviewCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnPreviewToggle(bool)));
453   connect(AutoApplyCheckBox, SIGNAL(toggled(bool)), this, SLOT(ClickOnApply()));
454   connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk()));
455   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(ClickOnCancel()));
456   connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply()));
457   connect(buttonHelp, SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
458   connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()), this, SLOT(ClickOnCancel()));
459   connect(mySelectionMgr,  SIGNAL(currentSelectionChanged()), this, SLOT(onSelectionChanged()));
460   /* to close dialog if study frame change */
461   connect(mySMESHGUI, SIGNAL (SignalStudyFrameChanged()), this, SLOT(ClickOnCancel()));
462
463   this->show();
464 }
465
466 //=================================================================================
467 // function : ~SMESHGUI_ClippingDlg()
468 // purpose  :
469 //=================================================================================
470 SMESHGUI_ClippingDlg::~SMESHGUI_ClippingDlg()
471 {
472   // no need to delete child widgets, Qt does it all for us
473   std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisiblity(false));
474   if (mySMESHGUI)
475     if (SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow(mySMESHGUI))
476       SMESH::RenderViewWindow(aViewWindow);
477 }
478
479 double SMESHGUI_ClippingDlg::getDistance() const
480 {
481   return SpinBoxDistance->GetValue();
482 }
483
484 void SMESHGUI_ClippingDlg::setDistance( const double theDistance )
485 {
486   SpinBoxDistance->SetValue( theDistance );
487 }
488
489 double SMESHGUI_ClippingDlg::getRotation1() const
490 {
491   return SpinBoxRot1->GetValue();
492 }
493
494 double SMESHGUI_ClippingDlg::getRotation2() const
495 {
496   return SpinBoxRot2->GetValue();
497 }
498
499 //=======================================================================
500 // function : ClickOnApply()
501 // purpose  :
502 //=======================================================================
503 void SMESHGUI_ClippingDlg::ClickOnApply()
504 {
505   if (!myActor)
506     return;
507
508   if (SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow(mySMESHGUI)) {
509     SUIT_OverrideCursor wc;
510     
511     QWidget *aCurrWid = this->focusWidget();
512     aCurrWid->clearFocus();
513     aCurrWid->setFocus();
514
515     myActor->RemoveAllClippingPlanes();
516
517     SMESH::TPlanes::iterator anIter = myPlanes.begin();
518     for ( ; anIter != myPlanes.end(); anIter++) {
519       OrientedPlane* anOrientedPlane = OrientedPlane::New(aViewWindow);
520       anOrientedPlane->ShallowCopy(anIter->GetPointer());
521       myActor->AddClippingPlane(anOrientedPlane);
522       anOrientedPlane->Delete();
523     }
524
525     SMESH::RenderViewWindow(aViewWindow);
526   }
527 }
528
529 //=======================================================================
530 // function : ClickOnOk()
531 // purpose  :
532 //=======================================================================
533 void SMESHGUI_ClippingDlg::ClickOnOk()
534 {
535   ClickOnApply();
536   ClickOnCancel();
537 }
538
539 //=======================================================================
540 // function : ClickOnCancel()
541 // purpose  :
542 //=======================================================================
543 void SMESHGUI_ClippingDlg::ClickOnCancel()
544 {
545   close();
546 }
547
548 //=================================================================================
549 // function : ClickOnHelp()
550 // purpose  :
551 //=================================================================================
552 void SMESHGUI_ClippingDlg::ClickOnHelp()
553 {
554   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
555   if (app) 
556     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
557   else {
558                 QString platform;
559 #ifdef WIN32
560                 platform = "winapplication";
561 #else
562                 platform = "application";
563 #endif
564     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
565                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
566                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
567                                                                  platform)).
568                              arg(myHelpFileName));
569   }
570 }
571
572 //=================================================================================
573 // function : onSelectionChanged()
574 // purpose  : Called when selection is changed
575 //=================================================================================
576 void SMESHGUI_ClippingDlg::onSelectionChanged()
577 {
578   if (SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow(mySMESHGUI)) {
579     const SALOME_ListIO& aList = mySelector->StoredIObjects();
580     if (aList.Extent() > 0) {
581       Handle(SALOME_InteractiveObject) IOS = aList.First();
582       myActor = SMESH::FindActorByEntry(IOS->getEntry());
583       if (myActor) {
584         std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisiblity(false));
585         myPlanes.clear();
586
587         vtkIdType anId = 0, anEnd = myActor->GetNumberOfClippingPlanes();
588         for ( ; anId < anEnd; anId++) {
589           if (vtkImplicitFunction* aFunction = myActor->GetClippingPlane(anId)) {
590             if(OrientedPlane* aPlane = OrientedPlane::SafeDownCast(aFunction)){
591               OrientedPlane* anOrientedPlane = OrientedPlane::New(aViewWindow);
592               SMESH::TVTKPlane aTVTKPlane(anOrientedPlane);
593               anOrientedPlane->Delete();
594               aTVTKPlane->ShallowCopy(aPlane);
595               myPlanes.push_back(aTVTKPlane);
596             }
597           }
598         }
599
600         std::for_each(myPlanes.begin(),myPlanes.end(),
601                       TSetVisiblity(PreviewCheckBox->isChecked()));
602       }
603     }
604     SMESH::RenderViewWindow(aViewWindow);
605   }
606   Sinchronize();
607 }
608
609 //=======================================================================
610 // function : onSelectPlane()
611 // purpose  :
612 //=======================================================================
613 void SMESHGUI_ClippingDlg::onSelectPlane (int theIndex)
614 {
615   if (!myActor || myPlanes.empty())
616     return;
617
618   OrientedPlane* aPlane = myPlanes[theIndex].GetPointer();
619
620   // Orientation
621   SMESH::Orientation anOrientation = aPlane->GetOrientation();
622
623   // Rotations
624   double aRot[2] = {aPlane->myAngle[0], aPlane->myAngle[1]};
625
626   // Set plane parameters in the dialog
627   myIsSelectPlane = true;
628   setDistance(aPlane->GetDistance());
629   setRotation(aRot[0], aRot[1]);
630   switch (anOrientation) {
631   case SMESH::XY:
632     ComboBoxOrientation->setCurrentIndex(0);
633     onSelectOrientation(0);
634     break;
635   case SMESH::YZ:
636     ComboBoxOrientation->setCurrentIndex(1);
637     onSelectOrientation(1);
638     break;
639   case SMESH::ZX:
640     ComboBoxOrientation->setCurrentIndex(2);
641     onSelectOrientation(2);
642     break;
643   }
644   myIsSelectPlane = false;
645 }
646
647 //=======================================================================
648 // function : ClickOnNew()
649 // purpose  :
650 //=======================================================================
651 void SMESHGUI_ClippingDlg::ClickOnNew()
652 {
653   if (!myActor)
654     return;
655
656   if(SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow(mySMESHGUI)){
657     OrientedPlane* aPlane = OrientedPlane::New(aViewWindow);
658     SMESH::TVTKPlane aTVTKPlane(aPlane);
659     myPlanes.push_back(aTVTKPlane);
660
661     if (PreviewCheckBox->isChecked())
662       aTVTKPlane->myActor->VisibilityOn();
663     
664     Sinchronize();
665     SetCurrentPlaneParam();
666   }
667 }
668
669 //=======================================================================
670 // function : ClickOnDelete()
671 // purpose  :
672 //=======================================================================
673 void SMESHGUI_ClippingDlg::ClickOnDelete()
674 {
675   if (!myActor || myPlanes.empty())
676     return;
677
678   int aPlaneIndex = ComboBoxPlanes->currentIndex();
679
680   SMESH::TPlanes::iterator anIter = myPlanes.begin() + aPlaneIndex;
681   anIter->GetPointer()->myActor->SetVisibility(false);
682   myPlanes.erase(anIter);
683
684   if(AutoApplyCheckBox->isChecked())
685     ClickOnApply();
686
687   Sinchronize();
688   SMESH::RenderViewWindow(SMESH::GetCurrentVtkView());
689 }
690
691 //=======================================================================
692 // function : onSelectOrientation()
693 // purpose  :
694 //=======================================================================
695 void SMESHGUI_ClippingDlg::onSelectOrientation (int theItem)
696 {
697   if (myPlanes.empty())
698     return;
699
700   if      (theItem == 0) {
701     TextLabelRot1->setText(tr("Rotation around X (Y to Z):"));
702     TextLabelRot2->setText(tr("Rotation around Y (X to Z):"));
703   }
704   else if (theItem == 1) {
705     TextLabelRot1->setText(tr("Rotation around Y (Z to X):"));
706     TextLabelRot2->setText(tr("Rotation around Z (Y to X):"));
707   }
708   else if (theItem == 2) {
709     TextLabelRot1->setText(tr("Rotation around Z (X to Y):"));
710     TextLabelRot2->setText(tr("Rotation around X (Z to Y):"));
711   }
712
713   if((QComboBox*)sender() == ComboBoxOrientation)
714     SetCurrentPlaneParam();
715 }
716
717 //=======================================================================
718 // function : Sinchronize()
719 // purpose  :
720 //=======================================================================
721 void SMESHGUI_ClippingDlg::Sinchronize()
722 {
723   int aNbPlanes = myPlanes.size();
724   ComboBoxPlanes->clear();
725
726   QString aName;
727   for(int i = 1; i<=aNbPlanes; i++) {
728     aName = QString(tr("Plane# %1")).arg(i);
729     ComboBoxPlanes->addItem(aName);
730   }
731
732   int aPos = ComboBoxPlanes->count() - 1;
733   ComboBoxPlanes->setCurrentIndex(aPos);
734
735   bool anIsControlsEnable = (aPos >= 0);
736   if (anIsControlsEnable) {
737     onSelectPlane(aPos);
738   } else {
739     ComboBoxPlanes->addItem(tr("No planes"));
740     SpinBoxRot1->SetValue(0.0);
741     SpinBoxRot2->SetValue(0.0);
742     SpinBoxDistance->SetValue(0.5);
743   }
744
745   buttonDelete->setEnabled(anIsControlsEnable);
746   buttonApply->setEnabled(anIsControlsEnable);
747   PreviewCheckBox->setEnabled(anIsControlsEnable);
748   AutoApplyCheckBox->setEnabled(anIsControlsEnable);
749   ComboBoxOrientation->setEnabled(anIsControlsEnable);
750   SpinBoxDistance->setEnabled(anIsControlsEnable);
751   SpinBoxRot1->setEnabled(anIsControlsEnable);
752   SpinBoxRot2->setEnabled(anIsControlsEnable);
753 }
754
755 //=======================================================================
756 // function : setRotation()
757 // purpose  :
758 //=======================================================================
759 void SMESHGUI_ClippingDlg::setRotation (const double theRot1, const double theRot2)
760 {
761   SpinBoxRot1->SetValue(theRot1);
762   SpinBoxRot2->SetValue(theRot2);
763 }
764
765 //=======================================================================
766 // function : SetCurrentPlaneParam()
767 // purpose  :
768 //=======================================================================
769 void SMESHGUI_ClippingDlg::SetCurrentPlaneParam()
770 {
771   if (myPlanes.empty() || myIsSelectPlane)
772     return;
773
774   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
775
776   OrientedPlane* aPlane = myPlanes[aCurPlaneIndex].GetPointer();
777
778   vtkFloatingPointType aNormal[3];
779   SMESH::Orientation anOrientation;
780   vtkFloatingPointType aDir[3][3] = {{0, 0, 0}, {0, 0, 0}};
781   {
782     static double aCoeff = vtkMath::Pi()/180.0;
783
784     vtkFloatingPointType aRot[2] = {getRotation1(), getRotation2()};
785     aPlane->myAngle[0] = aRot[0];
786     aPlane->myAngle[1] = aRot[1];
787
788     vtkFloatingPointType anU[2] = {cos(aCoeff*aRot[0]), cos(aCoeff*aRot[1])};
789     vtkFloatingPointType aV[2] = {sqrt(1.0-anU[0]*anU[0]), sqrt(1.0-anU[1]*anU[1])};
790     aV[0] = aRot[0] > 0? aV[0]: -aV[0];
791     aV[1] = aRot[1] > 0? aV[1]: -aV[1];
792
793     switch (ComboBoxOrientation->currentIndex()) {
794     case 0:
795       anOrientation = SMESH::XY;
796
797       aDir[0][1] = anU[0];
798       aDir[0][2] = aV[0];
799
800       aDir[1][0] = anU[1];
801       aDir[1][2] = aV[1];
802
803       break;
804     case 1:
805       anOrientation = SMESH::YZ;
806
807       aDir[0][2] = anU[0];
808       aDir[0][0] = aV[0];
809
810       aDir[1][1] = anU[1];
811       aDir[1][0] = aV[1];
812
813       break;
814     case 2:
815       anOrientation = SMESH::ZX;
816
817       aDir[0][0] = anU[0];
818       aDir[0][1] = aV[0];
819
820       aDir[1][2] = anU[1];
821       aDir[1][1] = aV[1];
822
823       break;
824     }
825
826     vtkMath::Cross(aDir[1],aDir[0],aNormal);
827     vtkMath::Normalize(aNormal);
828     vtkMath::Cross(aNormal,aDir[1],aDir[0]);
829   }
830
831   aPlane->SetOrientation(anOrientation);
832   aPlane->SetDistance(getDistance());
833
834   myActor->SetPlaneParam(aNormal, getDistance(), aPlane);
835
836   vtkDataSet* aDataSet = myActor->GetInput();
837   vtkFloatingPointType *aPnt = aDataSet->GetCenter();
838
839   vtkFloatingPointType* anOrigin = aPlane->GetOrigin();
840   vtkFloatingPointType aDel = aDataSet->GetLength()/2.0;
841
842   vtkFloatingPointType aDelta[2][3] = {{aDir[0][0]*aDel, aDir[0][1]*aDel, aDir[0][2]*aDel},
843                                        {aDir[1][0]*aDel, aDir[1][1]*aDel, aDir[1][2]*aDel}};
844   vtkFloatingPointType aParam, aPnt0[3], aPnt1[3], aPnt2[3];
845
846   vtkFloatingPointType aPnt01[3] = {aPnt[0] - aDelta[0][0] - aDelta[1][0],
847                                     aPnt[1] - aDelta[0][1] - aDelta[1][1],
848                                     aPnt[2] - aDelta[0][2] - aDelta[1][2]};
849   vtkFloatingPointType aPnt02[3] = {aPnt01[0] + aNormal[0],
850                                     aPnt01[1] + aNormal[1],
851                                     aPnt01[2] + aNormal[2]};
852   vtkPlane::IntersectWithLine(aPnt01,aPnt02,aNormal,anOrigin,aParam,aPnt0);
853
854   vtkFloatingPointType aPnt11[3] = {aPnt[0] - aDelta[0][0] + aDelta[1][0],
855                                     aPnt[1] - aDelta[0][1] + aDelta[1][1],
856                                     aPnt[2] - aDelta[0][2] + aDelta[1][2]};
857   vtkFloatingPointType aPnt12[3] = {aPnt11[0] + aNormal[0],
858                                     aPnt11[1] + aNormal[1],
859                                     aPnt11[2] + aNormal[2]};
860   vtkPlane::IntersectWithLine(aPnt11,aPnt12,aNormal,anOrigin,aParam,aPnt1);
861
862   vtkFloatingPointType aPnt21[3] = {aPnt[0] + aDelta[0][0] - aDelta[1][0],
863                                     aPnt[1] + aDelta[0][1] - aDelta[1][1],
864                                     aPnt[2] + aDelta[0][2] - aDelta[1][2]};
865   vtkFloatingPointType aPnt22[3] = {aPnt21[0] + aNormal[0],
866                                     aPnt21[1] + aNormal[1],
867                                     aPnt21[2] + aNormal[2]};
868   vtkPlane::IntersectWithLine(aPnt21,aPnt22,aNormal,anOrigin,aParam,aPnt2);
869
870   vtkPlaneSource* aPlaneSource = aPlane->myPlaneSource;
871   aPlaneSource->SetNormal(aNormal[0],aNormal[1],aNormal[2]);
872   aPlaneSource->SetOrigin(aPnt0[0],aPnt0[1],aPnt0[2]);
873   aPlaneSource->SetPoint1(aPnt1[0],aPnt1[1],aPnt1[2]);
874   aPlaneSource->SetPoint2(aPnt2[0],aPnt2[1],aPnt2[2]);
875
876   if(AutoApplyCheckBox->isChecked())
877     ClickOnApply();
878
879   SMESH::RenderViewWindow(SMESH::GetCurrentVtkView());
880 }
881
882 //=======================================================================
883 // function : OnPreviewToggle()
884 // purpose  :
885 //=======================================================================
886 void SMESHGUI_ClippingDlg::OnPreviewToggle (bool theIsToggled)
887 {
888   std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisiblity(theIsToggled));
889   SMESH::RenderViewWindow(SMESH::GetCurrentVtkView());
890 }
891
892 //=================================================================================
893 // function : keyPressEvent()
894 // purpose  :
895 //=================================================================================
896 void SMESHGUI_ClippingDlg::keyPressEvent( QKeyEvent* e )
897 {
898   QDialog::keyPressEvent( e );
899   if ( e->isAccepted() )
900     return;
901
902   if ( e->key() == Qt::Key_F1 ) {
903     e->accept();
904     ClickOnHelp();
905   }
906 }