Salome HOME
First step for the "21793: [CEA 625] Clipping : from coordinates or from bounding...
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ClippingDlg.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // SMESH SMESHGUI : GUI for SMESH component
24 // File   : SMESHGUI_ClippingDlg.cxx
25 // Author : Nicolas REJNERI, Open CASCADE S.A.S.
26 // SMESH includes
27 //
28 #include "SMESHGUI_ClippingDlg.h"
29
30 #include "SMESHGUI.h"
31 #include "SMESHGUI_Utils.h"
32 #include "SMESHGUI_VTKUtils.h"
33 #include "SMESHGUI_SpinBox.h"
34
35 #include <SMESH_Actor.h>
36 #include <SMESH_ActorUtils.h>
37
38 // SALOME GUI includes
39 #include <SUIT_Desktop.h>
40 #include <SUIT_Session.h>
41 #include <SUIT_OverrideCursor.h>
42 #include <SUIT_MessageBox.h>
43 #include <SUIT_ResourceMgr.h>
44 #include <SUIT_ViewManager.h>
45
46 #include <SALOME_ListIO.hxx>
47
48 #include <SalomeApp_Study.h>
49
50 #include <LightApp_Application.h>
51
52 #include <VTKViewer_Algorithm.h>
53
54 #include <SVTK_ViewWindow.h>
55 #include <SVTK_RenderWindowInteractor.h>
56
57 // Qt includes
58 #include <QLabel>
59 #include <QPushButton>
60 #include <QComboBox>
61 #include <QCheckBox>
62 #include <QVBoxLayout>
63 #include <QHBoxLayout>
64 #include <QGridLayout>
65 #include <QGroupBox>
66 #include <QKeyEvent>
67 #include <QListWidget>
68 #include <QStackedLayout>
69 #include <QSlider>
70 #include <QMenu>
71
72 // VTK includes
73 #include <vtkMath.h>
74 #include <vtkDataSet.h>
75 #include <vtkDataSetMapper.h>
76 #include <vtkPlaneSource.h>
77 #include <vtkProperty.h>
78 #include <vtkRenderer.h>
79 #include <vtkCallbackCommand.h>
80 #include <vtkImplicitPlaneWidget.h>
81
82 #include <math.h>
83
84 #define SPACING 6
85 #define MARGIN  11
86 #define SIZEFACTOR 1.1
87
88 /*!
89   Create new object of class OrientedPlane
90  */
91 SMESH::OrientedPlane* SMESH::OrientedPlane::New()
92 {
93   return new OrientedPlane();
94 }
95
96 /*!
97   Create new object of class OrientedPlane
98  */
99 SMESH::OrientedPlane* SMESH::OrientedPlane::New( SVTK_ViewWindow* theViewWindow )
100 {
101   return new OrientedPlane( theViewWindow );
102 }
103
104 /*!
105   Copy the object of class OrientedPlane
106  */
107 void SMESH::OrientedPlane::ShallowCopy( SMESH::OrientedPlane* theOrientedPlane )
108 {
109   SetNormal( theOrientedPlane->GetNormal() );
110   SetOrigin( theOrientedPlane->GetOrigin() );
111
112   myRelativeOrientation = theOrientedPlane->GetOrientation();
113   myDistance = theOrientedPlane->GetDistance();
114
115   IsOpenGLClipping = theOrientedPlane->IsOpenGLClipping;
116
117   myAngle[0] = theOrientedPlane->myAngle[0];
118   myAngle[1] = theOrientedPlane->myAngle[1];
119
120   myAbsoluteOrientation = theOrientedPlane->myAbsoluteOrientation;
121   X = theOrientedPlane->X;
122   Y = theOrientedPlane->Y;
123   Z = theOrientedPlane->Z;
124   Dx = theOrientedPlane->Dx;
125   Dy = theOrientedPlane->Dy;
126   Dz = theOrientedPlane->Dz;
127
128   PlaneMode = theOrientedPlane->PlaneMode;
129
130   myPlaneSource->SetNormal( theOrientedPlane->myPlaneSource->GetNormal() );
131   myPlaneSource->SetOrigin( theOrientedPlane->myPlaneSource->GetOrigin() );
132   myPlaneSource->SetPoint1( theOrientedPlane->myPlaneSource->GetPoint1() );
133   myPlaneSource->SetPoint2( theOrientedPlane->myPlaneSource->GetPoint2() );
134   myPlaneSource->Update();
135 }
136
137 /*!
138   Invert current clipping plane in contrary direction
139  */
140 SMESH::OrientedPlane* SMESH::OrientedPlane::InvertPlane()
141 {
142   OrientedPlane* aPlane = new OrientedPlane();
143   aPlane->ShallowCopy( this );
144   double* aNormal = aPlane->GetNormal();
145   for( int i=0; i<3; i++ )
146     aNormal[i] = -aNormal[i];
147   aPlane->SetNormal( aNormal );
148   return aPlane;
149 }
150
151 /*!
152   Constructor of class OrientedPlane
153  */
154 SMESH::OrientedPlane::OrientedPlane(SVTK_ViewWindow* theViewWindow):
155   myViewWindow(theViewWindow)
156 {
157   Init();
158   myViewWindow->AddActor(myActor, false, false); // don't adjust actors
159 }
160
161 /*!
162   Constructor of class OrientedPlane
163  */
164 SMESH::OrientedPlane::OrientedPlane():
165   myViewWindow(NULL)
166 {
167   Init();
168 }
169
170 /*!
171   Initialize parameters of class OrientedPlane
172  */
173 void SMESH::OrientedPlane::Init()
174 {
175   myPlaneSource = vtkPlaneSource::New();
176
177   PlaneMode = SMESH::Absolute;
178   X = Y = Z = 0.0;
179   Dx = Dy = Dz = 1.0;
180   myAbsoluteOrientation = 0; // CUSTOM
181   myRelativeOrientation = SMESH::XY;
182   myDistance = 0.5;
183   myAngle[0] = myAngle[1] = 0.0;
184   IsInvert = false;
185   IsOpenGLClipping = false;
186
187   // Create and display actor
188   myMapper = vtkDataSetMapper::New();
189   myMapper->SetInputConnection(myPlaneSource->GetOutputPort());
190
191   myActor = SALOME_Actor::New();
192   myActor->VisibilityOff();
193   myActor->PickableOff();
194   myActor->SetInfinitive(true);
195   myActor->SetMapper(myMapper);
196
197   QColor ffc, bfc;
198   int delta;
199   SMESH::GetColor( "SMESH", "fill_color", ffc, delta, "255, 170, 0|-100" ) ;
200  
201   vtkProperty* aProp = vtkProperty::New();
202   SMESH::GetColor( "SMESH", "fill_color", ffc, delta, "255, 170, 0|-100" ) ;
203   aProp->SetColor(ffc.red() / 255. , ffc.green() / 255. , ffc.blue() / 255.);
204   aProp->SetOpacity(0.75);
205   myActor->SetProperty(aProp);
206   aProp->Delete();
207
208   vtkProperty* aBackProp = vtkProperty::New();
209   bfc = Qtx::mainColorToSecondary(ffc, delta);
210   aBackProp->SetColor( bfc.red() / 255. , bfc.green() / 255. , bfc.blue() / 255.);
211   aBackProp->SetOpacity(0.75);
212   myActor->SetBackfaceProperty(aBackProp);
213   aBackProp->Delete();
214 }
215
216 /*!
217   Destructor of class OrientedPlane
218  */
219 SMESH::OrientedPlane::~OrientedPlane()
220 {
221   if (myViewWindow)
222     myViewWindow->RemoveActor(myActor);
223   myActor->Delete();
224     
225   myMapper->RemoveAllInputs();
226   myMapper->Delete();
227
228   // commented: porting to vtk 5.0
229   // myPlaneSource->UnRegisterAllOutputs();
230   myPlaneSource->Delete();
231 }
232
233 /*!
234   Definition of class ActorItem
235  */
236 class ActorItem : public QListWidgetItem
237 {
238 public:
239   ActorItem( SMESH_Actor* theActor, const QString& theName, QListWidget* theListWidget ) :
240     QListWidgetItem( theName, theListWidget ),
241     myActor( theActor ) {}
242
243   SMESH_Actor* getActor() const { return myActor; }
244
245 private:
246   SMESH_Actor* myActor;
247 };
248
249 /*!
250   Definition of class TSetVisibility
251  */
252 struct TSetVisibility {
253   // Set visibility of cutting plane
254   TSetVisibility(int theIsVisible): myIsVisible(theIsVisible){}
255   void operator()(SMESH::TPlaneData& thePlaneData){
256     bool anIsEmpty = thePlaneData.ActorList.empty();
257     thePlaneData.Plane.GetPointer()->myActor->SetVisibility(myIsVisible && !anIsEmpty);
258   }
259   int myIsVisible;
260 };
261
262 /*********************************************************************************
263  *********************      class SMESHGUI_ClippingDlg      *********************
264  *********************************************************************************/
265
266 /*!
267   Constructor
268 */
269 SMESHGUI_ClippingDlg::SMESHGUI_ClippingDlg( SMESHGUI* theModule, SVTK_ViewWindow* theViewWindow ):
270   QDialog( SMESH::GetDesktop(theModule) ),
271   mySMESHGUI(theModule),
272   myViewWindow(theViewWindow)
273 {
274   setModal( false );
275   setAttribute( Qt::WA_DeleteOnClose, true );
276   setWindowTitle(tr("SMESH_CLIPPING_TITLE"));
277   setSizeGripEnabled(true);
278
279   myPreviewWidget = vtkImplicitPlaneWidget::New();
280   myCallback = vtkCallbackCommand::New();
281   myCallback->SetClientData( this );
282   myCallback->SetCallback( SMESHGUI_ClippingDlg::ProcessEvents );
283   myPreviewWidget = createPreviewWidget();
284
285   myIsPreviewMoved = false;
286
287   QVBoxLayout* SMESHGUI_ClippingDlgLayout = new QVBoxLayout(this);
288   SMESHGUI_ClippingDlgLayout->setSpacing(SPACING);
289   SMESHGUI_ClippingDlgLayout->setMargin(MARGIN);
290
291   // Controls for selecting, creating, deleting planes
292   QGroupBox* GroupPlanes = new QGroupBox(tr("CLIP_PLANES"), this);
293   QGridLayout* GroupPlanesLayout = new QGridLayout(GroupPlanes);
294   GroupPlanesLayout->setSpacing(SPACING);
295   GroupPlanesLayout->setMargin(MARGIN);
296
297   ComboBoxPlanes = new QComboBox(GroupPlanes);
298
299   isOpenGLClipping = new QCheckBox( GroupPlanes );
300   isOpenGLClipping->setText( tr( "IS_OPENGL_CLIPPING" ) );
301
302   buttonNew = new QPushButton(tr("SMESH_BUT_NEW"), GroupPlanes);
303
304   MenuMode = new QMenu( "MenuMode", buttonNew );
305   MenuMode->addAction( tr( "ABSOLUTE" ), this, SLOT( onModeAbsolute() ) );
306   MenuMode->addAction( tr( "RELATIVE" ), this, SLOT( onModeRelative() ) );
307   buttonNew->setMenu( MenuMode );
308   CurrentMode = SMESH::Absolute;
309
310   buttonDelete = new QPushButton(tr("SMESH_BUT_DELETE"), GroupPlanes);
311
312   QLabel* aLabel = new QLabel(tr("MESHES_SUBMESHES_GROUPS"), GroupPlanes);
313
314   ActorList = new QListWidget(GroupPlanes);
315   ActorList->setSelectionMode(QAbstractItemView::SingleSelection);
316   
317   SelectAllCheckBox = new QCheckBox(tr("SELECT_ALL"), GroupPlanes);
318
319   GroupPlanesLayout->addWidget(ComboBoxPlanes,    0, 0);
320   GroupPlanesLayout->addWidget(isOpenGLClipping,  0, 1);
321   GroupPlanesLayout->addWidget(new QWidget(),     0, 2);
322   GroupPlanesLayout->addWidget(buttonNew,         0, 3);
323   GroupPlanesLayout->addWidget(buttonDelete,      0, 4);
324   GroupPlanesLayout->addWidget(aLabel,            1, 0, 1, 5);
325   GroupPlanesLayout->addWidget(ActorList,         2, 0, 1, 5);
326   GroupPlanesLayout->addWidget(SelectAllCheckBox, 3, 0, 1, 5);
327   GroupPlanesLayout->setColumnStretch( 1, 1 );
328
329   ModeStackedLayout = new QStackedLayout();
330
331   // Controls for defining plane parameters
332   /**********************   Mode Absolute   **********************/
333   /* Controls for absolute mode of clipping plane:
334      X, Y, Z - coordinates of the intersection of cutting plane and the three axes
335      Dx, Dy, Dz - components of normal to the cutting plane
336      Orientation - direction of cutting plane
337   */
338   const double min = -1e+7;
339   const double max =  1e+7;
340   const double step = 5;
341   const int precision = -7;
342
343   // Croup Point
344   QGroupBox* GroupAbsolutePoint = new QGroupBox( this );
345   GroupAbsolutePoint->setObjectName( "GroupPoint" );
346   GroupAbsolutePoint->setTitle( tr("BASE_POINT") );
347   QGridLayout* GroupPointLayout = new QGridLayout( GroupAbsolutePoint );
348   GroupPointLayout->setAlignment( Qt::AlignTop );
349   GroupPointLayout->setSpacing( 6 ); GroupPointLayout->setMargin( 11 );
350
351   TextLabelX = new QLabel( GroupAbsolutePoint );
352   TextLabelX->setObjectName( "TextLabelX" );
353   TextLabelX->setText( tr("X:") );
354   GroupPointLayout->addWidget( TextLabelX, 0, 0 );
355
356   SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
357   SpinBox_X->setObjectName("SpinBox_X" );
358   SpinBox_X->setPrecision( precision );
359   GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
360
361   TextLabelY = new QLabel( GroupAbsolutePoint );
362   TextLabelY->setObjectName( "TextLabelY" );
363   TextLabelY->setText( tr("Y:") );
364   GroupPointLayout->addWidget( TextLabelY, 0, 2 );
365
366   SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
367   SpinBox_Y->setObjectName("SpinBox_Y" );
368   SpinBox_Y->setPrecision( precision );
369   GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
370
371   TextLabelZ = new QLabel( GroupAbsolutePoint );
372   TextLabelZ->setObjectName( "TextLabelZ" );
373   TextLabelZ->setText( tr("Z:") );
374   GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
375
376   SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
377   SpinBox_Z->setObjectName("SpinBox_Z" );
378   SpinBox_Z->setPrecision( precision );
379   GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
380
381   resetButton  = new QPushButton( GroupAbsolutePoint );
382   resetButton->setObjectName( "resetButton" );
383   resetButton->setText( tr( "RESET"  ) );
384   GroupPointLayout->addWidget( resetButton, 0, 6 );
385
386   // Group Direction
387   GroupAbsoluteDirection = new QGroupBox( this );
388   GroupAbsoluteDirection->setObjectName( "GroupDirection" );
389   GroupAbsoluteDirection->setTitle( tr("DIRECTION") );
390   QGridLayout* GroupDirectionLayout = new QGridLayout( GroupAbsoluteDirection );
391   GroupDirectionLayout->setAlignment( Qt::AlignTop );
392   GroupDirectionLayout->setSpacing( 6 );
393   GroupDirectionLayout->setMargin( 11 );
394
395   TextLabelDx = new QLabel( GroupAbsoluteDirection );
396   TextLabelDx->setObjectName( "TextLabelDx" );
397   TextLabelDx->setText( tr("Dx:") );
398   GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
399
400   SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
401   SpinBox_Dx->setObjectName("SpinBox_Dx" );
402   SpinBox_Dx->setPrecision( precision );
403   GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
404
405   TextLabelDy = new QLabel( GroupAbsoluteDirection );
406   TextLabelDy->setObjectName( "TextLabelDy" );
407   TextLabelDy->setText( tr("Dy:") );
408   GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
409
410   SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
411   SpinBox_Dy->setObjectName("SpinBox_Dy" );
412   SpinBox_Dy->setPrecision( precision );
413   GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
414
415   TextLabelDz = new QLabel( GroupAbsoluteDirection );
416   TextLabelDz->setObjectName( "TextLabelDz" );
417   TextLabelDz->setText( tr("Dz:") );
418   GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
419
420   SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
421   SpinBox_Dz->setObjectName("SpinBox_Dz" );
422   SpinBox_Dz->setPrecision( precision );
423   GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
424
425   invertButton  = new QPushButton( GroupAbsoluteDirection );
426   invertButton->setObjectName( "invertButton" );
427   invertButton->setText( tr( "INVERT"  ) );
428   GroupDirectionLayout->addWidget( invertButton, 0, 6 );
429
430   CBAbsoluteOrientation = new QComboBox( GroupAbsoluteDirection );
431   CBAbsoluteOrientation->setObjectName( "AbsoluteOrientation" );
432   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "CUSTOM" ) );
433   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||X-Y" ) );
434   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Y-Z" ) );
435   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Z-X" ) );
436   GroupDirectionLayout->addWidget( CBAbsoluteOrientation, 1, 0, 1, 6 );
437
438   QVBoxLayout* ModeActiveLayout = new QVBoxLayout();
439   ModeActiveLayout->setMargin( 11 ); ModeActiveLayout->setSpacing( 6 );
440   ModeActiveLayout->addWidget( GroupAbsolutePoint );
441   ModeActiveLayout->addWidget( GroupAbsoluteDirection );
442
443   QWidget* ModeActiveWidget = new QWidget( this );
444   ModeActiveWidget->setLayout( ModeActiveLayout );
445
446   /**********************   Mode Relative   **********************/
447   /* Controls for relative mode of clipping plane:
448      Distance - Value from 0 to 1.
449      Specifies the distance from the minimum value in a given direction of bounding box to the current position
450      Rotation1, Rotation2 - turn angles of cutting plane in given directions
451      Orientation - direction of cutting plane
452   */
453   QGroupBox* GroupParameters = new QGroupBox( tr("SMESH_PARAMETERS"), this );
454   QGridLayout* GroupParametersLayout = new QGridLayout( GroupParameters );
455   GroupParametersLayout->setMargin( 11 ); GroupParametersLayout->setSpacing( 6 );
456
457   TextLabelOrientation = new QLabel( tr("SMESH_ORIENTATION"), GroupParameters);
458   TextLabelOrientation->setObjectName( "TextLabelOrientation" );
459   GroupParametersLayout->addWidget( TextLabelOrientation, 0, 0 );
460
461   CBRelativeOrientation = new QComboBox(GroupParameters);
462   CBRelativeOrientation->setObjectName( "RelativeOrientation" );
463   CBRelativeOrientation->addItem( tr("ALONG_XY") );
464   CBRelativeOrientation->addItem( tr("ALONG_YZ") );
465   CBRelativeOrientation->addItem( tr("ALONG_ZX") );
466   GroupParametersLayout->addWidget( CBRelativeOrientation, 0, 1 );
467
468   TLValueDistance = new QLabel( GroupParameters );
469   TLValueDistance->setObjectName( "TLValueDistance" );
470   TLValueDistance->setAlignment( Qt::AlignCenter );
471   TLValueDistance->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
472   QFont fnt = TLValueDistance->font(); fnt.setBold( true ); TLValueDistance->setFont( fnt );
473   GroupParametersLayout->addWidget( TLValueDistance, 1, 1 );
474
475   TextLabelDistance = new QLabel( tr("SMESH_DISTANCE"), GroupParameters );
476   TextLabelDistance->setObjectName( "TextLabelDistance" );
477   GroupParametersLayout->addWidget( TextLabelDistance, 2, 0 );
478
479   SliderDistance = new QSlider( Qt::Horizontal, GroupParameters );
480   SliderDistance->setObjectName( "SliderDistance" );
481   SliderDistance->setFocusPolicy( Qt::NoFocus );
482   SliderDistance->setMinimumSize( 300, 0 );
483   SliderDistance->setMinimum( 0 );
484   SliderDistance->setMaximum( 100 );
485   SliderDistance->setSingleStep( 1 );
486   SliderDistance->setPageStep( 10 );
487   SliderDistance->setTracking( false );
488   GroupParametersLayout->addWidget( SliderDistance, 2, 1 );
489
490   TLValueRotation1 = new QLabel( GroupParameters );
491   TLValueRotation1->setObjectName( "TLValueRotation1" );
492   TLValueRotation1->setAlignment( Qt::AlignCenter );
493   TLValueRotation1->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
494   TLValueRotation1->setFont( fnt );
495   GroupParametersLayout->addWidget( TLValueRotation1, 3, 1 );
496
497   TextLabelRotation1 = new QLabel( tr("ROTATION_AROUND_X_Y2Z"), GroupParameters );
498   TextLabelRotation1->setObjectName( "TextLabelRotation1" );
499   GroupParametersLayout->addWidget( TextLabelRotation1, 4, 0 );
500
501   SliderRotation1 = new QSlider( Qt::Horizontal, GroupParameters );
502   SliderRotation1->setObjectName( "SliderRotation1" );
503   SliderRotation1->setFocusPolicy( Qt::NoFocus );
504   SliderRotation1->setMinimumSize( 300, 0 );
505   SliderRotation1->setMinimum( -180 );
506   SliderRotation1->setMaximum( 180 );
507   SliderRotation1->setSingleStep( 1 );
508   SliderRotation1->setPageStep( 10 );
509   SliderRotation1->setTracking(false);
510   GroupParametersLayout->addWidget( SliderRotation1, 4, 1 );
511
512   TLValueRotation2 = new QLabel( GroupParameters );
513   TLValueRotation2->setObjectName( "TLValueRotation2" );
514   TLValueRotation2->setAlignment( Qt::AlignCenter );
515   TLValueRotation2->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
516   TLValueRotation2->setFont( fnt );
517   GroupParametersLayout->addWidget( TLValueRotation2, 5, 1 );
518
519   TextLabelRotation2 = new QLabel(tr("ROTATION_AROUND_Y_X2Z"), GroupParameters);
520   TextLabelRotation2->setObjectName( "TextLabelRotation2" );
521   TextLabelRotation2->setObjectName( "TextLabelRotation2" );
522   GroupParametersLayout->addWidget( TextLabelRotation2, 6, 0 );
523
524   SliderRotation2 = new QSlider( Qt::Horizontal, GroupParameters );
525   SliderRotation2->setObjectName( "SliderRotation2" );
526   SliderRotation2->setFocusPolicy( Qt::NoFocus );
527   SliderRotation2->setMinimumSize( 300, 0 );
528   SliderRotation2->setMinimum( -180 );
529   SliderRotation2->setMaximum( 180 );
530   SliderRotation2->setSingleStep( 1 );
531   SliderRotation2->setPageStep( 10 );
532   SliderRotation2->setTracking(false);
533   GroupParametersLayout->addWidget( SliderRotation2, 6, 1 );
534
535   /***************************************************************/
536   QWidget* CheckBoxWidget = new QWidget( this );
537   QHBoxLayout* CheckBoxLayout = new QHBoxLayout( CheckBoxWidget );
538
539   PreviewCheckBox = new QCheckBox( tr("SHOW_PREVIEW"), CheckBoxWidget );
540   PreviewCheckBox->setObjectName( "PreviewCheckBox" );
541   PreviewCheckBox->setChecked( true );
542   CheckBoxLayout->addWidget( PreviewCheckBox, 0, Qt::AlignCenter );
543
544   AutoApplyCheckBox = new QCheckBox( tr("AUTO_APPLY"), CheckBoxWidget );
545   AutoApplyCheckBox->setObjectName( "AutoApplyCheckBox" );
546   CheckBoxLayout->addWidget( AutoApplyCheckBox, 0, Qt::AlignCenter );
547
548   /***************************************************************/
549   // Controls for "Ok", "Apply" and "Close" button
550   QGroupBox* GroupButtons = new QGroupBox(this);
551   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
552   GroupButtonsLayout->setSpacing(SPACING);
553   GroupButtonsLayout->setMargin(MARGIN);
554   
555   buttonOk = new QPushButton( tr( "SMESH_BUT_APPLY_AND_CLOSE" ), GroupButtons );
556   buttonOk->setAutoDefault( true );
557   buttonOk->setDefault( true );
558   buttonApply = new QPushButton( tr( "SMESH_BUT_APPLY" ), GroupButtons );
559   buttonApply->setAutoDefault( true );
560   buttonCancel = new QPushButton( tr( "SMESH_BUT_CLOSE" ), GroupButtons );
561   buttonCancel->setAutoDefault( true );
562   buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons );
563   buttonHelp->setAutoDefault( true );
564   GroupButtonsLayout->addWidget( buttonOk );
565   GroupButtonsLayout->addSpacing(10);
566   GroupButtonsLayout->addWidget( buttonApply );
567   GroupButtonsLayout->addSpacing(10);
568   GroupButtonsLayout->addStretch();
569   GroupButtonsLayout->addWidget( buttonCancel );
570   GroupButtonsLayout->addWidget( buttonHelp );
571
572   ModeStackedLayout->addWidget( ModeActiveWidget );
573   ModeStackedLayout->addWidget( GroupParameters );
574
575   SMESHGUI_ClippingDlgLayout->addWidget( GroupPlanes );
576   SMESHGUI_ClippingDlgLayout->addLayout( ModeStackedLayout );
577   SMESHGUI_ClippingDlgLayout->addWidget( CheckBoxWidget );
578   SMESHGUI_ClippingDlgLayout->addWidget( GroupButtons );
579
580   // Initializations
581   initParam();
582
583   myIsSelectPlane = false;
584
585   myHelpFileName = "clipping_page.html";
586
587   // signals and slots connections :
588   connect( ComboBoxPlanes, SIGNAL( activated( int ) ), this, SLOT( onSelectPlane( int ) ) );
589   connect( isOpenGLClipping, SIGNAL( toggled( bool ) ), this, SLOT( onIsOpenGLClipping( bool ) ) );
590   connect( buttonNew, SIGNAL( clicked() ), buttonNew, SLOT( showMenu() ) );
591   connect( buttonDelete, SIGNAL( clicked() ), this, SLOT( ClickOnDelete() ) );
592   connect( ActorList, SIGNAL( itemChanged( QListWidgetItem* ) ), this, SLOT( onActorItemChanged( QListWidgetItem*) ) );
593   connect( SelectAllCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onSelectAll( int ) ) );
594
595   connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
596   connect( resetButton,  SIGNAL (clicked() ), this, SLOT( onReset() ) );
597   connect( SpinBox_X,  SIGNAL ( valueChanged( double ) ),  this, SLOT( SetCurrentPlaneParam() ) );
598   connect( SpinBox_Y,  SIGNAL ( valueChanged( double ) ),  this, SLOT( SetCurrentPlaneParam() ) );
599   connect( SpinBox_Z,  SIGNAL ( valueChanged( double ) ),  this, SLOT( SetCurrentPlaneParam() ) );
600   connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ),  this, SLOT( SetCurrentPlaneParam() ) );
601   connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ),  this, SLOT( SetCurrentPlaneParam() ) );
602   connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ),  this, SLOT( SetCurrentPlaneParam() ) );
603   connect( CBAbsoluteOrientation, SIGNAL ( activated ( int ) ), this, SLOT( onSelectAbsoluteOrientation( int ) ) ) ;
604
605   connect( CBRelativeOrientation, SIGNAL( activated( int ) ), this, SLOT( onSelectRelativeOrientation( int ) ) );
606   connect( SliderDistance,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderDistanceHasMoved( int ) ) );
607   connect( SliderDistance,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderDistanceHasMoved( int ) ) );
608   connect( SliderRotation1,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderRotation1HasMoved( int ) ) );
609   connect( SliderRotation1,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderRotation1HasMoved( int ) ) );
610   connect( SliderRotation2,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderRotation2HasMoved( int ) ) );
611   connect( SliderRotation2,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderRotation2HasMoved( int ) ) );
612
613   connect( PreviewCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( OnPreviewToggle( bool ) ) );
614   connect( AutoApplyCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( onAutoApply( bool ) ) );
615   connect( buttonOk, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
616   connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
617   connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
618   connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) );
619   connect( mySMESHGUI, SIGNAL ( SignalCloseAllDialogs() ), this, SLOT( reject() ) );
620   /* to close dialog if study frame change */
621   connect( mySMESHGUI, SIGNAL ( SignalStudyFrameChanged() ), this, SLOT( reject() ) );
622
623   initializePlaneData();
624   synchronize();
625
626   this->show();
627 }
628
629 /*!
630   Destructor
631   Destroys the object and frees any allocated resources
632 */
633 SMESHGUI_ClippingDlg::~SMESHGUI_ClippingDlg()
634 {
635   // no need to delete child widgets, Qt does it all for us
636   std::for_each(myPlanes.begin(),myPlanes.end(),TSetVisibility(false));
637   if (myViewWindow)
638     SMESH::RenderViewWindow(myViewWindow);
639
640   for( int i=0; i< myPlanes.size(); i++ ) {
641     SMESH::TPlaneData aPlaneData = myPlanes[i];
642     aPlaneData.Plane->Delete();
643   }
644
645   if (myPreviewWidget) {
646     myPreviewWidget->Off();
647     myPreviewWidget->Delete();
648   }
649   myPreviewWidget = 0;
650   myCallback->Delete();
651
652   myViewWindow->Repaint();
653 }
654
655 /*!
656   Get distance for cutting plane in relative mode
657 */
658 double SMESHGUI_ClippingDlg::getDistance() const
659 {
660   return TLValueDistance->text().toDouble();
661 }
662
663 /*!
664   Set distance of cutting plane in relative mode
665 */
666 void SMESHGUI_ClippingDlg::setDistance( const double theDistance )
667 {
668   SliderDistance->setValue( theDistance*100 );
669 }
670
671 /*!
672   Get rotation1 for cutting plane in relative mode
673 */
674 double SMESHGUI_ClippingDlg::getRotation1() const
675 {
676   return TLValueRotation1->text().remove("\xB0").toInt();
677 }
678
679 /*!
680   Get rotation2 for cutting plane in relative mode
681 */
682 double SMESHGUI_ClippingDlg::getRotation2() const
683 {
684   return TLValueRotation2->text().remove("\xB0").toInt();
685 }
686
687 /*!
688   Set angles of clipping plane in relative mode
689 */
690 void SMESHGUI_ClippingDlg::setRotation (const double theRot1, const double theRot2)
691 {
692   SliderRotation1->setValue( theRot1 );
693   SliderRotation2->setValue( theRot2 );
694 }
695
696 /*!
697   Set coordinates of origin point in dialog box
698 */
699 void SMESHGUI_ClippingDlg::setOrigin( double theVal[3] )
700 {
701   int anOrientation = CBAbsoluteOrientation->currentIndex();
702   if( anOrientation == 0 || anOrientation == 2 )
703     SpinBox_X->setValue( theVal[0] );
704   if( anOrientation == 0 || anOrientation == 3 )
705     SpinBox_Y->setValue( theVal[1] );
706   if( anOrientation == 0 || anOrientation == 1 )
707     SpinBox_Z->setValue( theVal[2] );
708 }
709
710 /*!
711   Set coordinates of normal vector in dialog box
712 */
713 void SMESHGUI_ClippingDlg::setDirection( double theVal[3] )
714 {
715   int anOrientation = CBAbsoluteOrientation->currentIndex();
716   if( anOrientation == 0 ) {
717     SpinBox_Dx->setValue( theVal[0] );
718     SpinBox_Dy->setValue( theVal[1] );
719     SpinBox_Dz->setValue( theVal[2] );
720   }
721 }
722
723 /*!
724   Create a new widget for preview clipping plane
725 */
726 vtkImplicitPlaneWidget* SMESHGUI_ClippingDlg::createPreviewWidget()
727 {
728   vtkImplicitPlaneWidget* aPlaneWgt = vtkImplicitPlaneWidget::New();
729
730   aPlaneWgt->SetInteractor( myViewWindow->getInteractor() );
731   aPlaneWgt->SetPlaceFactor( SIZEFACTOR );
732   aPlaneWgt->ScaleEnabledOff();
733   aPlaneWgt->SetOrigin( 0, 0, 0 );
734   aPlaneWgt->SetNormal( -1, -1, -1 );
735   aPlaneWgt->Off();
736
737   double anRGB[3];
738   SMESH::GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) );
739
740   aPlaneWgt->GetPlaneProperty()->SetColor( anRGB[0],anRGB[1],anRGB[2] );
741   aPlaneWgt->GetPlaneProperty()->SetOpacity( 0.2 );;
742
743   aPlaneWgt->GetSelectedPlaneProperty()->SetColor( anRGB[0],anRGB[1],anRGB[2] );
744   aPlaneWgt->GetSelectedPlaneProperty()->SetOpacity( 0.2 );
745   aPlaneWgt->GetSelectedPlaneProperty()->SetLineWidth( 2.0 );
746
747   aPlaneWgt->AddObserver(vtkCommand::InteractionEvent, myCallback, 0.);
748
749   return aPlaneWgt;
750 }
751
752 /*!
753   Translate two angles of plane to normal
754 */
755 void rotationToNormal ( double theRotation[2],
756                         int theOrientation,
757                         double theNormal[3],
758                         double theDir[2][3] )
759 {
760   static double aCoeff = M_PI/180.0;
761
762   double anU[2] = { cos( aCoeff * theRotation[0] ), cos( aCoeff * theRotation[1] ) };
763   double aV[2] = { sqrt( 1.0 - anU[0]*anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
764   aV[0] = theRotation[0] > 0? aV[0]: -aV[0];
765   aV[1] = theRotation[1] > 0? aV[1]: -aV[1];
766
767   switch ( theOrientation ) {
768   case 0:
769   case 1:
770         theDir[0][1] = anU[0];
771         theDir[0][2] = aV[0];
772         theDir[1][0] = anU[1];
773         theDir[1][2] = aV[1];
774     break;
775   case 2:
776         theDir[0][2] = anU[0];
777         theDir[0][0] = aV[0];
778         theDir[1][1] = anU[1];
779         theDir[1][0] = aV[1];
780     break;
781   case 3:
782         theDir[0][0] = anU[0];
783         theDir[0][1] = aV[0];
784         theDir[1][2] = anU[1];
785         theDir[1][1] = aV[1];
786     break;
787   }
788
789   vtkMath::Cross( theDir[1], theDir[0], theNormal );
790   vtkMath::Normalize( theNormal );
791   vtkMath::Cross( theNormal, theDir[1], theDir[0] );
792 }
793
794 /*!
795   Used in SMESHGUI::restoreVisualParameters() to avoid
796   Declaration of OrientedPlane outside of SMESHGUI_ClippingDlg.cxx
797 */
798 bool SMESHGUI_ClippingDlg::AddPlane ( SMESH::TActorList       theActorList,
799                                       SMESH::OrientedPlane*   thePlane )
800 {
801   double aNormal[3];
802   double aDir[2][3] = {{0, 0, 0}, {0, 0, 0}};
803   static double aCoeff = vtkMath::Pi()/180.0;
804
805   int anOrientation;
806   if ( thePlane->PlaneMode == SMESH::Absolute )
807    anOrientation = thePlane->myAbsoluteOrientation;
808   else if ( thePlane->PlaneMode == SMESH::Relative )
809    anOrientation = thePlane->myRelativeOrientation + 1;
810
811   if ( anOrientation == 0 ) {
812         // compute a direction for plane in absolute mode
813     double znam = sqrt( thePlane->Dx*thePlane->Dx + thePlane->Dy*thePlane->Dy + thePlane->Dz*thePlane->Dz );
814     double aRotation = acos( thePlane->Dy/znam )/aCoeff;
815     if ( thePlane->Dy >= 0.0 && thePlane->Dz >= 0.0 )      thePlane->myAngle[0] = 90.0 + aRotation;
816     else if ( thePlane->Dy >= 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[0] = 90.0 - aRotation;
817     else if ( thePlane->Dy < 0.0 && thePlane->Dz >= 0.0 ) thePlane->myAngle[0] = aRotation - 90.0;
818     else if ( thePlane->Dy < 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[0] = 270.0 - aRotation;
819
820     aRotation = acos( thePlane->Dx/znam )/aCoeff;
821     if ( thePlane->Dx >= 0.0 && thePlane->Dz >= 0.0 )      thePlane->myAngle[1] = 90.0 + aRotation;
822     else if ( thePlane->Dx >= 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[1] = 90.0 - aRotation;
823     else if ( thePlane->Dx < 0.0 && thePlane->Dz >= 0.0 ) thePlane->myAngle[1] = aRotation - 90.0;
824     else if ( thePlane->Dx < 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[1] = 270.0 - aRotation;
825   }
826
827   // compute a normal
828   rotationToNormal( thePlane->myAngle, anOrientation, aNormal, aDir );
829
830   double aBounds[6];
831   double anOrigin[3];
832
833   if ( thePlane->PlaneMode == SMESH::Absolute ) {
834     aNormal[0] = thePlane->Dx;
835     aNormal[1] = thePlane->Dy;
836     aNormal[2] = thePlane->Dz;
837   }
838
839   bool anIsOk = false;
840   if( theActorList.empty() ) {
841     // to support planes with empty actor list we should create
842     // a nullified plane that will be initialized later
843     anOrigin[0] = anOrigin[1] = anOrigin[2] = 0;
844     aBounds[0] = aBounds[2] = aBounds[4] = 0;
845     aBounds[1] = aBounds[3] = aBounds[5] = 0;
846     anIsOk = true;
847   }
848   else
849     anIsOk = SMESH::ComputeClippingPlaneParameters( theActorList,
850                                                     aNormal,
851                                                     thePlane->myDistance,
852                                                     aBounds,
853                                                     anOrigin );
854   if( !anIsOk )
855     return false;
856
857   if ( thePlane->PlaneMode == SMESH::Absolute ) {
858     anOrigin[0] = thePlane->X;
859     anOrigin[1] = thePlane->Y;
860     anOrigin[2] = thePlane->Z;
861   }
862   thePlane->SetNormal( aNormal );
863   thePlane->SetOrigin( anOrigin );
864
865
866   double aPnt[3] = { ( aBounds[0] + aBounds[1] ) / 2.,
867                      ( aBounds[2] + aBounds[3] ) / 2.,
868                      ( aBounds[4] + aBounds[5] ) / 2. };
869
870   double aDel = pow( pow( aBounds[1] - aBounds[0], 2 ) +
871                      pow( aBounds[3] - aBounds[2], 2 ) +
872                      pow( aBounds[5] - aBounds[4], 2 ), 0.5 );
873
874   double aDelta[2][3] = { { aDir[0][0]*aDel, aDir[0][1]*aDel, aDir[0][2]*aDel },
875                           { aDir[1][0]*aDel, aDir[1][1]*aDel, aDir[1][2]*aDel } };
876   double aParam, aPnt0[3], aPnt1[3], aPnt2[3];
877
878   double aPnt01[3] = { aPnt[0] - aDelta[0][0] - aDelta[1][0],
879                        aPnt[1] - aDelta[0][1] - aDelta[1][1],
880                        aPnt[2] - aDelta[0][2] - aDelta[1][2] };
881   double aPnt02[3] = { aPnt01[0] + aNormal[0],
882                        aPnt01[1] + aNormal[1],
883                        aPnt01[2] + aNormal[2] };
884   vtkPlane::IntersectWithLine( aPnt01, aPnt02, aNormal, anOrigin, aParam, aPnt0 );
885
886   double aPnt11[3] = { aPnt[0] - aDelta[0][0] + aDelta[1][0],
887                        aPnt[1] - aDelta[0][1] + aDelta[1][1],
888                        aPnt[2] - aDelta[0][2] + aDelta[1][2] };
889   double aPnt12[3] = { aPnt11[0] + aNormal[0],
890                        aPnt11[1] + aNormal[1],
891                        aPnt11[2] + aNormal[2] };
892   vtkPlane::IntersectWithLine( aPnt11, aPnt12, aNormal, anOrigin, aParam, aPnt1);
893
894   double aPnt21[3] = { aPnt[0] + aDelta[0][0] - aDelta[1][0],
895                        aPnt[1] + aDelta[0][1] - aDelta[1][1],
896                        aPnt[2] + aDelta[0][2] - aDelta[1][2] };
897   double aPnt22[3] = { aPnt21[0] + aNormal[0],
898                        aPnt21[1] + aNormal[1],
899                        aPnt21[2] + aNormal[2] };
900   vtkPlane::IntersectWithLine( aPnt21, aPnt22, aNormal, anOrigin, aParam, aPnt2);
901
902   vtkPlaneSource* aPlaneSource = thePlane->myPlaneSource;
903   aPlaneSource->SetNormal( aNormal[0], aNormal[1], aNormal[2] );
904   aPlaneSource->SetOrigin( aPnt0[0], aPnt0[1], aPnt0[2] );
905   aPlaneSource->SetPoint1( aPnt1[0], aPnt1[1], aPnt1[2] );
906   aPlaneSource->SetPoint2( aPnt2[0], aPnt2[1], aPnt2[2] );
907   aPlaneSource->Update();
908
909   SMESH::TActorList::iterator anIter = theActorList.begin();
910   for ( ; anIter != theActorList.end(); anIter++ )
911     if( vtkActor* aVTKActor = *anIter )
912       if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
913         if( thePlane->IsOpenGLClipping )
914           anActor->AddOpenGLClippingPlane( thePlane->InvertPlane() );
915         else
916                 anActor->AddClippingPlane( thePlane );
917       }
918
919   return true;
920 }
921
922 /*!
923   Custom handling of events
924 */
925 void SMESHGUI_ClippingDlg::keyPressEvent( QKeyEvent* e )
926 {
927   QDialog::keyPressEvent( e );
928   if ( e->isAccepted() )
929     return;
930
931   if ( e->key() == Qt::Key_F1 ) {
932     e->accept();
933     ClickOnHelp();
934   }
935 }
936
937 /*!
938   Handles the char preview widget activation event
939 */
940 void SMESHGUI_ClippingDlg::ProcessEvents( vtkObject* theObject,
941                                           unsigned long theEvent,
942                                           void* theClientData,
943                                           void* vtkNotUsed( theCallData ) )
944 {
945   vtkImplicitPlaneWidget* aWidget = vtkImplicitPlaneWidget::SafeDownCast( theObject );
946   if ( aWidget == NULL ) return;
947   if ( theClientData == NULL ) return;
948
949   SMESHGUI_ClippingDlg* aDlg = (SMESHGUI_ClippingDlg*) theClientData;
950
951   double anOrigin[3];
952   double aDir[3];
953
954   switch( theEvent ){
955   case vtkCommand::InteractionEvent:
956     aWidget->GetOrigin( anOrigin );
957     aWidget->GetNormal( aDir );
958
959     aDlg->myIsSelectPlane = true;
960
961     if( aDlg->CurrentMode == SMESH::Absolute ) {
962       aDlg->setOrigin( anOrigin );
963       aDlg->setDirection( aDir );
964       aDlg->myIsPreviewMoved = true;
965     }
966     else if( aDlg->CurrentMode == SMESH::Relative ) {
967       aDlg->absolutePlaneToRelative( anOrigin, aDir );
968     }
969     aDlg->myIsSelectPlane = false;
970
971     aDlg->SetCurrentPlaneParam();
972     aDlg->myIsPreviewMoved = false;
973     break;
974   }
975 }
976
977 /*!
978   Initialize the planes's data when the dialog opened
979 */
980 void SMESHGUI_ClippingDlg::initializePlaneData()
981 {
982   const SMESHGUI_ClippingPlaneInfoMap& aClippingPlaneInfoMap = mySMESHGUI->getClippingPlaneInfoMap();
983   SMESHGUI_ClippingPlaneInfoMap::const_iterator anIter1 = aClippingPlaneInfoMap.find( myViewWindow->getViewManager() );
984   if( anIter1 != aClippingPlaneInfoMap.end() ) {
985     const SMESHGUI_ClippingPlaneInfoList& aClippingPlaneInfoList = anIter1->second;
986     SMESHGUI_ClippingPlaneInfoList::const_iterator anIter2 = aClippingPlaneInfoList.begin();
987     for( ; anIter2 != aClippingPlaneInfoList.end(); anIter2++ ) {
988       const SMESH::ClippingPlaneInfo& aClippingPlaneInfo = *anIter2;
989       SMESH::OrientedPlane* anOrientedPlane = SMESH::OrientedPlane::New(myViewWindow);
990       anOrientedPlane->ShallowCopy(aClippingPlaneInfo.Plane);
991       SMESH::TPlane aTPlane( anOrientedPlane );
992       SMESH::TPlaneData aPlaneData( aTPlane, aClippingPlaneInfo.ActorList );
993       myPlanes.push_back( aPlaneData );
994     }
995   }
996   std::for_each( myPlanes.begin(),myPlanes.end(), TSetVisibility( PreviewCheckBox->isChecked() ) );
997   if( myPlanes.size() )
998     myPreviewWidget->SetEnabled( PreviewCheckBox->isChecked() );
999 }
1000
1001 /*!
1002   Initialization of initial values of widgets
1003 */
1004 void SMESHGUI_ClippingDlg::initParam()
1005 {
1006   SpinBox_X->setValue( 0.0 );
1007   SpinBox_Y->setValue( 0.0 );
1008   SpinBox_Z->setValue( 0.0 );
1009
1010   SpinBox_Dx->setValue( 1.0 );
1011   SpinBox_Dy->setValue( 1.0 );
1012   SpinBox_Dz->setValue( 1.0 );
1013
1014   CBAbsoluteOrientation->setCurrentIndex(0);
1015
1016   TLValueDistance->setText( "0.5" );
1017   TLValueRotation1->setText( "0\xB0" );
1018   TLValueRotation2->setText( "0\xB0" );
1019   CBRelativeOrientation->setCurrentIndex( 0 );
1020   SliderDistance->setValue( 50 );
1021   SliderRotation1->setValue( 0 );
1022   SliderRotation2->setValue( 0 );
1023 }
1024
1025 /*!
1026   Synchronize dialog's widgets with data
1027 */
1028 void SMESHGUI_ClippingDlg::synchronize()
1029 {
1030   int aNbPlanes = myPlanes.size();
1031   ComboBoxPlanes->clear();
1032
1033   QString aName;
1034   for( int i = 1; i<=aNbPlanes; i++ ) {
1035     aName = QString( tr( "PLANE_NUM" ) ).arg(i);
1036     ComboBoxPlanes->addItem( aName );
1037   }
1038
1039   int aPos = ComboBoxPlanes->count() - 1;
1040   ComboBoxPlanes->setCurrentIndex( aPos );
1041
1042   bool anIsControlsEnable = ( aPos >= 0 );
1043   if ( anIsControlsEnable ) {
1044     onSelectPlane( aPos );
1045     updateActorList();
1046     if( PreviewCheckBox->isChecked() )
1047       myPreviewWidget->On();
1048   }
1049   else {
1050     ComboBoxPlanes->addItem( tr( "NO_PLANES" ) );
1051     ActorList->clear();
1052     initParam();
1053     if( PreviewCheckBox->isChecked() )
1054       myPreviewWidget->Off();
1055   }
1056
1057   isOpenGLClipping->setEnabled( anIsControlsEnable );
1058   ActorList->setEnabled( anIsControlsEnable );
1059   SelectAllCheckBox->setEnabled( anIsControlsEnable );
1060   buttonDelete->setEnabled( anIsControlsEnable );
1061   if ( CurrentMode == SMESH::Absolute ) {
1062     SpinBox_X->setEnabled( anIsControlsEnable );
1063     SpinBox_Y->setEnabled( anIsControlsEnable );
1064     SpinBox_Z->setEnabled( anIsControlsEnable );
1065     SpinBox_Dx->setEnabled( anIsControlsEnable );
1066     SpinBox_Dy->setEnabled( anIsControlsEnable );
1067     SpinBox_Dz->setEnabled( anIsControlsEnable );
1068     CBAbsoluteOrientation->setEnabled( anIsControlsEnable );
1069     invertButton->setEnabled( anIsControlsEnable );
1070     resetButton->setEnabled( anIsControlsEnable );
1071   }
1072   else if ( CurrentMode == SMESH::Relative ) {
1073     CBRelativeOrientation->setEnabled( anIsControlsEnable );
1074     SliderDistance->setEnabled( anIsControlsEnable );
1075     SliderRotation1->setEnabled( anIsControlsEnable );
1076     SliderRotation2->setEnabled( anIsControlsEnable );
1077   }
1078 }
1079
1080 /*!
1081   Update the list of actors
1082 */
1083 void SMESHGUI_ClippingDlg::updateActorList()
1084 {
1085   ActorList->clear();
1086
1087   SalomeApp_Study* anAppStudy = SMESHGUI::activeStudy();
1088   if( !anAppStudy )
1089     return;
1090
1091   _PTR(Study) aStudy = anAppStudy->studyDS();
1092   if( !aStudy )
1093     return;
1094
1095   if( !myViewWindow )
1096     return;
1097
1098   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1099   const SMESH::TPlaneData& aPlaneData = myPlanes[ aCurPlaneIndex ];
1100   const SMESH::TActorList& anActorList = aPlaneData.ActorList;
1101
1102   std::for_each( myPlanes.begin(),myPlanes.end(), TSetVisibility( PreviewCheckBox->isChecked() ) );
1103   aPlaneData.Plane.GetPointer()->myActor->SetVisibility( false );
1104
1105   VTK::ActorCollectionCopy aCopy( myViewWindow->getRenderer()->GetActors() );
1106   vtkActorCollection* anAllActors = aCopy.GetActors();
1107   anAllActors->InitTraversal();
1108   while( vtkActor* aVTKActor = anAllActors->GetNextActor() ) {
1109     if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
1110       if( anActor->hasIO() ) {
1111         Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
1112         if( _PTR(SObject) aSObj = aStudy->FindObjectID( anIO->getEntry() ) ) {
1113           bool anIsChecked = false;
1114           SMESH::TActorList::const_iterator anIter = anActorList.begin();
1115           for ( ; anIter != anActorList.end(); anIter++ ) {
1116             if( vtkActor* aVTKActorRef = *anIter ) {
1117               if( SMESH_Actor* anActorRef = SMESH_Actor::SafeDownCast( aVTKActorRef ) ) {
1118                 if( anActorRef == anActor ) {
1119                   anIsChecked = true;
1120                   break;
1121                 }
1122               }
1123             }
1124           }
1125           QString aName = QString( aSObj->GetName().c_str() );
1126           QListWidgetItem* anItem = new ActorItem( anActor, aName, ActorList );
1127           anItem->setCheckState( anIsChecked ? Qt::Checked : Qt::Unchecked );
1128           updateActorItem( anItem, true, false );
1129         }
1130       }
1131     }
1132   }
1133 }
1134
1135 /*!
1136   Update an actor in actor's list
1137 */
1138 void SMESHGUI_ClippingDlg::updateActorItem( QListWidgetItem* theItem,
1139                                             bool theUpdateSelectAll,
1140                                             bool theUpdateClippingPlaneMap )
1141 {
1142   // update Select All check box
1143   if( theUpdateSelectAll ) {
1144     int aNbItems = ActorList->count(), aNbChecked = 0;
1145     for( int i = 0; i < aNbItems; i++ )
1146       if( QListWidgetItem* anItem = ActorList->item( i ) )
1147         if( anItem->checkState() == Qt::Checked )
1148           aNbChecked++;
1149
1150     bool anIsBlocked = SelectAllCheckBox->blockSignals( true );
1151     SelectAllCheckBox->setCheckState( aNbChecked == aNbItems ? Qt::Checked : Qt::Unchecked);
1152     SelectAllCheckBox->blockSignals( anIsBlocked );
1153   }
1154
1155   // update clipping plane map
1156   if( theUpdateClippingPlaneMap ) {
1157     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1158     if( ActorItem* anItem = dynamic_cast<ActorItem*>( theItem ) ) {
1159       if( SMESH_Actor* anActor = anItem->getActor() ) {
1160         SMESH::TPlaneData& aPlaneData = myPlanes[ aCurPlaneIndex ];
1161         SMESH::TActorList& anActorList = aPlaneData.ActorList;
1162         bool anIsPushed = false;
1163         SMESH::TActorList::iterator anIter = anActorList.begin();
1164         for ( ; anIter != anActorList.end(); anIter++ ) {
1165           if( anActor == *anIter ) {
1166             anIsPushed = true;
1167             break;
1168           }
1169         }
1170         if( theItem->checkState() == Qt::Checked && !anIsPushed )
1171           anActorList.push_back( anActor );
1172         else if( theItem->checkState() == Qt::Unchecked && anIsPushed )
1173           anActorList.remove( anActor );
1174
1175         SMESH::ComputeBounds( anActorList, myBounds );
1176         myPreviewWidget->PlaceWidget( myBounds[0], myBounds[1], myBounds[2],
1177                                                   myBounds[3], myBounds[4], myBounds[5] );
1178       }
1179     }
1180   }
1181 }
1182
1183 /*!
1184   Get the list of current actors
1185 */
1186 SMESH::TActorList SMESHGUI_ClippingDlg::getCurrentActors()
1187 {
1188   SMESH::TActorList anActorList;
1189   for( int i = 0, n = ActorList->count(); i < n; i++ )
1190     if( ActorItem* anItem = dynamic_cast<ActorItem*>( ActorList->item( i ) ) )
1191       if( anItem->checkState() == Qt::Checked )
1192         if( SMESH_Actor* anActor = anItem->getActor() )
1193           anActorList.push_back( anActor );
1194   return anActorList;
1195 }
1196
1197 /*!
1198   Dump the parameters of clipping planes
1199 */
1200 void SMESHGUI_ClippingDlg::dumpPlaneData() const
1201 {
1202   printf( "----------- Plane Data -----------\n" );
1203   int anId = 1;
1204   SMESH::TPlaneDataVector::const_iterator anIter1 = myPlanes.begin();
1205   for ( ; anIter1 != myPlanes.end(); anIter1++, anId++ ) {
1206     SMESH::TPlaneData aPlaneData = *anIter1;
1207     SMESH::TPlane aPlane = aPlaneData.Plane;
1208     double* aNormal = aPlane->GetNormal();
1209     double* anOrigin = aPlane->GetOrigin();
1210     printf( "Plane N%d:\n", anId );
1211     printf( "  Normal = ( %f, %f, %f )\n", aNormal[0], aNormal[1], aNormal[2] );
1212     printf( "  Origin = ( %f, %f, %f )\n", anOrigin[0], anOrigin[1], anOrigin[2] );
1213
1214     SMESH::TActorList anActorList = aPlaneData.ActorList;
1215     SMESH::TActorList::const_iterator anIter2 = anActorList.begin();
1216     for ( ; anIter2 != anActorList.end(); anIter2++ ) {
1217       if( vtkActor* aVTKActor = *anIter2 ) {
1218         if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) )
1219           printf( "  - Actor: '%s'\n", anActor->getName() );
1220       }
1221       else
1222         printf( "  - Actor: NULL\n");
1223     }
1224   }
1225   printf( "----------------------------------\n" );
1226 }
1227
1228 /*!
1229   SLOT on close button click: rejects dialog
1230 */
1231 void SMESHGUI_ClippingDlg::reject()
1232 {
1233   //here we can insert actions to do at close.
1234   QDialog::reject();
1235 }
1236
1237 /*!
1238   Set absolute mode of clipping plane
1239 */
1240 void SMESHGUI_ClippingDlg::onModeAbsolute()
1241 {
1242   ModeStackedLayout->setCurrentIndex(0);
1243   CurrentMode = SMESH::Absolute;
1244   ClickOnNew();
1245   SetCurrentPlaneParam();
1246 }
1247
1248 /*!
1249   Set relative mode of clipping plane
1250 */
1251 void SMESHGUI_ClippingDlg::onModeRelative()
1252 {
1253   ModeStackedLayout->setCurrentIndex(1);
1254   CurrentMode = SMESH::Relative;
1255   ClickOnNew();
1256   SetCurrentPlaneParam();
1257 }
1258
1259 /*!
1260   SLOT on new button click: create a new clipping plane
1261 */
1262 void SMESHGUI_ClippingDlg::ClickOnNew()
1263 {
1264   if(myViewWindow) {
1265     SMESH::OrientedPlane* aPlane = SMESH::OrientedPlane::New(myViewWindow);
1266     SMESH::TPlane aTPlane(aPlane);
1267     aPlane->PlaneMode = CurrentMode;
1268     SMESH::TActorList anActorList;
1269     VTK::ActorCollectionCopy aCopy( myViewWindow->getRenderer()->GetActors() );
1270     vtkActorCollection* anAllActors = aCopy.GetActors();
1271     anAllActors->InitTraversal();
1272     while( vtkActor* aVTKActor = anAllActors->GetNextActor() )
1273       if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) )
1274         anActorList.push_back( anActor );
1275
1276     SMESH::TPlaneData aPlaneData(aTPlane, anActorList);
1277
1278     myPlanes.push_back(aPlaneData);
1279
1280
1281     std::for_each( myPlanes.begin(),myPlanes.end(), TSetVisibility( PreviewCheckBox->isChecked() ) );
1282     aPlane->myActor->SetVisibility( false );
1283
1284     bool anIsBlocked = ActorList->blockSignals( true );
1285
1286     SMESH::ComputeBounds( anActorList, myBounds );
1287     myPreviewWidget->PlaceWidget( myBounds[0],myBounds[1],myBounds[2],
1288                                   myBounds[3],myBounds[4],myBounds[5] );
1289     synchronize();
1290     SetCurrentPlaneParam();
1291
1292     ActorList->blockSignals( anIsBlocked );
1293   }
1294 }
1295
1296 /*!
1297   SLOT on delete button click: Delete selected clipping plane
1298 */
1299 void SMESHGUI_ClippingDlg::ClickOnDelete()
1300 {
1301   if (myPlanes.empty())
1302     return;
1303
1304   int aPlaneIndex = ComboBoxPlanes->currentIndex();
1305
1306   SMESH::TPlaneDataVector::iterator anIter = myPlanes.begin() + aPlaneIndex;
1307   SMESH::TPlaneData aPlaneData = *anIter;
1308   aPlaneData.Plane.GetPointer()->myActor->SetVisibility(false);
1309   myPlanes.erase(anIter);
1310
1311   if(AutoApplyCheckBox->isChecked())
1312     ClickOnApply();
1313
1314   synchronize();
1315   SMESH::RenderViewWindow( myViewWindow );
1316 }
1317
1318 /*!
1319   Set current parameters of selected plane
1320 */
1321 void SMESHGUI_ClippingDlg::onSelectPlane ( int theIndex )
1322 {
1323   if ( myPlanes.empty() )
1324     return;
1325
1326   SMESH::TPlaneData aPlaneData = myPlanes[theIndex];
1327   SMESH::OrientedPlane* aPlane = aPlaneData.Plane.GetPointer();
1328
1329   myIsSelectPlane = true;
1330   isOpenGLClipping->setChecked( aPlane->IsOpenGLClipping );
1331
1332   if ( aPlane->PlaneMode == SMESH::Absolute ) {
1333     ModeStackedLayout->setCurrentIndex( 0 );
1334     CurrentMode = SMESH::Absolute;
1335     int anOrientation = aPlane->myAbsoluteOrientation;
1336     // Set plane parameters in the dialog
1337     double anOrigin[3], aDir[3];
1338     anOrigin[0] = aPlane->X;
1339     anOrigin[1] = aPlane->Y;
1340     anOrigin[2] = aPlane->Z;
1341     setOrigin( anOrigin );
1342     aDir[0] = aPlane->Dx;
1343     aDir[1] = aPlane->Dy;
1344     aDir[2] = aPlane->Dz;
1345     setDirection( aDir );
1346     CBAbsoluteOrientation->setCurrentIndex( anOrientation );
1347     onSelectAbsoluteOrientation( anOrientation );
1348   }
1349   else if ( aPlane->PlaneMode == SMESH::Relative ) {
1350     ModeStackedLayout->setCurrentIndex( 1 );
1351     CurrentMode = SMESH::Relative;
1352     SMESH::Orientation anOrientation = aPlane->GetOrientation();
1353     double aRot[2] = { aPlane->myAngle[0], aPlane->myAngle[1] };
1354     // Set plane parameters in the dialog
1355     setDistance( aPlane->GetDistance() );
1356     setRotation( aRot[0], aRot[1] );
1357     switch ( anOrientation ) {
1358     case SMESH::XY:
1359       CBRelativeOrientation->setCurrentIndex(0);
1360       onSelectRelativeOrientation(0);
1361       break;
1362     case SMESH::YZ:
1363       CBRelativeOrientation->setCurrentIndex(1);
1364       onSelectRelativeOrientation(1);
1365       break;
1366     case SMESH::ZX:
1367       CBRelativeOrientation->setCurrentIndex(2);
1368       onSelectRelativeOrientation(2);
1369       break;
1370     }
1371   }
1372   myIsSelectPlane = false;
1373   SMESH::ComputeBounds( aPlaneData.ActorList, myBounds );
1374   myPreviewWidget->PlaceWidget( myBounds[0], myBounds[1], myBounds[2],
1375                                           myBounds[3], myBounds[4], myBounds[5] );
1376   SetCurrentPlaneParam();
1377
1378   // Actors
1379   bool anIsBlocked = ActorList->blockSignals( true );
1380   updateActorList();
1381   ActorList->blockSignals( anIsBlocked );
1382 }
1383
1384 /*!
1385   SLOT: called on OpenGLClipping check box toggled
1386 */
1387 void SMESHGUI_ClippingDlg::onIsOpenGLClipping( bool toggled )
1388 {
1389   if ( myPlanes.empty() || myIsSelectPlane )
1390     return;
1391
1392   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1393   SMESH::TPlaneData aPlane = myPlanes[aCurPlaneIndex];
1394   SMESH::OrientedPlane* aPlaneData = aPlane.Plane.GetPointer();
1395   aPlaneData->IsOpenGLClipping = toggled;
1396
1397   if( AutoApplyCheckBox->isChecked() )
1398     ClickOnApply();
1399 }
1400
1401 /*!
1402   SLOT: called on SelectAll check box toggled
1403 */
1404 void SMESHGUI_ClippingDlg::onSelectAll( int theState )
1405 {
1406   if( theState == Qt::PartiallyChecked ) {
1407     SelectAllCheckBox->setCheckState( Qt::Checked );
1408     return;
1409   }
1410
1411   bool anIsBlocked = ActorList->blockSignals( true );
1412   for( int i = 0, n = ActorList->count(); i < n; i++ ) {
1413     if( QListWidgetItem* anItem = ActorList->item( i ) ) {
1414       anItem->setCheckState( theState == Qt::Checked ? Qt::Checked : Qt::Unchecked );
1415       updateActorItem( anItem, false, true );
1416     }
1417   }
1418   SelectAllCheckBox->setTristate( false );
1419   ActorList->blockSignals( anIsBlocked );
1420   SetCurrentPlaneParam();
1421 }
1422
1423 /*!
1424   SLOT: called when actor item was changed
1425 */
1426 void SMESHGUI_ClippingDlg::onActorItemChanged( QListWidgetItem* theItem )
1427 {
1428   updateActorItem( theItem, true, true );
1429   SetCurrentPlaneParam();
1430 }
1431
1432 /*!
1433   Restore parameters of selected plane
1434 */
1435 void SMESHGUI_ClippingDlg::SetCurrentPlaneParam()
1436 {
1437   if ( myPlanes.empty() || myIsSelectPlane )
1438     return;
1439
1440   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1441
1442   SMESH::TPlaneData aPlaneData = myPlanes[aCurPlaneIndex];
1443   SMESH::OrientedPlane* aPlane = aPlaneData.Plane.GetPointer();
1444
1445   if ( aPlane->PlaneMode == SMESH::Absolute ) {
1446     aPlane->myAbsoluteOrientation = CBAbsoluteOrientation->currentIndex();
1447     aPlane->X = SpinBox_X->value();
1448     aPlane->Y = SpinBox_Y->value();
1449     aPlane->Z = SpinBox_Z->value();
1450     aPlane->Dx = SpinBox_Dx->value();
1451     aPlane->Dy = SpinBox_Dy->value();
1452     aPlane->Dz = SpinBox_Dz->value();
1453   }
1454
1455   double aNormal[3];
1456   double aDir[2][3] = { {0, 0, 0}, {0, 0, 0} };
1457   static double aCoeff = vtkMath::Pi()/180.0;
1458
1459   double aRot[2] = { getRotation1(), getRotation2() };
1460   int anOrient;
1461   if ( aPlane->PlaneMode == SMESH::Absolute )
1462         anOrient = CBAbsoluteOrientation->currentIndex();
1463   else if ( aPlane->PlaneMode == SMESH::Relative )
1464         anOrient = CBRelativeOrientation->currentIndex() + 1;
1465
1466   if ( aPlane->PlaneMode == SMESH::Relative ) {
1467     aPlane->myAngle[0] = aRot[0];
1468     aPlane->myAngle[1] = aRot[1];
1469     aPlane->SetOrientation( SMESH::Orientation( CBRelativeOrientation->currentIndex() ) );
1470     aPlane->SetDistance( getDistance() );
1471   }
1472
1473   if ( anOrient == 0 ) {
1474         // compute a direction for plane in absolute mode
1475     double znam = sqrt( aPlane->Dx*aPlane->Dx + aPlane->Dy*aPlane->Dy + aPlane->Dz*aPlane->Dz );
1476     double aRotation = acos( aPlane->Dy/znam )/aCoeff;
1477     if ( aPlane->Dy >= 0.0 && aPlane->Dz >= 0.0 )     aRot[0] = 90.0 + aRotation;
1478     else if ( aPlane->Dy >= 0.0 && aPlane->Dz < 0.0 ) aRot[0] = 90.0 - aRotation;
1479     else if ( aPlane->Dy < 0.0 && aPlane->Dz >= 0.0 ) aRot[0] = aRotation - 90.0;
1480     else if ( aPlane->Dy < 0.0 && aPlane->Dz < 0.0 )  aRot[0] = 270.0 - aRotation;
1481
1482     aRotation = acos( aPlane->Dx/znam )/aCoeff;
1483     if ( aPlane->Dx >= 0.0 && aPlane->Dz >= 0.0 )     aRot[1] = 90.0 + aRotation;
1484     else if ( aPlane->Dx >= 0.0 && aPlane->Dz < 0.0 ) aRot[1] = 90.0 - aRotation;
1485     else if ( aPlane->Dx < 0.0 && aPlane->Dz >= 0.0 ) aRot[1] = aRotation - 90.0;
1486     else if ( aPlane->Dx < 0.0 && aPlane->Dz < 0.0 )  aRot[1] = 270.0 - aRotation;
1487   }
1488
1489   // compute a normal
1490   rotationToNormal( aRot, anOrient, aNormal, aDir );
1491
1492
1493   SMESH::TActorList anActorList = aPlaneData.ActorList;
1494
1495   double aBounds[6];
1496   double anOrigin[3];
1497   double aDistance;
1498   aDistance = getDistance();
1499   if ( aPlane->PlaneMode == SMESH::Absolute ) {
1500     aNormal[0] = aPlane->Dx;
1501     aNormal[1] = aPlane->Dy;
1502     aNormal[2] = aPlane->Dz;
1503   }
1504
1505   bool anIsOk = SMESH::ComputeClippingPlaneParameters( anActorList,
1506                                                        aNormal,
1507                                                        aDistance,
1508                                                        aBounds,
1509                                                        anOrigin );
1510
1511   if ( aPlane->PlaneMode == SMESH::Absolute ) {
1512     anOrigin[0] = aPlane->X;
1513     anOrigin[1] = aPlane->Y;
1514     anOrigin[2] = aPlane->Z;
1515   }
1516   
1517   if( anIsOk ) {
1518     aPlane->SetNormal( aNormal );
1519     aPlane->SetOrigin( anOrigin );
1520
1521     double aPnt[3] = { ( aBounds[0] + aBounds[1] ) / 2.,
1522                        ( aBounds[2] + aBounds[3] ) / 2.,
1523                        ( aBounds[4] + aBounds[5] ) / 2. };
1524
1525     double aDel = pow( pow( aBounds[1] - aBounds[0], 2 ) +
1526                        pow( aBounds[3] - aBounds[2], 2 ) +
1527                        pow( aBounds[5] - aBounds[4], 2 ), 0.5 );
1528
1529     double aDelta[2][3] = { { aDir[0][0]*aDel, aDir[0][1]*aDel, aDir[0][2]*aDel },
1530                             { aDir[1][0]*aDel, aDir[1][1]*aDel, aDir[1][2]*aDel } };
1531     double aParam, aPnt0[3], aPnt1[3], aPnt2[3];
1532
1533     double aPnt01[3] = { aPnt[0] - aDelta[0][0] - aDelta[1][0],
1534                          aPnt[1] - aDelta[0][1] - aDelta[1][1],
1535                          aPnt[2] - aDelta[0][2] - aDelta[1][2] };
1536     double aPnt02[3] = { aPnt01[0] + aNormal[0],
1537                          aPnt01[1] + aNormal[1],
1538                          aPnt01[2] + aNormal[2] };
1539     vtkPlane::IntersectWithLine(aPnt01,aPnt02,aNormal,anOrigin,aParam,aPnt0);
1540
1541     double aPnt11[3] = { aPnt[0] - aDelta[0][0] + aDelta[1][0],
1542                          aPnt[1] - aDelta[0][1] + aDelta[1][1],
1543                          aPnt[2] - aDelta[0][2] + aDelta[1][2] };
1544     double aPnt12[3] = { aPnt11[0] + aNormal[0],
1545                          aPnt11[1] + aNormal[1],
1546                          aPnt11[2] + aNormal[2] };
1547     vtkPlane::IntersectWithLine(aPnt11,aPnt12,aNormal,anOrigin,aParam,aPnt1);
1548
1549     double aPnt21[3] = { aPnt[0] + aDelta[0][0] - aDelta[1][0],
1550                          aPnt[1] + aDelta[0][1] - aDelta[1][1],
1551                          aPnt[2] + aDelta[0][2] - aDelta[1][2] };
1552     double aPnt22[3] = { aPnt21[0] + aNormal[0],
1553                          aPnt21[1] + aNormal[1],
1554                          aPnt21[2] + aNormal[2] };
1555     vtkPlane::IntersectWithLine(aPnt21,aPnt22,aNormal,anOrigin,aParam,aPnt2);
1556
1557     vtkPlaneSource* aPlaneSource = aPlane->myPlaneSource;
1558
1559     aPlaneSource->SetNormal( aNormal[0], aNormal[1], aNormal[2] );
1560     aPlaneSource->SetOrigin( aPnt0[0], aPnt0[1], aPnt0[2] );
1561     aPlaneSource->SetPoint1( aPnt1[0], aPnt1[1], aPnt1[2] );
1562     aPlaneSource->SetPoint2( aPnt2[0], aPnt2[1], aPnt2[2] );
1563     aPlaneSource->Update();
1564   }
1565
1566   setBoundsForPreviewWidget();
1567
1568   myPreviewWidget->SetOrigin( anOrigin );
1569   myPreviewWidget->SetNormal( aNormal );
1570
1571   if(AutoApplyCheckBox->isChecked())
1572     ClickOnApply();
1573
1574   SMESH::RenderViewWindow( myViewWindow );
1575 }
1576
1577 /*!
1578   Set current bounds for preview widget
1579 */
1580 void SMESHGUI_ClippingDlg::setBoundsForPreviewWidget()
1581 {
1582   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1583   SMESH::TPlaneData aPlaneData = myPlanes[aCurPlaneIndex];
1584   SMESH::OrientedPlane* aPlane = aPlaneData.Plane.GetPointer();
1585   SMESH::TActorList anActorList = aPlaneData.ActorList;
1586
1587   double* anOrigin = aPlane->GetOrigin();
1588
1589   double aBounds[6];
1590   SMESH::ComputeBounds( anActorList, aBounds );
1591
1592   bool isBoundsChanged = false;
1593
1594   if( myIsPreviewMoved ) {
1595     // if widget has moved by hand the bounds can to minimize
1596     if( anOrigin[0] > myBounds[0] && anOrigin[0] < aBounds[0] ) {
1597       myBounds[0] = anOrigin[0]; isBoundsChanged = true; }
1598     if( anOrigin[0] < myBounds[1] && anOrigin[0] > aBounds[1] ) {
1599       myBounds[1] = anOrigin[0]; isBoundsChanged = true; }
1600     if( anOrigin[1] > myBounds[2] && anOrigin[1] < aBounds[2] ) {
1601       myBounds[2] = anOrigin[1]; isBoundsChanged = true; }
1602     if( anOrigin[1] < myBounds[3] && anOrigin[1] > aBounds[3] ) {
1603       myBounds[3] = anOrigin[1]; isBoundsChanged = true; }
1604     if( anOrigin[2] > myBounds[4] && anOrigin[2] < aBounds[4] ) {
1605       myBounds[4] = anOrigin[2]; isBoundsChanged = true; }
1606     if( anOrigin[2] < myBounds[5] && anOrigin[2] > aBounds[5] ) {
1607       myBounds[5] = anOrigin[2]; isBoundsChanged = true; }
1608   }
1609   else {
1610     // if widget has moved by dialog data the bounds can to take necessary size
1611     if( anOrigin[0] < aBounds[0] ) {
1612       myBounds[0] = anOrigin[0]; isBoundsChanged = true; }
1613     if( anOrigin[0] > aBounds[1] ) {
1614       myBounds[1] = anOrigin[0]; isBoundsChanged = true; }
1615     if( anOrigin[1] < aBounds[2] ) {
1616       myBounds[2] = anOrigin[1]; isBoundsChanged = true; }
1617     if( anOrigin[1] > aBounds[3] ) {
1618       myBounds[3] = anOrigin[1]; isBoundsChanged = true; }
1619     if( anOrigin[2] < aBounds[4] ) {
1620       myBounds[4] = anOrigin[2]; isBoundsChanged = true; }
1621     if( anOrigin[2] > aBounds[5] ) {
1622         myBounds[5] = anOrigin[2]; isBoundsChanged = true; }
1623   }
1624
1625   if( isBoundsChanged )
1626     myPreviewWidget->PlaceWidget( myBounds[0],myBounds[1],myBounds[2],
1627                                   myBounds[3],myBounds[4],myBounds[5] );
1628   else if( !myIsPreviewMoved )
1629     myPreviewWidget->PlaceWidget( aBounds[0],aBounds[1],aBounds[2],
1630                                   aBounds[3],aBounds[4],aBounds[5] );
1631
1632 }
1633
1634 /*!
1635   Convert absolute coordinates of plane to relative mode
1636 */
1637 void SMESHGUI_ClippingDlg::absolutePlaneToRelative ( double theOrigin[3], double theDir[3] )
1638 {
1639   double aRot[2];
1640
1641   aRot[0] = getRotation1();
1642   aRot[1] = getRotation2();
1643
1644   double eps = 0.0001;
1645
1646   int anOrientation = CBRelativeOrientation->currentIndex();
1647   double aDirection[3];
1648   double aRotation1, aRotation2;
1649   switch( anOrientation ) {
1650   case 0:
1651     aDirection[0] = theDir[0] + eps;
1652     aDirection[1] = theDir[1] + eps;
1653     aDirection[2] = theDir[2] + eps;
1654     aRotation1 = atan2( theDir[2], theDir[1] )*180.0/M_PI;
1655     aRotation2 = atan2( theDir[2], theDir[0] )*180.0/M_PI;
1656     break;
1657   case 1:
1658     aDirection[0] = theDir[1] + eps;
1659     aDirection[1] = theDir[2] + eps;
1660     aDirection[2] = theDir[0] + eps;
1661     aRotation1 = atan2( theDir[0], theDir[2] )*180.0/M_PI;
1662     aRotation2 = atan2( theDir[0], theDir[1] )*180.0/M_PI;
1663     break;
1664   case 2:
1665     aDirection[0] = theDir[2] + eps;
1666     aDirection[1] = theDir[0] + eps;
1667     aDirection[2] = theDir[1] + eps;
1668     aRotation1 = atan2( theDir[1], theDir[0] )*180.0/M_PI;
1669     aRotation2 = atan2( theDir[1], theDir[2] )*180.0/M_PI;
1670     break;
1671   }
1672
1673   if( aDirection[0] > 0 && aDirection[1] > 0 && aDirection[2] > 0 && aRot[0] <= 0 ) {
1674     aRot[0] = aRotation1 - 90.0;  aRot[1] = aRotation2 - 90.0; }
1675   else if( aDirection[0] > 0 && aDirection[1] > 0 && aDirection[2] > 0 && aRot[0] > 0 ) {
1676     aRot[0] = aRotation1 + 90.0;  aRot[1] = aRotation2 + 90.0; }
1677   else if( aDirection[0] > 0 && aDirection[1] > 0 && aDirection[2] < 0 && aRot[0] <= 0 ) {
1678     aRot[0] = aRotation1 - 90.0;  aRot[1] = aRotation2 + 90.0; }
1679   else if( aDirection[0] > 0 && aDirection[1] > 0 && aDirection[2] < 0 && aRot[0] > 0 ) {
1680     aRot[0] = aRotation1 + 90.0;  aRot[1] = aRotation2 - 90.0; }
1681   else if( aDirection[0] > 0 && aDirection[1] < 0 && aDirection[2] > 0 && aRot[0] <= 0 ) {
1682     aRot[0] = aRotation1 - 270.0; aRot[1] = aRotation2 + 90.0; }
1683   else if( aDirection[0] > 0 && aDirection[1] < 0 && aDirection[2] > 0 && aRot[0] > 0 ) {
1684     aRot[0] = aRotation1 - 90.0;  aRot[1] = aRotation2 - 90.0; }
1685   else if( aDirection[0] > 0 && aDirection[1] < 0 && aDirection[2] < 0 && aRot[0] <= 0 ) {
1686     aRot[0] = aRotation1 + 90.0;  aRot[1] = aRotation2 - 90.0; }
1687   else if( aDirection[0] > 0 && aDirection[1] < 0 && aDirection[2] < 0 && aRot[0] > 0 ) {
1688     aRot[0] = aRotation1 + 270.0; aRot[1] = aRotation2 + 90.0; }
1689   else if( aDirection[0] < 0 && aDirection[1] > 0 && aDirection[2] > 0 && aRot[0] <= 0 ) {
1690     aRot[0] = aRotation1 - 90.0;  aRot[1] = aRotation2 - 90.0; }
1691   else if( aDirection[0] < 0 && aDirection[1] > 0 && aDirection[2] > 0 && aRot[0] > 0 ) {
1692     aRot[0] = aRotation1 + 90.0;  aRot[1] = aRotation2 - 270.0; }
1693   else if( aDirection[0] < 0 && aDirection[1] > 0 && aDirection[2] < 0 && aRot[0] <= 0 ) {
1694     aRot[0] = aRotation1 - 90.0;  aRot[1] = aRotation2 + 90.0; }
1695   else if( aDirection[0] < 0 && aDirection[1] > 0 && aDirection[2] < 0 && aRot[0] > 0 ) {
1696     aRot[0] = aRotation1 + 90.0;  aRot[1] = aRotation2 + 270.0; }
1697   else if( aDirection[0] < 0 && aDirection[1] < 0 && aDirection[2] > 0 && aRot[0] <= 0  ) {
1698     aRot[0] = aRotation1 - 270.0; aRot[1] = aRotation2 - 270.0; }
1699   else if( aDirection[0] < 0 && aDirection[1] < 0 && aDirection[2] > 0 && aRot[0] > 0 ) {
1700     aRot[0] = aRotation1 - 90.0;  aRot[1] = aRotation2 - 90.0; }
1701   else if( aDirection[0] < 0 && aDirection[1] < 0 && aDirection[2] < 0 && aRot[0] <= 0  ) {
1702     aRot[0] = aRotation1 + 90.0;  aRot[1] = aRotation2 + 270.0; }
1703   else if( aDirection[0] < 0 && aDirection[1] < 0 && aDirection[2] < 0 && aRot[0] > 0 ) {
1704     aRot[0] = aRotation1 + 270.0; aRot[1] = aRotation2 + 90.0; }
1705
1706   SliderRotation1HasMoved( round( aRot[0] ) );
1707   SliderRotation1->setValue( round( aRot[0] ) );
1708   SliderRotation2HasMoved( round( aRot[1] ) );
1709   SliderRotation2->setValue( round( aRot[1] ) );
1710
1711   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1712   const SMESH::TPlaneData& aPlaneData = myPlanes[ aCurPlaneIndex ];
1713   const SMESH::TActorList& anActorList = aPlaneData.ActorList;
1714
1715   double aBounds[6];
1716   double aDist;
1717   SMESH::ComputeBounds( anActorList, aBounds );
1718   SMESH::PositionToDistance( aBounds, theDir, theOrigin, aDist );
1719   aDist = 1.0 - aDist;
1720   if( aDist>1.0 )
1721     aDist = 1.0;
1722   else if( aDist < 0.0 )
1723     aDist = 0.0;
1724
1725   SliderDistanceHasMoved( round( aDist*100 ) );
1726   SliderDistance->setValue( round( aDist*100 ) );
1727   return;
1728 }
1729
1730 /*!
1731   SLOT: called on preview check box toggled
1732 */
1733 void SMESHGUI_ClippingDlg::OnPreviewToggle (bool theIsToggled)
1734 {
1735   std::for_each( myPlanes.begin(), myPlanes.end(), TSetVisibility( theIsToggled ) );
1736   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1737   SMESH::TPlaneData aPlane = myPlanes[aCurPlaneIndex];
1738   SMESH::OrientedPlane* aPlaneData = aPlane.Plane.GetPointer();
1739   aPlaneData->myActor->SetVisibility( false );
1740   if( theIsToggled )
1741     myPreviewWidget->On();
1742   else
1743     myPreviewWidget->Off();
1744   SMESH::RenderViewWindow( myViewWindow );
1745 }
1746
1747 /*!
1748   SLOT: called on Auto Apply check box toggled
1749 */
1750 void SMESHGUI_ClippingDlg::onAutoApply(bool toggled)
1751 {
1752   if ( toggled ) ClickOnApply();
1753 }
1754
1755 /*!
1756   SLOT on ok button click: sets cutting plane and closes dialog
1757 */
1758 void SMESHGUI_ClippingDlg::ClickOnOk()
1759 {
1760   ClickOnApply();
1761   accept();
1762 }
1763
1764
1765 /*!
1766   SLOT on Apply button click: sets cutting plane and update viewer
1767 */
1768 void SMESHGUI_ClippingDlg::ClickOnApply()
1769 {
1770   if (myViewWindow) {
1771     SUIT_OverrideCursor wc;
1772
1773     QWidget *aCurrWid = this->focusWidget();
1774     aCurrWid->clearFocus();
1775     aCurrWid->setFocus();
1776
1777     SMESHGUI_ClippingPlaneInfoMap& aClippingPlaneInfoMap = mySMESHGUI->getClippingPlaneInfoMap();
1778     SMESHGUI_ClippingPlaneInfoList& aClippingPlaneInfoList = aClippingPlaneInfoMap[ myViewWindow->getViewManager() ];
1779
1780     // clean memory allocated for planes
1781     SMESHGUI_ClippingPlaneInfoList::iterator anIter1 = aClippingPlaneInfoList.begin();
1782     for( ; anIter1 != aClippingPlaneInfoList.end(); anIter1++ )
1783       if( SMESH::OrientedPlane* aPlane = (*anIter1).Plane )
1784         aPlane->Delete();
1785
1786     aClippingPlaneInfoList.clear();
1787
1788     VTK::ActorCollectionCopy aCopy( myViewWindow->getRenderer()->GetActors() );
1789     vtkActorCollection* anAllActors = aCopy.GetActors();
1790     anAllActors->InitTraversal();
1791     while( vtkActor* aVTKActor = anAllActors->GetNextActor() )
1792       if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) )
1793         anActor->RemoveAllClippingPlanes();
1794
1795     SMESH::TPlaneDataVector::iterator anIter2 = myPlanes.begin();
1796     for( ; anIter2 != myPlanes.end(); anIter2++ ) {
1797       SMESH::TPlaneData aPlaneData = *anIter2;
1798       SMESH::TPlane aPlane = aPlaneData.Plane;
1799       SMESH::TActorList anActorList = aPlaneData.ActorList;
1800
1801       // the check is disabled to support planes with empty actor list
1802       //if( anActorList.empty() )
1803       //  continue;
1804
1805       SMESH::OrientedPlane* anOrientedPlane = SMESH::OrientedPlane::New(myViewWindow);
1806       anOrientedPlane->ShallowCopy(aPlane.GetPointer());
1807       SMESH::TActorList::iterator anIter3 = anActorList.begin();
1808       for( ; anIter3 != anActorList.end(); anIter3++ )
1809         if( vtkActor* aVTKActor = *anIter3 )
1810           if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
1811                 if( anOrientedPlane->IsOpenGLClipping )
1812               anActor->AddOpenGLClippingPlane( anOrientedPlane->InvertPlane() );
1813                 else
1814                         anActor->AddClippingPlane( anOrientedPlane );
1815           }
1816
1817       SMESH::ClippingPlaneInfo aClippingPlaneInfo;
1818       aClippingPlaneInfo.Plane = anOrientedPlane;
1819       aClippingPlaneInfo.ActorList = anActorList;
1820
1821       aClippingPlaneInfoList.push_back( aClippingPlaneInfo );
1822     }
1823
1824     SMESH_Actor* anSMESHActor;
1825     anAllActors->InitTraversal();
1826     while( vtkActor* aVTKActor = anAllActors->GetNextActor() )
1827       if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
1828         anSMESHActor = anActor;
1829         anActor->SetOpenGLClippingPlane();
1830       }
1831
1832     SMESH::RenderViewWindow( myViewWindow );
1833   }
1834 }
1835
1836 /*!
1837   SLOT on help button click: opens a help page
1838 */
1839 void SMESHGUI_ClippingDlg::ClickOnHelp()
1840 {
1841   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
1842   if (app)
1843     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
1844   else {
1845                 QString platform;
1846 #ifdef WIN32
1847                 platform = "winapplication";
1848 #else
1849                 platform = "application";
1850 #endif
1851     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
1852                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
1853                              arg(app->resourceMgr()->stringValue("ExternalBrowser",
1854                                                                  platform)).
1855                              arg(myHelpFileName));
1856   }
1857 }
1858
1859 /*!
1860   SLOT: Called when value of slider distance change
1861 */
1862 void SMESHGUI_ClippingDlg::SliderDistanceHasMoved( int value )
1863 {
1864   double new_value = value/100.;
1865   TLValueDistance->setText( QString("%1").arg( new_value ) );
1866   SetCurrentPlaneParam();
1867 }
1868
1869 /*!
1870   SLOT: Called when value of slider rotation1 change
1871 */
1872 void SMESHGUI_ClippingDlg::SliderRotation1HasMoved( int value )
1873 {
1874   TLValueRotation1->setText( QString("%1\xB0").arg( value ) );
1875   SetCurrentPlaneParam();
1876 }
1877
1878 /*!
1879   SLOT: Called when value of slider rotation2 change
1880 */
1881 void SMESHGUI_ClippingDlg::SliderRotation2HasMoved( int value )
1882 {
1883   TLValueRotation2->setText( QString("%1\xB0").arg( value ) );
1884   SetCurrentPlaneParam();
1885 }
1886
1887 void SMESHGUI_ClippingDlg::onSelectAbsoluteOrientation( int mode )
1888 {
1889   bool isUserMode = (mode==0);
1890
1891   TextLabelX->setEnabled( isUserMode );
1892   TextLabelY->setEnabled( isUserMode );
1893   TextLabelZ->setEnabled( isUserMode );
1894
1895   SpinBox_X->setEnabled( isUserMode );
1896   SpinBox_Y->setEnabled( isUserMode );
1897   SpinBox_Z->setEnabled( isUserMode );
1898
1899   TextLabelDx->setEnabled( isUserMode );
1900   TextLabelDy->setEnabled( isUserMode );
1901   TextLabelDz->setEnabled( isUserMode );
1902
1903   SpinBox_Dx->setEnabled( isUserMode );
1904   SpinBox_Dy->setEnabled( isUserMode );
1905   SpinBox_Dz->setEnabled( isUserMode );
1906
1907   if ( isUserMode )
1908     return;
1909
1910   double aDx = 0, aDy = 0, aDz = 0;
1911
1912   if ( mode == 1 )
1913   {
1914     aDz = 1;
1915     TextLabelZ->setEnabled( true );
1916     SpinBox_Z->setEnabled( true );
1917     SpinBox_Z->setFocus();
1918   }
1919   else if ( mode == 2 )
1920   {
1921     aDx = 1;
1922     TextLabelX->setEnabled( true );
1923     SpinBox_X->setEnabled( true );
1924     SpinBox_X->setFocus();
1925   }
1926   else if ( mode == 3 )
1927   {
1928     aDy = 1;
1929     TextLabelY->setEnabled( true );
1930     SpinBox_Y->setEnabled( true );
1931     SpinBox_Y->setFocus();
1932   }
1933
1934   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1935   SMESH::TPlaneData aPlane = myPlanes[aCurPlaneIndex];
1936   SMESH::OrientedPlane* aPlaneData = aPlane.Plane.GetPointer();
1937
1938   if ( aPlaneData->IsInvert == true ) {
1939     aDx = -aDx; aDy = -aDy; aDz = -aDz;
1940   }
1941
1942   myIsSelectPlane = true;
1943   SpinBox_Dx->setValue( aDx );
1944   SpinBox_Dy->setValue( aDy );
1945   SpinBox_Dz->setValue( aDz );
1946   myIsSelectPlane = false;
1947
1948   SetCurrentPlaneParam();
1949 }
1950
1951 /*!
1952   SLOT: called on orientation of clipping plane in relative mode changed
1953 */
1954 void SMESHGUI_ClippingDlg::onSelectRelativeOrientation ( int theItem )
1955 {
1956   if ( myPlanes.empty() )
1957     return;
1958
1959   if ( theItem == 0 ) {
1960     TextLabelRotation1->setText( tr( "ROTATION_AROUND_X_Y2Z" ) );
1961     TextLabelRotation2->setText( tr( "ROTATION_AROUND_Y_X2Z" ) );
1962   }
1963   else if ( theItem == 1 ) {
1964     TextLabelRotation1->setText( tr( "ROTATION_AROUND_Y_Z2X" ) );
1965     TextLabelRotation2->setText( tr( "ROTATION_AROUND_Z_Y2X" ) );
1966   }
1967   else if ( theItem == 2 ) {
1968     TextLabelRotation1->setText( tr( "ROTATION_AROUND_Z_X2Y" ) );
1969     TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) );
1970   }
1971
1972   if( (QComboBox*)sender() == CBRelativeOrientation )
1973     SetCurrentPlaneParam();
1974 }
1975
1976 /*!
1977   SLOT on reset button click: sets default values
1978 */
1979 void SMESHGUI_ClippingDlg::onReset()
1980 {
1981   myIsSelectPlane = true;
1982   SpinBox_X->setValue(0);
1983   SpinBox_Y->setValue(0);
1984   SpinBox_Z->setValue(0);
1985   myIsSelectPlane = false;
1986
1987   SetCurrentPlaneParam();
1988 }
1989
1990 /*!
1991   SLOT on invert button click: inverts normal of cutting plane
1992 */
1993 void SMESHGUI_ClippingDlg::onInvert()
1994 {
1995   double Dx = SpinBox_Dx->value();
1996   double Dy = SpinBox_Dy->value();
1997   double Dz = SpinBox_Dz->value();
1998
1999   myIsSelectPlane = true;
2000   SpinBox_Dx->setValue( -Dx );
2001   SpinBox_Dy->setValue( -Dy );
2002   SpinBox_Dz->setValue( -Dz );
2003   myIsSelectPlane = false;
2004
2005   if ( !myPlanes.empty() ) {
2006     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
2007     SMESH::TPlaneData aPlane = myPlanes[aCurPlaneIndex];
2008     SMESH::OrientedPlane* aPlaneData = aPlane.Plane.GetPointer();
2009     aPlaneData->IsInvert = !aPlaneData->IsInvert;
2010   }
2011   SetCurrentPlaneParam();
2012 }
2013