Salome HOME
Fix pb with labels of rotation spin boxes (bad update after switch from IJK pane...
[modules/visu.git] / src / VISUGUI / VisuGUI_ClippingDlg.cxx
1
2 #include "VisuGUI_ClippingDlg.h"
3
4 #include "VisuGUI.h"
5 #include "VisuGUI_Tools.h"
6
7 #include "VISU_Prs3d_i.hh"
8 #include "VISU_Result_i.hh"
9
10 #include "SalomeApp_SelectionMgr.h"
11
12 #include "SVTK_ViewWindow.h"
13
14 #include "SUIT_Session.h"
15 #include "SUIT_Desktop.h"
16 #include "SUIT_ResourceMgr.h"
17 #include "SUIT_OverrideCursor.h"
18
19 #include "SALOME_Actor.h"
20
21 // QT Includes
22 #include <qlabel.h>
23 #include <qpushbutton.h>
24 #include <qcombobox.h>
25 #include <qcheckbox.h>
26 #include <qlayout.h>
27 #include <qgroupbox.h>
28 #include <qvalidator.h>
29 #include <qtabwidget.h>
30 #include <qhbuttongroup.h>
31 #include <qradiobutton.h>
32 #include <qspinbox.h>
33
34 // VTK Includes
35 #include <vtkMath.h>
36 #include <vtkCamera.h>
37 #include <vtkRenderer.h>
38 #include <vtkDataSet.h>
39 #include <vtkDataSetMapper.h>
40 #include <vtkImplicitFunction.h>
41 #include <vtkPlaneSource.h>
42 #include <vtkPolyData.h>
43 #include <vtkUnstructuredGrid.h>
44
45 // OCCT Includes
46 #include <gp_Dir.hxx>
47
48 using namespace std;
49
50 namespace VISU {
51   float GetFloat (const QString& theValue, float theDefault)
52   {
53     if (theValue.isEmpty()) return theDefault;
54     SUIT_ResourceMgr* aResourceMgr = VISU::GetResourceMgr();
55     QString aValue = aResourceMgr->stringValue(theValue);
56     if (aValue.isEmpty()) return theDefault;
57     return aValue.toFloat();
58   }
59
60   void RenderViewWindow (SVTK_ViewWindow* vw)
61   {
62     if (vw) {
63 //if (vw->getRenderer()->GetActors()->GetNumberOfItems() > 0) {
64         vw->getRenderer()->ResetCameraClippingRange();
65         vw->Repaint();
66 //}
67     }
68   }
69
70   void RangeStepAndValidator (QtxDblSpinBox* theSpinBox, double min, double max,
71                               double step, unsigned short decimals)
72   {
73     theSpinBox->setRange(min, max);
74     theSpinBox->setLineStep(step);
75     ((QDoubleValidator*)theSpinBox->validator())->setRange(min, max, decimals);
76   }
77 };
78
79 //=================================================================================
80 //class    : OrientedPlane
81 //purpose  :
82 //=================================================================================
83 class OrientedPlane: public vtkPlane
84 {
85   SVTK_ViewWindow* myViewWindow;
86
87   vtkDataSetMapper* myMapper;
88
89 public:
90   static OrientedPlane * New() {
91     return new OrientedPlane();
92   }
93   static OrientedPlane * New (SVTK_ViewWindow* vw) {
94     return new OrientedPlane(vw);
95   }
96   vtkTypeMacro(OrientedPlane, vtkPlane);
97
98
99   VISU::Orientation myOrientation;
100   float myDistance;
101   double myAngle[2];
102
103   vtkPlaneSource* myPlaneSource;
104   SALOME_Actor *myActor;
105
106   void SetOrientation(VISU::Orientation theOrientation) {myOrientation = theOrientation;}
107   VISU::Orientation GetOrientation() {return myOrientation;}
108
109   void SetDistance(float theDistance) {myDistance = theDistance;}
110   float GetDistance() {return myDistance;}
111
112   void ShallowCopy(OrientedPlane* theOrientedPlane){
113     SetNormal(theOrientedPlane->GetNormal());
114     SetOrigin(theOrientedPlane->GetOrigin());
115
116     myOrientation = theOrientedPlane->GetOrientation();
117     myDistance = theOrientedPlane->GetDistance();
118
119     myAngle[0] = theOrientedPlane->myAngle[0];
120     myAngle[1] = theOrientedPlane->myAngle[1];
121
122     myPlaneSource->SetNormal(theOrientedPlane->myPlaneSource->GetNormal());
123     myPlaneSource->SetOrigin(theOrientedPlane->myPlaneSource->GetOrigin());
124     myPlaneSource->SetPoint1(theOrientedPlane->myPlaneSource->GetPoint1());
125     myPlaneSource->SetPoint2(theOrientedPlane->myPlaneSource->GetPoint2());
126   }
127
128 protected:
129   OrientedPlane(SVTK_ViewWindow* vw):
130     myOrientation(VISU::XY),
131     myDistance(0.5),
132     myViewWindow(vw)
133   {
134     Init();
135     myViewWindow->AddActor(myActor);
136   }
137
138   OrientedPlane():
139     myOrientation(VISU::XY),
140     myDistance(0.5),
141     myViewWindow(NULL)
142   {
143     Init();
144   }
145
146   void Init(){
147     myPlaneSource = vtkPlaneSource::New();
148
149     myAngle[0] = myAngle[1] = 0.0;
150
151     // Create and display actor
152     myMapper = vtkDataSetMapper::New();
153     myMapper->SetInput(myPlaneSource->GetOutput());
154
155     myActor = SALOME_Actor::New();
156     myActor->VisibilityOff();
157     myActor->PickableOff();
158     myActor->SetInfinitive(true);
159     myActor->SetMapper(myMapper);
160
161     vtkProperty* aProp = vtkProperty::New();
162     float anRGB[3];
163     anRGB[0] = VISU::GetFloat("SMESH:SettingsFillColorRed", 0)/255.;
164     anRGB[1] = VISU::GetFloat("SMESH:SettingsFillColorGreen", 170)/255.;
165     anRGB[2] = VISU::GetFloat("SMESH:SettingsFillColorBlue", 255)/255.;
166     aProp->SetColor(anRGB[0],anRGB[1],anRGB[2]);
167     aProp->SetOpacity(0.75);
168     myActor->SetProperty(aProp);
169     aProp->Delete();
170
171     vtkProperty* aBackProp = vtkProperty::New();
172     anRGB[0] = VISU::GetFloat("SMESH:SettingsBackFaceColorRed", 0)/255.;
173     anRGB[1] = VISU::GetFloat("SMESH:SettingsBackFaceColorGreen", 0)/255.;
174     anRGB[2] = VISU::GetFloat("SMESH:SettingsBackFaceColorBlue", 255)/255.;
175     aBackProp->SetColor(anRGB[0],anRGB[1],anRGB[2]);
176     aBackProp->SetOpacity(0.75);
177     myActor->SetBackfaceProperty(aBackProp);
178     aBackProp->Delete();
179   }
180
181   ~OrientedPlane()
182   {
183     if (myViewWindow)
184       myViewWindow->RemoveActor(myActor);
185
186     myActor->Delete();
187
188     myMapper->RemoveAllInputs();
189     myMapper->Delete();
190
191     myPlaneSource->UnRegisterAllOutputs();
192     myPlaneSource->Delete();
193   };
194
195 private:
196   // Not implemented.
197   OrientedPlane(const OrientedPlane&);
198   void operator=(const OrientedPlane&);
199 };
200
201 struct TSetVisiblity {
202   TSetVisiblity(int theIsVisible): myIsVisible(theIsVisible){}
203   void operator()(VISU::TVTKPlane& theOrientedPlane){
204     theOrientedPlane->myActor->SetVisibility(myIsVisible);
205   }
206   int myIsVisible;
207 };
208
209 //=================================================================================
210 // class    : VisuGUI_ClippingDlg()
211 // purpose  :
212 //
213 //=================================================================================
214 VisuGUI_ClippingDlg::VisuGUI_ClippingDlg (VisuGUI* theModule,
215                                           const char* name,
216                                           bool modal,
217                                           WFlags fl)
218   : QDialog(VISU::GetDesktop(theModule), name, modal, WStyle_Customize |
219             WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu | WDestructiveClose),
220   mySelectionMgr(VISU::GetSelectionMgr(theModule)),
221   myVisuGUI(theModule)
222 {
223   if (!name)
224     setName("VisuGUI_ClippingDlg");
225   setCaption(tr("TITLE"));
226   setSizeGripEnabled(TRUE);
227   QGridLayout* VisuGUI_ClippingDlgLayout = new QGridLayout(this);
228   VisuGUI_ClippingDlgLayout->setSpacing(6);
229   VisuGUI_ClippingDlgLayout->setMargin(11);
230
231   // Controls for selecting, creating, deleting planes
232   QGroupBox* GroupPlanes = new QGroupBox (this, "GroupPlanes");
233   GroupPlanes->setTitle(tr("GRP_PLANES"));
234   GroupPlanes->setColumnLayout(0, Qt::Vertical);
235   GroupPlanes->layout()->setSpacing(0);
236   GroupPlanes->layout()->setMargin(0);
237   QGridLayout* GroupPlanesLayout = new QGridLayout (GroupPlanes->layout());
238   GroupPlanesLayout->setAlignment(Qt::AlignTop);
239   GroupPlanesLayout->setSpacing(6);
240   GroupPlanesLayout->setMargin(11);
241
242   ComboBoxPlanes = new QComboBox (GroupPlanes, "ComboBoxPlanes");
243   GroupPlanesLayout->addWidget(ComboBoxPlanes, 0, 0);
244
245   QSpacerItem* spacerGP = new QSpacerItem (20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
246   GroupPlanesLayout->addItem(spacerGP, 0, 1);
247
248   buttonNew = new QPushButton (GroupPlanes, "buttonNew");
249   buttonNew->setText(tr("BUT_NEW"));
250   GroupPlanesLayout->addWidget(buttonNew, 0, 2);
251
252   buttonDelete = new QPushButton(GroupPlanes, "buttonDelete");
253   buttonDelete->setText(tr("BUT_DELETE"));
254   GroupPlanesLayout->addWidget(buttonDelete, 0, 3);
255
256   // Controls for defining plane parameters
257
258   // Tab pane
259   QGroupBox* GroupParameters = new QGroupBox(this, "GroupParameters");
260   GroupParameters->setTitle(tr("GRP_PARAMETERS"));
261   GroupParameters->setColumnLayout(0, Qt::Vertical);
262   GroupParameters->layout()->setSpacing(0);
263   GroupParameters->layout()->setMargin(0);
264   QGridLayout* GroupParametersLayout = new QGridLayout (GroupParameters->layout());
265   GroupParametersLayout->setAlignment(Qt::AlignTop);
266   GroupParametersLayout->setSpacing(6);
267   GroupParametersLayout->setMargin(11);
268
269   TabPane = new QTabWidget (GroupParameters);
270   TabPane->addTab(createParamsTab()   , tr("TAB_NON_STRUCTURED"));
271   TabPane->addTab(createIJKParamsTab(), tr("TAB_IJK_STRUCTURED"));
272   GroupParametersLayout->addWidget(TabPane, 0, 0);
273
274   // "Show preview" and "Auto Apply" check boxes
275
276   PreviewCheckBox = new QCheckBox (tr("SHOW_PREVIEW_CHK"), this);
277   PreviewCheckBox->setChecked(true);
278
279   AutoApplyCheckBox = new QCheckBox (tr("AUTO_APPLY_CHK"), this);
280   AutoApplyCheckBox->setChecked(false);
281
282   // Controls for "Ok", "Apply" and "Close" button
283   QGroupBox* GroupButtons = new QGroupBox (this, "GroupButtons");
284   GroupButtons->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)7,
285                                           (QSizePolicy::SizeType)0, 0, 0,
286                                           GroupButtons->sizePolicy().hasHeightForWidth()));
287   GroupButtons->setGeometry(QRect(10, 10, 281, 48));
288   //GroupButtons->setTitle(tr(""));
289   GroupButtons->setColumnLayout(0, Qt::Vertical);
290   GroupButtons->layout()->setSpacing(0);
291   GroupButtons->layout()->setMargin(0);
292   QGridLayout* GroupButtonsLayout = new QGridLayout (GroupButtons->layout());
293   GroupButtonsLayout->setAlignment(Qt::AlignTop);
294   GroupButtonsLayout->setSpacing(6);
295   GroupButtonsLayout->setMargin(11);
296   buttonCancel = new QPushButton (GroupButtons, "buttonCancel");
297   buttonCancel->setText(tr("BUT_CLOSE"));
298   buttonCancel->setAutoDefault(TRUE);
299   GroupButtonsLayout->addWidget(buttonCancel, 0, 3);
300   buttonApply = new QPushButton (GroupButtons, "buttonApply");
301   buttonApply->setText(tr("BUT_APPLY"));
302   buttonApply->setAutoDefault(TRUE);
303   GroupButtonsLayout->addWidget(buttonApply, 0, 1);
304   QSpacerItem* spacer_9 = new QSpacerItem (20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
305   GroupButtonsLayout->addItem(spacer_9, 0, 2);
306   buttonOk = new QPushButton (GroupButtons, "buttonOk");
307   buttonOk->setText(tr("BUT_OK"));
308   buttonOk->setAutoDefault(TRUE);
309   buttonOk->setDefault(TRUE);
310   GroupButtonsLayout->addWidget(buttonOk, 0, 0);
311
312   VisuGUI_ClippingDlgLayout->addMultiCellWidget(GroupPlanes,     0, 0, 0, 1);
313   VisuGUI_ClippingDlgLayout->addMultiCellWidget(GroupParameters, 1, 1, 0, 1);
314   VisuGUI_ClippingDlgLayout->addWidget(PreviewCheckBox,          2,    0);
315   VisuGUI_ClippingDlgLayout->addWidget(AutoApplyCheckBox,        2,    1);
316   VisuGUI_ClippingDlgLayout->addMultiCellWidget(GroupButtons,    3, 3, 0, 1);
317
318   // Initial state
319   VISU::RangeStepAndValidator(SpinBoxDistance, 0.0, 1.0, 0.01, 3);
320   VISU::RangeStepAndValidator(SpinBoxRot1, -180.0, 180.0, 1, 3);
321   VISU::RangeStepAndValidator(SpinBoxRot2, -180.0, 180.0, 1, 3);
322
323   ComboBoxOrientation->insertItem(tr("PARALLEL_XOY_COMBO_ITEM"));
324   ComboBoxOrientation->insertItem(tr("PARALLEL_YOZ_COMBO_ITEM"));
325   ComboBoxOrientation->insertItem(tr("PARALLEL_ZOX_COMBO_ITEM"));
326
327   SpinBoxDistance->setValue(0.5);
328
329   myPrs3d = 0;
330   myIsSelectPlane = false;
331   onSelectionChanged();
332
333   // signals and slots connections :
334   connect(ComboBoxPlanes, SIGNAL(activated(int)), this, SLOT(onSelectPlane(int)));
335   connect(buttonNew, SIGNAL(clicked()), this, SLOT(ClickOnNew()));
336   connect(buttonDelete, SIGNAL(clicked()), this, SLOT(ClickOnDelete()));
337   connect(ComboBoxOrientation, SIGNAL(activated(int)), this, SLOT(onSelectOrientation(int)));
338   connect(SpinBoxDistance, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam()));
339   connect(SpinBoxRot1, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam()));
340   connect(SpinBoxRot2, SIGNAL(valueChanged(double)), this, SLOT(SetCurrentPlaneParam()));
341   connect(ButtonGroupIJKAxis, SIGNAL(clicked(int)), this, SLOT(onIJKAxisChanged(int)));
342   connect(SpinBoxIJKIndex, SIGNAL(valueChanged(int)), this, SLOT(SetCurrentPlaneIJKParam()));
343   connect(CheckBoxIJKPlaneReverse, SIGNAL(toggled(bool)), this, SLOT(SetCurrentPlaneIJKParam()));
344   connect(TabPane, SIGNAL(currentChanged (QWidget*)), this, SLOT(onTabChanged(QWidget*)));
345
346   connect(PreviewCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnPreviewToggle(bool)));
347   connect(AutoApplyCheckBox, SIGNAL(toggled(bool)), this, SLOT(ClickOnApply()));
348   connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk()));
349   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(ClickOnCancel()));
350   connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply()));
351   connect(myVisuGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnOk()));
352   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(onSelectionChanged()));
353   /* to close dialog if study frame change */
354   connect(myVisuGUI, SIGNAL(SignalStudyFrameChanged()), this, SLOT(ClickOnCancel()));
355
356   this->show();
357 }
358
359 //=================================================================================
360 // function : ~VisuGUI_ClippingDlg()
361 // purpose  :
362 //=================================================================================
363 VisuGUI_ClippingDlg::~VisuGUI_ClippingDlg()
364 {
365   // no need to delete child widgets, Qt does it all for us
366   std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisiblity(false));
367   VISU::RenderViewWindow(VISU::GetViewWindow(myVisuGUI));
368 }
369
370 //=================================================================================
371 // function : createParamsTab
372 // purpose  :
373 //=================================================================================
374 QWidget* VisuGUI_ClippingDlg::createParamsTab()
375 {
376   QFrame* GroupParameters = new QFrame(this);
377   QGridLayout* GroupParametersLayout = new QGridLayout(GroupParameters);
378   GroupParametersLayout->setAlignment(Qt::AlignTop);
379   GroupParametersLayout->setSpacing(6);
380   GroupParametersLayout->setMargin(11);
381
382   TextLabelOrientation = new QLabel(GroupParameters, "TextLabelOrientation");
383   TextLabelOrientation->setText(tr("LBL_ORIENTATION"));
384   GroupParametersLayout->addWidget(TextLabelOrientation, 0, 0);
385
386   ComboBoxOrientation = new QComboBox(GroupParameters, "ComboBoxOrientation");
387   GroupParametersLayout->addWidget(ComboBoxOrientation, 0, 1);
388
389   TextLabelDistance = new QLabel(GroupParameters, "TextLabelDistance");
390   TextLabelDistance->setText(tr("LBL_DISTANCE"));
391   GroupParametersLayout->addWidget(TextLabelDistance, 1, 0);
392
393   SpinBoxDistance = new QtxDblSpinBox(GroupParameters, "SpinBoxDistance");
394   GroupParametersLayout->addWidget(SpinBoxDistance, 1, 1);
395
396   TextLabelRot1 = new QLabel(GroupParameters, "TextLabelRot1");
397   TextLabelRot1->setText(tr("LBL_ROTATION_YZ"));
398   GroupParametersLayout->addWidget(TextLabelRot1, 2, 0);
399
400   SpinBoxRot1 = new QtxDblSpinBox(GroupParameters, "SpinBoxRot1");
401   GroupParametersLayout->addWidget(SpinBoxRot1, 2, 1);
402
403   TextLabelRot2 = new QLabel(GroupParameters, "TextLabelRot2");
404   TextLabelRot2->setText(tr("LBL_ROTATION_XZ"));
405   GroupParametersLayout->addWidget(TextLabelRot2, 3, 0);
406
407   SpinBoxRot2 = new QtxDblSpinBox(GroupParameters, "SpinBoxRot2");
408   GroupParametersLayout->addWidget(SpinBoxRot2, 3, 1);
409
410   return GroupParameters;
411 }
412
413 //=================================================================================
414 // function : createIJKParamsTab
415 // purpose  :
416 //=================================================================================
417 QWidget* VisuGUI_ClippingDlg::createIJKParamsTab()
418 {
419   // tab layout
420   WidgetIJKTab = new QFrame(this);
421   QGridLayout* IJKParametersLayout = new QGridLayout(WidgetIJKTab);
422   IJKParametersLayout->setAlignment(Qt::AlignTop);
423   IJKParametersLayout->setSpacing(6);
424   IJKParametersLayout->setMargin(11);
425
426   // Axis group
427   ButtonGroupIJKAxis = new QHButtonGroup (tr("GRP_IJK_AXIS"), WidgetIJKTab);
428   new QRadioButton (tr("I_RADIO_BTN"), ButtonGroupIJKAxis);  // 0
429   new QRadioButton (tr("J_RADIO_BTN"), ButtonGroupIJKAxis);  // 1
430   new QRadioButton (tr("K_RADIO_BTN"), ButtonGroupIJKAxis);  // 2
431   ButtonGroupIJKAxis->setButton(0);
432
433   // Index
434   TextLabelIJKIndex = new QLabel(WidgetIJKTab, "TextLabelIJKIndex");
435   TextLabelIJKIndex->setText(tr("LBL_IJK_INDEX"));
436   SpinBoxIJKIndex = new QSpinBox(WidgetIJKTab, "SpinBoxIJKIndex");
437
438   // Orientation
439   CheckBoxIJKPlaneReverse = new QCheckBox (tr("REVERSE_NORMAL_CHK"), WidgetIJKTab);
440   CheckBoxIJKPlaneReverse->setChecked(false);
441
442   IJKParametersLayout->addMultiCellWidget(ButtonGroupIJKAxis, 0, 0, 0, 1);
443   IJKParametersLayout->addWidget(TextLabelIJKIndex,          1, 0);
444   IJKParametersLayout->addWidget(SpinBoxIJKIndex,            1, 1);
445   IJKParametersLayout->addWidget(CheckBoxIJKPlaneReverse, 2, 0);
446
447   return WidgetIJKTab;
448 }
449
450 //=================================================================================
451 // function : ClickOnApply()
452 // purpose  :
453 //=================================================================================
454 void VisuGUI_ClippingDlg::ClickOnApply()
455 {
456   if (!myPrs3d)
457     return;
458
459   if (SVTK_ViewWindow* aViewWindow = VISU::GetViewWindow(myVisuGUI)) {
460     SUIT_OverrideCursor wc;
461
462     myPrs3d->RemoveAllClippingPlanes();
463
464     VISU::TPlanes::iterator anIter = myPlanes.begin();
465     for (;anIter != myPlanes.end();anIter++) {
466       OrientedPlane* anOrientedPlane = OrientedPlane::New(aViewWindow);
467       anOrientedPlane->ShallowCopy(anIter->GetPointer());
468       myPrs3d->AddClippingPlane(anOrientedPlane);
469       anOrientedPlane->Delete();
470     }
471
472     VISU::RenderViewWindow(aViewWindow);
473   }
474 }
475
476 //=================================================================================
477 // function : ClickOnOk()
478 // purpose  :
479 //=================================================================================
480 void VisuGUI_ClippingDlg::ClickOnOk()
481 {
482   ClickOnApply();
483   ClickOnCancel();
484 }
485
486 //=================================================================================
487 // function : ClickOnCancel()
488 // purpose  :
489 //=================================================================================
490 void VisuGUI_ClippingDlg::ClickOnCancel()
491 {
492   close();
493 }
494
495 //=================================================================================
496 // function : onSelectionChanged()
497 // purpose  : Called when selection is changed
498 //=================================================================================
499 void VisuGUI_ClippingDlg::onSelectionChanged()
500 {
501   if (SVTK_ViewWindow* aViewWindow = VISU::GetViewWindow(myVisuGUI)) {
502     Handle(SALOME_InteractiveObject) anIO;
503     CORBA::Object_var anObject = VISU::GetSelectedObj(myVisuGUI, &anIO);
504     if (CORBA::is_nil(anObject)) return;
505     PortableServer::ServantBase_var aServant = VISU::GetServant(anObject);
506     if (!aServant.in()) return;
507
508     myPrs3d = dynamic_cast<VISU::Prs3d_i*>(aServant.in());
509     if (myPrs3d) {
510       std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisiblity(false));
511       myPlanes.clear();
512
513       float anOffset [3];
514       myPrs3d->GetOffset(anOffset);
515
516       vtkIdType anId = 0, anEnd = myPrs3d->GetNumberOfClippingPlanes();
517       for (; anId < anEnd; anId++) {
518         if (vtkImplicitFunction* aFunction = myPrs3d->GetClippingPlane(anId)) {
519           if (OrientedPlane* aPlane = OrientedPlane::SafeDownCast(aFunction)) {
520             OrientedPlane* anOrientedPlane = OrientedPlane::New(aViewWindow);
521             VISU::TVTKPlane aTVTKPlane(anOrientedPlane);
522             anOrientedPlane->Delete();
523             aTVTKPlane->ShallowCopy(aPlane);
524             aTVTKPlane->myActor->SetPosition(anOffset);
525             myPlanes.push_back(aTVTKPlane);
526           }
527         }
528       }
529
530       std::for_each(myPlanes.begin(),myPlanes.end(),
531                     TSetVisiblity(PreviewCheckBox->isChecked()));
532     }
533
534     // enable/disable IJK tab
535     TabPane->setTabEnabled(WidgetIJKTab, isStructured());
536     Sinchronize();
537     VISU::RenderViewWindow(aViewWindow);
538   }
539 }
540
541 //=================================================================================
542 // function : onSelectPlane()
543 // purpose  :
544 //=================================================================================
545 void VisuGUI_ClippingDlg::onSelectPlane(int theIndex)
546 {
547   if (!myPrs3d || myPlanes.empty())
548     return;
549
550   OrientedPlane* aPlane = myPlanes[theIndex].GetPointer();
551
552   // Orientation
553   VISU::Orientation anOrientation = aPlane->GetOrientation();
554
555   // Rotations
556   double aRot[2] = {aPlane->myAngle[0], aPlane->myAngle[1]};
557
558   // Set plane parameters in the dialog
559   myIsSelectPlane = true;
560   setDistance(aPlane->GetDistance());
561   setRotation(aRot[0], aRot[1]);
562   int item = 0;
563   switch (anOrientation) {
564   case VISU::XY: item = 0; break;
565   case VISU::YZ: item = 1; break;
566   case VISU::ZX: item = 2; break;
567   }
568   ComboBoxOrientation->setCurrentItem(item);
569
570   bool isIJK = (TabPane->currentPage() == WidgetIJKTab);
571   if (isIJK)
572     setIJKByNonStructured();
573   else
574     onSelectOrientation(item);
575
576   myIsSelectPlane = false;
577 }
578
579 //=================================================================================
580 // function : ClickOnNew()
581 // purpose  :
582 //=================================================================================
583 void VisuGUI_ClippingDlg::ClickOnNew()
584 {
585   if (!myPrs3d)
586     return;
587
588   if (SVTK_ViewWindow* aViewWindow = VISU::GetViewWindow(myVisuGUI)) {
589     OrientedPlane* aPlane = OrientedPlane::New(aViewWindow);
590     VISU::TVTKPlane aTVTKPlane(aPlane);
591     myPlanes.push_back(aTVTKPlane);
592
593     float anOffset [3];
594     myPrs3d->GetOffset(anOffset);
595     aTVTKPlane->myActor->SetPosition(anOffset);
596
597     if (PreviewCheckBox->isChecked())
598       aTVTKPlane->myActor->VisibilityOn();
599
600     Sinchronize();
601     SetCurrentPlaneParam();
602   }
603 }
604
605 //=================================================================================
606 // function : ClickOnDelete()
607 // purpose  :
608 //=================================================================================
609 void VisuGUI_ClippingDlg::ClickOnDelete()
610 {
611   if (!myPrs3d || myPlanes.empty())
612     return;
613
614   int aPlaneIndex = ComboBoxPlanes->currentItem();
615
616   VISU::TPlanes::iterator anIter = myPlanes.begin() + aPlaneIndex;
617   anIter->GetPointer()->myActor->SetVisibility(false);
618   myPlanes.erase(anIter);
619
620   if(AutoApplyCheckBox->isChecked())
621     ClickOnApply();
622
623   Sinchronize();
624   if (SVTK_ViewWindow* aViewWindow = VISU::GetViewWindow(myVisuGUI))
625     VISU::RenderViewWindow(aViewWindow);
626 }
627
628 //=================================================================================
629 // function : onSelectOrientation()
630 // purpose  :
631 //=================================================================================
632 void VisuGUI_ClippingDlg::onSelectOrientation(int theItem)
633 {
634   if (myPlanes.empty())
635     return;
636
637   if      (theItem == 0) {
638     TextLabelRot1->setText(tr("LBL_ROTATION_YZ"));
639     TextLabelRot2->setText(tr("LBL_ROTATION_XZ"));
640   }
641   else if (theItem == 1) {
642     TextLabelRot1->setText(tr("LBL_ROTATION_ZX"));
643     TextLabelRot2->setText(tr("LBL_ROTATION_YX"));
644   }
645   else if (theItem == 2) {
646     TextLabelRot1->setText(tr("LBL_ROTATION_XY"));
647     TextLabelRot2->setText(tr("LBL_ROTATION_ZY"));
648   }
649
650   if((QComboBox*)sender() == ComboBoxOrientation)
651     SetCurrentPlaneParam();
652 }
653
654 //=================================================================================
655 // function : Sinchronize()
656 // purpose  : update control values according to plane selection
657 //=================================================================================
658 void VisuGUI_ClippingDlg::Sinchronize()
659 {
660   int aNbPlanes = myPlanes.size();
661   ComboBoxPlanes->clear();
662
663   QString aName;
664   for (int i = 1; i<=aNbPlanes; i++) {
665     aName = QString(tr("PLANES_COMBO_ITEM_i")).arg(i);
666     ComboBoxPlanes->insertItem(aName);
667   }
668
669   int aPos = ComboBoxPlanes->count() - 1;
670   ComboBoxPlanes->setCurrentItem(aPos);
671
672   bool anIsControlsEnable = (aPos >= 0);
673   if (anIsControlsEnable) {
674     onSelectPlane(aPos);
675   } else {
676     ComboBoxPlanes->insertItem(tr("PLANES_COMBO_ITEM_no"));
677     SpinBoxRot1->setValue(0.0);
678     SpinBoxRot2->setValue(0.0);
679     SpinBoxDistance->setValue(0.5);
680   }
681
682   buttonDelete           ->setEnabled(anIsControlsEnable);
683   buttonApply            ->setEnabled(anIsControlsEnable);
684   PreviewCheckBox        ->setEnabled(anIsControlsEnable);
685   AutoApplyCheckBox      ->setEnabled(anIsControlsEnable);
686
687   ComboBoxOrientation    ->setEnabled(anIsControlsEnable);
688   SpinBoxDistance        ->setEnabled(anIsControlsEnable);
689   SpinBoxRot1            ->setEnabled(anIsControlsEnable);
690   SpinBoxRot2            ->setEnabled(anIsControlsEnable);
691
692   ButtonGroupIJKAxis     ->setEnabled(anIsControlsEnable);
693   SpinBoxIJKIndex        ->setEnabled(anIsControlsEnable);
694   CheckBoxIJKPlaneReverse->setEnabled(anIsControlsEnable);
695 }
696
697 //=================================================================================
698 // function : setRotation()
699 // purpose  :
700 //=================================================================================
701 void VisuGUI_ClippingDlg::setRotation(const double theRot1, const double theRot2)
702 {
703   SpinBoxRot1->setValue(theRot1);
704   SpinBoxRot2->setValue(theRot2);
705 }
706
707 //=================================================================================
708 // function : SetCurrentPlaneParam()
709 // purpose  :
710 //=================================================================================
711 void VisuGUI_ClippingDlg::SetCurrentPlaneParam()
712 {
713   if (myPlanes.empty() || myIsSelectPlane)
714     return;
715
716   int aCurPlaneIndex = ComboBoxPlanes->currentItem();
717
718   OrientedPlane* aPlane = myPlanes[aCurPlaneIndex].GetPointer();
719
720   float aNormal[3];
721   VISU::Orientation anOrientation;
722   float aDir[3][3] = {{0, 0, 0}, {0, 0, 0}};
723   {
724     static double aCoeff = vtkMath::Pi()/180.0;
725
726     float aRot[2] = {getRotation1(), getRotation2()};
727     aPlane->myAngle[0] = aRot[0];
728     aPlane->myAngle[1] = aRot[1];
729
730     float anU[2] = {cos(aCoeff*aRot[0]), cos(aCoeff*aRot[1])};
731     float aV[2] = {sqrt(1.0-anU[0]*anU[0]), sqrt(1.0-anU[1]*anU[1])};
732     aV[0] = aRot[0] > 0? aV[0]: -aV[0];
733     aV[1] = aRot[1] > 0? aV[1]: -aV[1];
734
735     switch (ComboBoxOrientation->currentItem()) {
736     case 0:
737       anOrientation = VISU::XY;
738
739       aDir[0][1] = anU[0];
740       aDir[0][2] = aV[0];
741
742       aDir[1][0] = anU[1];
743       aDir[1][2] = aV[1];
744
745       break;
746     case 1:
747       anOrientation = VISU::YZ;
748
749       aDir[0][2] = anU[0];
750       aDir[0][0] = aV[0];
751
752       aDir[1][1] = anU[1];
753       aDir[1][0] = aV[1];
754
755       break;
756     case 2:
757       anOrientation = VISU::ZX;
758
759       aDir[0][0] = anU[0];
760       aDir[0][1] = aV[0];
761
762       aDir[1][2] = anU[1];
763       aDir[1][1] = aV[1];
764
765       break;
766     }
767
768     vtkMath::Cross(aDir[1],aDir[0],aNormal);
769     vtkMath::Normalize(aNormal);
770     vtkMath::Cross(aNormal,aDir[1],aDir[0]);
771   }
772
773   aPlane->SetOrientation(anOrientation);
774   aPlane->SetDistance(getDistance());
775
776   myPrs3d->SetPlaneParam(aNormal, 1. - getDistance(), aPlane);
777
778   vtkDataSet* aDataSet = myPrs3d->GetInput();
779   float *aPnt = aDataSet->GetCenter();
780
781   float* anOrigin = aPlane->GetOrigin();
782   float aDel = aDataSet->GetLength()/2.0;
783
784   float aDelta[2][3] = {{aDir[0][0]*aDel, aDir[0][1]*aDel, aDir[0][2]*aDel},
785                         {aDir[1][0]*aDel, aDir[1][1]*aDel, aDir[1][2]*aDel}};
786   float aParam, aPnt0[3], aPnt1[3], aPnt2[3];
787
788   float aPnt01[3] = {aPnt[0] - aDelta[0][0] - aDelta[1][0],
789                      aPnt[1] - aDelta[0][1] - aDelta[1][1],
790                      aPnt[2] - aDelta[0][2] - aDelta[1][2]};
791   float aPnt02[3] = {aPnt01[0] + aNormal[0],
792                       aPnt01[1] + aNormal[1],
793                       aPnt01[2] + aNormal[2]};
794   vtkPlane::IntersectWithLine(aPnt01,aPnt02,aNormal,anOrigin,aParam,aPnt0);
795
796   float aPnt11[3] = {aPnt[0] - aDelta[0][0] + aDelta[1][0],
797                      aPnt[1] - aDelta[0][1] + aDelta[1][1],
798                      aPnt[2] - aDelta[0][2] + aDelta[1][2]};
799   float aPnt12[3] = {aPnt11[0] + aNormal[0],
800                      aPnt11[1] + aNormal[1],
801                      aPnt11[2] + aNormal[2]};
802   vtkPlane::IntersectWithLine(aPnt11,aPnt12,aNormal,anOrigin,aParam,aPnt1);
803
804   float aPnt21[3] = {aPnt[0] + aDelta[0][0] - aDelta[1][0],
805                      aPnt[1] + aDelta[0][1] - aDelta[1][1],
806                      aPnt[2] + aDelta[0][2] - aDelta[1][2]};
807   float aPnt22[3] = {aPnt21[0] + aNormal[0],
808                      aPnt21[1] + aNormal[1],
809                      aPnt21[2] + aNormal[2]};
810   vtkPlane::IntersectWithLine(aPnt21,aPnt22,aNormal,anOrigin,aParam,aPnt2);
811
812   vtkPlaneSource* aPlaneSource = aPlane->myPlaneSource;
813   aPlaneSource->SetNormal(aNormal[0],aNormal[1],aNormal[2]);
814   aPlaneSource->SetOrigin(aPnt0[0],aPnt0[1],aPnt0[2]);
815   aPlaneSource->SetPoint1(aPnt1[0],aPnt1[1],aPnt1[2]);
816   aPlaneSource->SetPoint2(aPnt2[0],aPnt2[1],aPnt2[2]);
817
818   if (AutoApplyCheckBox->isChecked())
819     ClickOnApply();
820
821   if (SVTK_ViewWindow* vw = VISU::GetViewWindow(myVisuGUI))
822     VISU::RenderViewWindow(vw);
823 }
824
825 //=================================================================================
826 // function : onTabChanged
827 // purpose  :
828 //=================================================================================
829 void VisuGUI_ClippingDlg::onTabChanged(QWidget* newTab)
830 {
831   if (newTab == WidgetIJKTab) // IJK
832     setIJKByNonStructured();
833   else {
834     // set correct labels of rotation spin boxes
835     onSelectOrientation(ComboBoxOrientation->currentItem());
836   }
837 }
838
839 //=================================================================================
840 // function : SetCurrentPlaneIJKParam
841 // purpose  : set non structured parameters by IJK parameters
842 //=================================================================================
843 void VisuGUI_ClippingDlg::SetCurrentPlaneIJKParam()
844 {
845   if (myPlanes.empty() || myIsSelectPlane || !WidgetIJKTab->isEnabled())
846     return;
847
848   VISU::Result_i* result = myPrs3d ? myPrs3d->GetResult() : 0;
849   if (!result)
850     return;
851
852   // get axis data
853   int i, axId = ButtonGroupIJKAxis->id (ButtonGroupIJKAxis->selected());
854   VISU::Result_i::TAxis axis = (VISU::Result_i::TAxis) axId;
855   gp_Dir dir;
856   const vector<float> * values =
857     result->GetAxisInfo(myPrs3d->GetMeshName(), axis, dir);
858   if (!values)
859     return;
860
861   // find distance;
862   int index = SpinBoxIJKIndex->value();
863   float distance = 0;
864   if (index < values->size())
865     distance = (*values)[ index ];
866
867   // find id of axis closest to dir
868   // 0  || X-Y - axis Z
869   // 1  || Y-Z - azis X
870   // 2  || Z-X - axiz Y
871   double cos[3] = { gp::DZ() * dir, gp::DX() * dir, gp::DY() * dir };
872   double maxCos = 0;
873   for (i = 0; i < 3; ++i) {
874     if (Abs(cos[ i ]) > Abs (maxCos)) {
875       maxCos = cos[ i ];
876       axId = i;
877     }
878   }
879   // find rotation angles
880   float angle[2];
881   int rotId[2] = {
882     (axId == 0) ? 2 : axId - 1,
883     (axId == 2) ? 0 : axId + 1
884     };
885   static double aCoeff = 180.0/vtkMath::Pi();
886   for (i = 0; i < 2; ++i) {
887     float cosin = cos[ rotId[ i ]];
888     if (maxCos < 0)
889       cosin = -cosin;
890     angle[ i ] = asin(cosin) * aCoeff;
891     if (maxCos < 0)
892       angle[ i ] += 180. * (angle[ i ] < 0 ? 1. : -1.);
893   }
894   if (CheckBoxIJKPlaneReverse->isChecked()) {
895     angle[ 0 ] += 180. * (angle[ 0 ] < 0 ? 1. : -1.);
896     distance = 1. - distance;
897   }
898   if (maxCos < 0)
899     distance = 1. - distance;
900
901   // set paramerets
902   myIsSelectPlane = true;
903   ComboBoxOrientation->setCurrentItem(axId);
904   setRotation(-angle[0], -angle[1]);
905   setDistance(distance);
906   myIsSelectPlane = false;
907
908   SetCurrentPlaneParam();
909 }
910
911 //=================================================================================
912 // function : setIJKByNonStructured
913 // purpose  : convert current non structured parameters to structured ones
914 //=================================================================================
915 void VisuGUI_ClippingDlg::setIJKByNonStructured()
916 {
917   if (!myPrs3d || myPlanes.empty() || !myPrs3d->GetResult())
918     return;
919
920   // get plane normal
921   int planeIndex = ComboBoxPlanes->currentItem();
922   OrientedPlane* plane = myPlanes[ planeIndex ].GetPointer();
923   vtkPlaneSource* planeSource = plane->myPlaneSource;
924   float * planeNormal = planeSource->GetNormal();
925   gp_Dir normal(planeNormal[0], planeNormal[1], planeNormal[2]);
926
927   // find a grid axis most co-directed with plane normal
928   // and cartesian axis most co-directed with plane normal
929   int i, maxAx = 0, gridAxId = 0;
930   gp_Dir dir, gridDir;
931   double maxDot = 0;
932   const vector<float> *curValues, *values = 0;
933   VISU::Result_i* result = myPrs3d->GetResult();
934   for (i = 0; i < 3; ++i) {
935     VISU::Result_i::TAxis axis = (VISU::Result_i::TAxis) i;
936     curValues = result->GetAxisInfo(myPrs3d->GetMeshName(), axis, dir);
937     if (curValues) {
938       double dot = normal * dir;
939       if (Abs(dot) > Abs(maxDot)) {
940         maxDot = dot;
941         gridDir = dir;
942         values = curValues;
943         gridAxId = i;
944       }
945     }
946     if (Abs (planeNormal[ maxAx ]) < Abs (planeNormal[ i ]))
947       maxAx = i;
948   }
949   gp_XYZ axDir(0,0,0);
950   axDir.SetCoord(maxAx + 1, 1.);
951
952   // find index value
953   double v = SpinBoxDistance->value();
954   // reverse value?
955   bool reverse = (normal * axDir < 0); // normal and axis are opposite
956   if (gridDir * axDir < 0) // grid dir and axis are opposite
957     reverse = !reverse;
958   if (reverse)
959     v = 1. - v;
960   for (i = 0; i < values->size(); ++i)
961     if ((*values)[ i ] > v)
962       break;
963   if (i == values->size())
964     --i;
965   if (i != 0 && (*values)[ i ] - v > v - (*values)[ i - 1])
966     --i;
967
968   // set control values
969   myIsSelectPlane = true;
970   CheckBoxIJKPlaneReverse->setChecked(normal * axDir < 0);
971   SpinBoxIJKIndex->setValue(i);
972   ButtonGroupIJKAxis->setButton(gridAxId);
973   onIJKAxisChanged(gridAxId); // update label and range of index
974   myIsSelectPlane = false;
975
976   SetCurrentPlaneIJKParam();
977 }
978
979 //=================================================================================
980 // function : isStructured
981 // purpose  : return true if mesh is structured
982 //=================================================================================
983 bool VisuGUI_ClippingDlg::isStructured() const
984 {
985   VISU::Result_i* result = myPrs3d ? myPrs3d->GetResult() : 0;
986   if (result) {
987     gp_Dir dir;
988     return result->GetAxisInfo(myPrs3d->GetMeshName(),
989                                VISU::Result_i::AXIS_X,
990                                dir);
991   }
992   return false;
993 }
994
995 //=================================================================================
996 // function : onIJKAxisChanged
997 // purpose  : update Index range and call SetCurrentPlaneParam()
998 //=================================================================================
999 void VisuGUI_ClippingDlg::onIJKAxisChanged(int axisId)
1000 {
1001   // set index range
1002   int maxIndex = 0;
1003   VISU::Result_i* result = myPrs3d ? myPrs3d->GetResult() : 0;
1004   if (result) {
1005     VISU::Result_i::TAxis axis = (VISU::Result_i::TAxis) axisId;
1006     gp_Dir dir;
1007     const vector<float> * indices = result->GetAxisInfo(myPrs3d->GetMeshName(),
1008                                                         axis, dir);
1009     if (indices)
1010       maxIndex = indices->size() - 1;
1011   }
1012   QString text = tr("LBL_IJK_INDEX_TO_arg").arg(maxIndex);
1013   TextLabelIJKIndex->setText(text);
1014   SpinBoxIJKIndex->setRange(0, maxIndex);
1015
1016   if (SpinBoxIJKIndex->value() > maxIndex)
1017     SpinBoxIJKIndex->setValue(0);
1018
1019   SetCurrentPlaneIJKParam();
1020 }
1021
1022 //=================================================================================
1023 // function : OnPreviewToggle()
1024 // purpose  :
1025 //=================================================================================
1026 void VisuGUI_ClippingDlg::OnPreviewToggle (bool theIsToggled)
1027 {
1028   std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisiblity(theIsToggled));
1029   if (SVTK_ViewWindow* vw = VISU::GetViewWindow(myVisuGUI))
1030     VISU::RenderViewWindow(vw);
1031 }