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