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