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