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