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