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