Salome HOME
Implementation of the following issues:
[modules/gui.git] / src / OCCViewer / OCCViewer_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 #include "OCCViewer_ClippingDlg.h"
24
25 #include <QtxDoubleSpinBox.h>
26 #include <QtxAction.h>
27
28 #include "SUIT_Session.h"
29 #include "SUIT_ViewWindow.h"
30 #include "SUIT_ViewManager.h"
31 #include "OCCViewer_ClipPlane.h"
32 #include "OCCViewer_ViewWindow.h"
33 #include "OCCViewer_ViewPort3d.h"
34 #include "OCCViewer_ViewModel.h"
35
36 #include <V3d_View.hxx>
37 #include <Visual3d_View.hxx>
38 #include <Geom_Plane.hxx>
39 #include <Prs3d_Presentation.hxx>
40 #include <AIS_ListIteratorOfListOfInteractive.hxx>
41 #include <AIS_ListOfInteractive.hxx>
42 #include <AIS_InteractiveObject.hxx>
43 #include <AIS_InteractiveContext.hxx>
44 #include <IntAna_IntConicQuad.hxx>
45 #include <gp_Lin.hxx>
46 #include <gp_Pln.hxx>
47 #include <math.h>
48
49 // QT Includes
50 #include <QApplication>
51 #include <QGroupBox>
52 #include <QHBoxLayout>
53 #include <QVBoxLayout>
54 #include <QGridLayout>
55 #include <QLabel>
56 #include <QPushButton>
57 #include <QComboBox>
58 #include <QCheckBox>
59 #include <QStackedLayout>
60 #include <QSlider>
61 #include <QMenu>
62
63 /**********************************************************************************
64  ************************        Internal functions        ************************
65  *********************************************************************************/
66
67 void getMinMaxFromContext( Handle(AIS_InteractiveContext) ic,
68                            double  theDefaultSize,
69                            double& theXMin,
70                            double& theYMin,
71                            double& theZMin,
72                            double& theXMax,
73                            double& theYMax,
74                            double& theZMax) {
75
76   double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
77   aXMin = aYMin = aZMin = DBL_MAX;
78   aXMax = aYMax = aZMax = -DBL_MAX;
79   
80   bool isFound = false;
81   AIS_ListOfInteractive aList;
82   ic->DisplayedObjects( aList );
83   for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() ) {
84     Handle(AIS_InteractiveObject) anObj = it.Value();
85     if ( !anObj.IsNull() && anObj->HasPresentation() &&
86          !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) ) {
87       Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
88       if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() ) {
89         isFound = true;
90         double xmin, ymin, zmin, xmax, ymax, zmax;
91         aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
92         aXMin = qMin( aXMin, xmin );  aXMax = qMax( aXMax, xmax );
93         aYMin = qMin( aYMin, ymin );  aYMax = qMax( aYMax, ymax );
94         aZMin = qMin( aZMin, zmin );  aZMax = qMax( aZMax, zmax );
95       }
96     }
97   }
98
99   if(!isFound) {
100     if(theDefaultSize == 0.0)
101       theDefaultSize = 100.;
102     aXMin = aYMin = aZMin = -theDefaultSize;
103     aXMax = aYMax = aZMax = theDefaultSize;
104   }
105   theXMin = aXMin;theYMin = aYMin;theZMin = aZMin;
106   theXMax = aXMax;theYMax = aYMax;theZMax = aZMax;
107 }
108
109 /*!
110   Compute the point of bounding box and current clipping plane
111  */
112 void ComputeBoundsParam( double theBounds[6],
113                          double theDirection[3],
114                          double theMinPnt[3],
115                          double& theMaxBoundPrj,
116                          double& theMinBoundPrj )
117 {
118   //Enlarge bounds in order to avoid conflicts of precision
119   for(int i = 0; i < 6; i += 2) {
120     static double EPS = 1.0E-3;
121     double aDelta = (theBounds[i+1] - theBounds[i])*EPS;
122     theBounds[i] -= aDelta;
123     theBounds[i+1] += aDelta;
124   }
125
126   double aBoundPoints[8][3] = { { theBounds[0], theBounds[2], theBounds[4] },
127                                 { theBounds[1], theBounds[2], theBounds[4] },
128                                 { theBounds[0], theBounds[3], theBounds[4] },
129                                 { theBounds[1], theBounds[3], theBounds[4] },
130                                 { theBounds[0], theBounds[2], theBounds[5] },
131                                 { theBounds[1], theBounds[2], theBounds[5] },
132                                 { theBounds[0], theBounds[3], theBounds[5] },
133                                 { theBounds[1], theBounds[3], theBounds[5] } };
134
135   int aMaxId = 0;
136   theMaxBoundPrj = theDirection[0] * aBoundPoints[aMaxId][0] + theDirection[1] * aBoundPoints[aMaxId][1]
137                    + theDirection[2] * aBoundPoints[aMaxId][2];
138   theMinBoundPrj = theMaxBoundPrj;
139   for(int i = 1; i < 8; i++) {
140     double aTmp = theDirection[0] * aBoundPoints[i][0] + theDirection[1] * aBoundPoints[i][1]
141                   + theDirection[2] * aBoundPoints[i][2];
142     if(theMaxBoundPrj < aTmp) {
143       theMaxBoundPrj = aTmp;
144       aMaxId = i;
145     }
146     if(theMinBoundPrj > aTmp) {
147       theMinBoundPrj = aTmp;
148     }
149   }
150   double *aMinPnt = aBoundPoints[aMaxId];
151   theMinPnt[0] = aMinPnt[0];
152   theMinPnt[1] = aMinPnt[1];
153   theMinPnt[2] = aMinPnt[2];
154 }
155
156 /*!
157   Compute the position of current plane by distance
158  */
159 void DistanceToPosition( double theBounds[6],
160                          double theDirection[3],
161                          double theDist,
162                          double thePos[3] )
163 {
164   double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
165   ComputeBoundsParam( theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj );
166   double aLength = (aMaxBoundPrj - aMinBoundPrj)*theDist;
167   thePos[0] = aMinPnt[0] - theDirection[0]*aLength;
168   thePos[1] = aMinPnt[1] - theDirection[1]*aLength;
169   thePos[2] = aMinPnt[2] - theDirection[2]*aLength;
170 }
171
172 /*!
173   Compute the parameters of clipping plane
174  */
175 bool ComputeClippingPlaneParameters( double theNormal[3],
176                                      double theDist,
177                                      double theOrigin[3],
178                                      Handle(AIS_InteractiveContext) ic,
179                                      double theDefaultSize)
180 {
181   double aBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
182   getMinMaxFromContext(ic,theDefaultSize,aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5]);
183
184   DistanceToPosition( aBounds, theNormal, theDist, theOrigin );
185   return true;
186 }
187
188 /*!
189   Cross product of two 3-vectors. Result vector in result[3].
190  */
191 void Cross(const double first[3], const double second[3], double result[3])
192 {
193   result[0] = first[1]*second[2] - first[2]*second[1];
194   result[1] = first[2]*second[0] - first[0]*second[2];
195   result[2] = first[0]*second[1] - first[1]*second[0];
196 }
197
198 /*!
199   Compute relative clipping plane in absolute coordinates
200  */
201 void RelativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) ic, double theDefaultSize )
202 {
203   double aNormal[3];
204   double aDir[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };
205   {
206     static double aCoeff = M_PI/180.0;
207
208     double anU[2] = { cos( aCoeff * thePlane.RelativeMode.Rotation1 ), cos( aCoeff * thePlane.RelativeMode.Rotation2 ) };
209     double aV[2] = { sqrt( 1.0 - anU[0]*anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
210     aV[0] = thePlane.RelativeMode.Rotation1 > 0? aV[0]: -aV[0];
211     aV[1] = thePlane.RelativeMode.Rotation2 > 0? aV[1]: -aV[1];
212
213     switch ( thePlane.RelativeMode.Orientation ) {
214     case 0:
215       aDir[0][1] = anU[0];
216       aDir[0][2] = aV[0];
217       aDir[1][0] = anU[1];
218       aDir[1][2] = aV[1];
219       break;
220     case 1:
221       aDir[0][2] = anU[0];
222       aDir[0][0] = aV[0];
223       aDir[1][1] = anU[1];
224       aDir[1][0] = aV[1];
225       break;
226     case 2:
227       aDir[0][0] = anU[0];
228       aDir[0][1] = aV[0];
229       aDir[1][2] = anU[1];
230       aDir[1][1] = aV[1];
231       break;
232     }
233
234     Cross( aDir[1], aDir[0], aNormal );
235     // Normalize
236     double den;
237     den = sqrt( aNormal[0] * aNormal[0] + aNormal[1] * aNormal[1] + aNormal[2] * aNormal[2] );
238     if ( den != 0.0 ) {
239       for (int i=0; i < 3; i++) {
240         aNormal[i] /= den;
241       }
242     }
243     Cross( aNormal, aDir[1], aDir[0] );
244   }
245
246   double anOrigin[3];
247
248   anOrigin[0] = anOrigin[1] = anOrigin[2] = 0;
249   bool anIsOk = true;
250
251   anIsOk = ComputeClippingPlaneParameters( aNormal,
252                                            thePlane.RelativeMode.Distance,
253                                            anOrigin,
254                                            ic,
255                                            theDefaultSize );
256   if( !anIsOk )
257           return;
258   thePlane.X = anOrigin[0];
259   thePlane.Y = anOrigin[1];
260   thePlane.Z = anOrigin[2];
261   thePlane.Dx = aNormal[0];
262   thePlane.Dy = aNormal[1];
263   thePlane.Dz = aNormal[2];
264 }
265
266 /*!
267   Compute clipping plane size base point and normal
268  */
269
270 void clipPlaneParams(OCCViewer_ClipPlane& theClipPlane, Handle(AIS_InteractiveContext) theContext,
271                      double& theSize, gp_Pnt& theBasePnt, gp_Dir& theNormal, double defaultSize) {
272   double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
273   aXMin = aYMin = aZMin = DBL_MAX;
274   aXMax = aYMax = aZMax = -DBL_MAX;
275   
276   getMinMaxFromContext(theContext,defaultSize,aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
277   double aSize = 50;
278
279
280   gp_Pnt aBasePnt(theClipPlane.X ,  theClipPlane.Y ,  theClipPlane.Z);
281   gp_Dir aNormal(theClipPlane.Dx, theClipPlane.Dy, theClipPlane.Dz );
282
283   // compute clipping plane size
284   gp_Pnt aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
285   double aDiag = aCenter.Distance( gp_Pnt( aXMax, aYMax, aZMax ) )*2;
286   aSize = aDiag * 1.1;
287   
288   // compute clipping plane center ( redefine the base point )
289   IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
290   
291   intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
292
293   if ( intersector.IsDone() && intersector.NbPoints() == 1 )
294     aBasePnt = intersector.Point( 1 );
295   
296   theSize = aSize;
297   theBasePnt = aBasePnt;
298   theNormal = aNormal;
299 }
300
301
302 /*********************************************************************************
303  *********************      class OCCViewer_ClippingDlg      *********************
304  *********************************************************************************/
305 /*!
306   Constructor
307   \param view - view window
308   \param parent - parent widget
309 */
310 OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCViewer_Viewer* model)
311   : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
312     myCurrentClipPlaneMode (Absolute)
313 {
314   setObjectName( "OCCViewer_ClippingDlg" );
315   setModal( false );
316
317   setWindowTitle( tr( "Clipping" ) );
318
319   setAttribute (Qt::WA_DeleteOnClose, true);
320   
321   QVBoxLayout* topLayout = new QVBoxLayout( this );
322   topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
323
324   /***************************************************************/
325   // Controls for selecting, creating, deleting planes
326   QGroupBox* GroupPlanes = new QGroupBox( tr("CLIPPING_PLANES"), this );
327   QHBoxLayout* GroupPlanesLayout = new QHBoxLayout( GroupPlanes );
328   ComboBoxPlanes = new QComboBox( GroupPlanes );
329   isActivePlane = new QCheckBox( tr("IS_ACTIVE_PLANE"), this );
330   buttonNew = new QPushButton( tr("BTN_NEW"), GroupPlanes );
331   buttonDelete = new QPushButton( tr("BTN_DELETE"), GroupPlanes );
332   buttonDisableAll = new QPushButton( tr("BTN_DISABLE_ALL"), GroupPlanes );
333   MenuMode = new QMenu( "MenuMode", buttonNew );
334   MenuMode->addAction( tr( "ABSOLUTE" ), this, SLOT( onModeAbsolute() ) );
335   MenuMode->addAction( tr( "RELATIVE" ), this, SLOT( onModeRelative() ) );
336   buttonNew->setMenu( MenuMode );
337
338   GroupPlanesLayout->addWidget( ComboBoxPlanes );
339   GroupPlanesLayout->addWidget( isActivePlane );
340   GroupPlanesLayout->addWidget( buttonNew );
341   GroupPlanesLayout->addWidget( buttonDelete );
342   GroupPlanesLayout->addWidget( buttonDisableAll );
343
344   ModeStackedLayout = new QStackedLayout();
345
346   /**********************   Mode Absolute   **********************/
347   /* Controls for absolute mode of clipping plane:
348      X, Y, Z - coordinates of the intersection of cutting plane and the three axes
349      Dx, Dy, Dz - components of normal to the cutting plane
350      Orientation - direction of cutting plane
351    */
352   const double min = -1e+7;
353   const double max =  1e+7;
354   const double step = 5;
355   const int precision = -7;
356
357   // Croup Point
358   QGroupBox* GroupAbsolutePoint = new QGroupBox( this );
359   GroupAbsolutePoint->setObjectName( "GroupPoint" );
360   GroupAbsolutePoint->setTitle( tr("BASE_POINT") );
361   QGridLayout* GroupPointLayout = new QGridLayout( GroupAbsolutePoint );
362   GroupPointLayout->setAlignment( Qt::AlignTop );
363   GroupPointLayout->setSpacing( 6 ); GroupPointLayout->setMargin( 11 );
364
365   TextLabelX = new QLabel( GroupAbsolutePoint );
366   TextLabelX->setObjectName( "TextLabelX" );
367   TextLabelX->setText( tr("X:") );
368   GroupPointLayout->addWidget( TextLabelX, 0, 0 );
369   
370   SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
371   SpinBox_X->setObjectName("SpinBox_X" );
372   SpinBox_X->setPrecision( precision );
373   GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
374
375   TextLabelY = new QLabel( GroupAbsolutePoint );
376   TextLabelY->setObjectName( "TextLabelY" );
377   TextLabelY->setText( tr("Y:") );
378   GroupPointLayout->addWidget( TextLabelY, 0, 2 );
379
380   SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
381   SpinBox_Y->setObjectName("SpinBox_Y" );
382   SpinBox_Y->setPrecision( precision );
383   GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
384
385   TextLabelZ = new QLabel( GroupAbsolutePoint );
386   TextLabelZ->setObjectName( "TextLabelZ" );
387   TextLabelZ->setText( tr("Z:") );
388   GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
389
390   SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
391   SpinBox_Z->setObjectName("SpinBox_Z" );
392   SpinBox_Z->setPrecision( precision );
393   GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
394
395   resetButton  = new QPushButton( GroupAbsolutePoint );
396   resetButton->setObjectName( "resetButton" );
397   resetButton->setText( tr( "RESET"  ) );
398   GroupPointLayout->addWidget( resetButton, 0, 6 );
399
400   // Group Direction
401   GroupAbsoluteDirection = new QGroupBox( this );
402   GroupAbsoluteDirection->setObjectName( "GroupDirection" );
403   GroupAbsoluteDirection->setTitle( tr("DIRECTION") );
404   QGridLayout* GroupDirectionLayout = new QGridLayout( GroupAbsoluteDirection );
405   GroupDirectionLayout->setAlignment( Qt::AlignTop );
406   GroupDirectionLayout->setSpacing( 6 );
407   GroupDirectionLayout->setMargin( 11 );
408   
409   TextLabelDx = new QLabel( GroupAbsoluteDirection );
410   TextLabelDx->setObjectName( "TextLabelDx" );
411   TextLabelDx->setText( tr("Dx:") );
412   GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
413   
414   SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
415   SpinBox_Dx->setObjectName("SpinBox_Dx" );
416   SpinBox_Dx->setPrecision( precision );
417   GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
418
419   TextLabelDy = new QLabel( GroupAbsoluteDirection );
420   TextLabelDy->setObjectName( "TextLabelDy" );
421   TextLabelDy->setText( tr("Dy:") );
422   GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
423   
424   SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
425   SpinBox_Dy->setObjectName("SpinBox_Dy" );
426   SpinBox_Dy->setPrecision( precision );
427   GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
428
429   TextLabelDz = new QLabel( GroupAbsoluteDirection );
430   TextLabelDz->setObjectName( "TextLabelDz" );
431   TextLabelDz->setText( tr("Dz:") );
432   GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
433   
434   SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
435   SpinBox_Dz->setObjectName("SpinBox_Dz" );
436   SpinBox_Dz->setPrecision( precision );
437   GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
438
439   invertButton  = new QPushButton( GroupAbsoluteDirection );
440   invertButton->setObjectName( "invertButton" );
441   invertButton->setText( tr( "INVERT"  ) );
442   GroupDirectionLayout->addWidget( invertButton, 0, 6 );
443  
444   CBAbsoluteOrientation = new QComboBox( GroupAbsoluteDirection );
445   CBAbsoluteOrientation->setObjectName( "AbsoluteOrientation" );
446   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "CUSTOM" ) );
447   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||X-Y" ) );
448   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Y-Z" ) );
449   CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Z-X" ) );
450   GroupDirectionLayout->addWidget( CBAbsoluteOrientation, 1, 0, 1, 6 );
451
452   QVBoxLayout* ModeActiveLayout = new QVBoxLayout();
453   ModeActiveLayout->setMargin( 11 ); ModeActiveLayout->setSpacing( 6 );
454   ModeActiveLayout->addWidget( GroupAbsolutePoint );
455   ModeActiveLayout->addWidget( GroupAbsoluteDirection );
456
457   QWidget* ModeActiveWidget = new QWidget( this );
458   ModeActiveWidget->setLayout( ModeActiveLayout );
459
460   /**********************   Mode Relative   **********************/
461   /* Controls for relative mode of clipping plane:
462      Distance - Value from 0 to 1.
463      Specifies the distance from the minimum value in a given direction of bounding box to the current position
464      Rotation1, Rotation2 - turn angles of cutting plane in given directions
465      Orientation - direction of cutting plane
466    */
467   QGroupBox* GroupParameters = new QGroupBox( tr("PARAMETERS"), this );
468   QGridLayout* GroupParametersLayout = new QGridLayout( GroupParameters );
469   GroupParametersLayout->setMargin( 11 ); GroupParametersLayout->setSpacing( 6 );
470
471   TextLabelOrientation = new QLabel( tr("ORIENTATION"), GroupParameters);
472   TextLabelOrientation->setObjectName( "TextLabelOrientation" );
473   GroupParametersLayout->addWidget( TextLabelOrientation, 0, 0 );
474
475   CBRelativeOrientation = new QComboBox(GroupParameters);
476   CBRelativeOrientation->setObjectName( "RelativeOrientation" );
477   CBRelativeOrientation->addItem( tr("ALONG_XY") );
478   CBRelativeOrientation->addItem( tr("ALONG_YZ") );
479   CBRelativeOrientation->addItem( tr("ALONG_ZX") );
480   GroupParametersLayout->addWidget( CBRelativeOrientation, 0, 1 );
481
482   TLValueDistance = new QLabel( GroupParameters );
483   TLValueDistance->setObjectName( "TLValueDistance" );
484   TLValueDistance->setAlignment( Qt::AlignCenter );
485   TLValueDistance->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
486   QFont fnt = TLValueDistance->font(); fnt.setBold( true ); TLValueDistance->setFont( fnt );
487   GroupParametersLayout->addWidget( TLValueDistance, 1, 1 );
488
489   TextLabelDistance = new QLabel( tr("DISTANCE"), GroupParameters );
490   TextLabelDistance->setObjectName( "TextLabelDistance" );
491   GroupParametersLayout->addWidget( TextLabelDistance, 2, 0 );
492
493   SliderDistance = new QSlider( Qt::Horizontal, GroupParameters );
494   SliderDistance->setObjectName( "SliderDistance" );
495   SliderDistance->setFocusPolicy( Qt::NoFocus );
496   SliderDistance->setMinimumSize( 300, 0 );
497   SliderDistance->setMinimum( 0 );
498   SliderDistance->setMaximum( 100 );
499   SliderDistance->setSingleStep( 1 );
500   SliderDistance->setPageStep( 10 );
501   SliderDistance->setTracking( false );
502   GroupParametersLayout->addWidget( SliderDistance, 2, 1 );
503
504   TLValueRotation1 = new QLabel( GroupParameters );
505   TLValueRotation1->setObjectName( "TLValueRotation1" );
506   TLValueRotation1->setAlignment( Qt::AlignCenter );
507   TLValueRotation1->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
508   TLValueRotation1->setFont( fnt );
509   GroupParametersLayout->addWidget( TLValueRotation1, 3, 1 );
510
511   TextLabelRotation1 = new QLabel( tr("ROTATION_AROUND_X_Y2Z"), GroupParameters );
512   TextLabelRotation1->setObjectName( "TextLabelRotation1" );
513   GroupParametersLayout->addWidget( TextLabelRotation1, 4, 0 );
514
515   SliderRotation1 = new QSlider( Qt::Horizontal, GroupParameters );
516   SliderRotation1->setObjectName( "SliderRotation1" );
517   SliderRotation1->setFocusPolicy( Qt::NoFocus );
518   SliderRotation1->setMinimumSize( 300, 0 );
519   SliderRotation1->setMinimum( -180 );
520   SliderRotation1->setMaximum( 180 );
521   SliderRotation1->setSingleStep( 1 );
522   SliderRotation1->setPageStep( 10 );
523   SliderRotation1->setTracking(false);
524   GroupParametersLayout->addWidget( SliderRotation1, 4, 1 );
525
526   TLValueRotation2 = new QLabel( GroupParameters );
527   TLValueRotation2->setObjectName( "TLValueRotation2" );
528   TLValueRotation2->setAlignment( Qt::AlignCenter );
529   TLValueRotation2->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
530   TLValueRotation2->setFont( fnt );
531   GroupParametersLayout->addWidget( TLValueRotation2, 5, 1 );
532
533   TextLabelRotation2 = new QLabel(tr("ROTATION_AROUND_Y_X2Z"), GroupParameters);
534   TextLabelRotation2->setObjectName( "TextLabelRotation2" );
535   TextLabelRotation2->setObjectName( "TextLabelRotation2" );
536   GroupParametersLayout->addWidget( TextLabelRotation2, 6, 0 );
537
538   SliderRotation2 = new QSlider( Qt::Horizontal, GroupParameters );
539   SliderRotation2->setObjectName( "SliderRotation2" );
540   SliderRotation2->setFocusPolicy( Qt::NoFocus );
541   SliderRotation2->setMinimumSize( 300, 0 );
542   SliderRotation2->setMinimum( -180 );
543   SliderRotation2->setMaximum( 180 );
544   SliderRotation2->setSingleStep( 1 );
545   SliderRotation2->setPageStep( 10 );
546   SliderRotation2->setTracking(false);
547   GroupParametersLayout->addWidget( SliderRotation2, 6, 1 );
548
549   /***************************************************************/
550   QGroupBox* CheckBoxWidget = new QGroupBox( this );
551   QHBoxLayout* CheckBoxLayout = new QHBoxLayout( CheckBoxWidget );
552   
553   PreviewCheckBox = new QCheckBox( tr("PREVIEW"), CheckBoxWidget );
554   PreviewCheckBox->setObjectName( "PreviewCheckBox" );
555   PreviewCheckBox->setChecked( true );
556   CheckBoxLayout->addWidget( PreviewCheckBox, 0, Qt::AlignCenter );
557   
558   AutoApplyCheckBox = new QCheckBox( tr("AUTO_APPLY"), CheckBoxWidget );
559   AutoApplyCheckBox->setObjectName( "AutoApplyCheckBox" );
560   CheckBoxLayout->addWidget( AutoApplyCheckBox, 0, Qt::AlignCenter );
561
562   /***************************************************************/
563   QGroupBox* GroupButtons = new QGroupBox( this );
564   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons );
565   GroupButtonsLayout->setAlignment( Qt::AlignTop );
566   GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 );
567   
568   buttonOk = new QPushButton( GroupButtons );
569   buttonOk->setObjectName( "buttonOk" );
570   buttonOk->setText( tr( "BUT_APPLY_AND_CLOSE"  ) );
571   buttonOk->setAutoDefault( TRUE );
572   buttonOk->setDefault( TRUE );
573   GroupButtonsLayout->addWidget( buttonOk );
574
575   buttonApply = new QPushButton( GroupButtons );
576   buttonApply->setObjectName( "buttonApply" );
577   buttonApply->setText( tr( "BUT_APPLY"  ) );
578   buttonApply->setAutoDefault( TRUE );
579   buttonApply->setDefault( TRUE );
580   GroupButtonsLayout->addWidget( buttonApply );
581
582   GroupButtonsLayout->addStretch();
583   
584   buttonClose = new QPushButton( GroupButtons );
585   buttonClose->setObjectName( "buttonClose" );
586   buttonClose->setText( tr( "BUT_CLOSE"  ) );
587   buttonClose->setAutoDefault( TRUE );
588   GroupButtonsLayout->addWidget( buttonClose );
589
590   QPushButton* buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons );
591   buttonHelp->setAutoDefault( TRUE );
592   GroupButtonsLayout->addWidget( buttonHelp );
593
594   /***************************************************************/
595   ModeStackedLayout->addWidget( ModeActiveWidget );
596   ModeStackedLayout->addWidget( GroupParameters );
597
598   topLayout->addWidget( GroupPlanes );
599   topLayout->addLayout( ModeStackedLayout );
600   topLayout->addWidget( CheckBoxWidget );
601   topLayout->addWidget( GroupButtons );
602
603   this->setLayout( topLayout );
604
605   // Initializations
606   initParam();
607
608   // Signals and slots connections
609   connect( ComboBoxPlanes, SIGNAL( activated( int ) ), this, SLOT( onSelectPlane( int ) ) );
610   connect( isActivePlane,  SIGNAL ( toggled ( bool ) ),  this, SLOT( onValueChanged() ) );
611   connect( buttonNew, SIGNAL( clicked() ), buttonNew, SLOT( showMenu() ) );
612   connect( buttonDelete, SIGNAL( clicked() ), this, SLOT( ClickOnDelete() ) );
613   connect( buttonDisableAll, SIGNAL( clicked() ), this, SLOT( ClickOnDisableAll() ) );
614
615   connect( resetButton,  SIGNAL (clicked() ), this, SLOT( onReset() ) );
616   connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
617   connect( SpinBox_X,  SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
618   connect( SpinBox_Y,  SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
619   connect( SpinBox_Z,  SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
620   connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
621   connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
622   connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
623   connect( CBAbsoluteOrientation, SIGNAL ( activated ( int ) ), this, SLOT( onOrientationAbsoluteChanged( int ) ) ) ;
624
625   connect( CBRelativeOrientation, SIGNAL( activated( int ) ), this, SLOT( onOrientationRelativeChanged( int ) ) );
626   connect( SliderDistance,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderDistanceHasMoved( int ) ) );
627   connect( SliderDistance,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderDistanceHasMoved( int ) ) );
628   connect( SliderRotation1,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderRotation1HasMoved( int ) ) );
629   connect( SliderRotation1,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderRotation1HasMoved( int ) ) );
630   connect( SliderRotation2,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderRotation2HasMoved( int ) ) );
631   connect( SliderRotation2,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderRotation2HasMoved( int ) ) );
632
633   connect( PreviewCheckBox, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
634   connect( AutoApplyCheckBox, SIGNAL ( toggled( bool ) ), this, SLOT( onAutoApply( bool ) ) );
635   
636   connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
637   connect( buttonOk, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
638   connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
639   connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) );
640
641   myBusy = false;
642   myIsSelectPlane = false;
643   myIsPlaneCreation = false;
644   myModel = model;
645
646   myModel->getViewer3d()->InitActiveViews();
647
648   myLocalPlanes = myModel->getClipPlanes();
649   synchronize();
650 }
651
652 /*!
653   Destructor
654   Destroys the object and frees any allocated resources
655 */
656 OCCViewer_ClippingDlg::~OCCViewer_ClippingDlg()
657 {
658   myLocalPlanes.clear();
659 }
660
661 /*!
662   Custom handling of close event: erases preview
663 */
664 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
665 {
666   erasePreview();
667   QDialog::closeEvent( e );
668   OCCViewer_ViewWindow* v = qobject_cast<OCCViewer_ViewWindow*>(parent());
669   if(v)
670     v->onClipping(false);
671 }
672
673 /*!
674   Custom handling of show event: displays preview
675 */
676 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
677 {
678   QDialog::showEvent( e );
679   onPreview( PreviewCheckBox->isChecked() );
680 }
681
682 /*!
683   Custom handling of hide event: erases preview
684 */
685 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
686 {
687   erasePreview();
688   QDialog::hideEvent( e );
689   OCCViewer_ViewWindow* v = qobject_cast<OCCViewer_ViewWindow*>(parent());
690   if(v)
691     v->onClipping(false);
692
693 }
694
695 /*!
696   Initialization of initial values of widgets
697 */
698 void OCCViewer_ClippingDlg::initParam()
699 {
700   SpinBox_X->setValue( 0.0 );
701   SpinBox_Y->setValue( 0.0 );
702   SpinBox_Z->setValue( 0.0 );
703
704   SpinBox_Dx->setValue( 1.0 );
705   SpinBox_Dy->setValue( 1.0 );
706   SpinBox_Dz->setValue( 1.0 );
707
708   CBAbsoluteOrientation->setCurrentIndex(0);
709
710   TLValueDistance->setText( "0.5" );
711   TLValueRotation1->setText( "0\xB0" );
712   TLValueRotation2->setText( "0\xB0" );
713   CBRelativeOrientation->setCurrentIndex( 0 );
714   SliderDistance->setValue( 50 );
715   SliderRotation1->setValue( 0 );
716   SliderRotation2->setValue( 0 );
717 }
718
719 /*!
720   Synchronize dialog's widgets with data
721 */
722 void OCCViewer_ClippingDlg::synchronize()
723 {
724   ComboBoxPlanes->clear();
725   int aNbPlanesAbsolute = myLocalPlanes.size();
726
727   QString aName;
728   for(int i = 1; i<=aNbPlanesAbsolute; i++ ) {
729     aName = QString("Plane %1").arg(i);
730     ComboBoxPlanes->addItem( aName );
731   }
732
733   int aPos = ComboBoxPlanes->count() - 1;
734   ComboBoxPlanes->setCurrentIndex( aPos );
735
736   bool anIsControlsEnable = ( aPos >= 0 );
737   if ( anIsControlsEnable ) {
738     onSelectPlane( aPos );
739   }
740   else {
741     ComboBoxPlanes->addItem( tr( "NO_PLANES" ) );
742     initParam();
743   }
744   if ( myCurrentClipPlaneMode == Absolute ) {
745     SpinBox_X->setEnabled( anIsControlsEnable );
746     SpinBox_Y->setEnabled( anIsControlsEnable );
747     SpinBox_Z->setEnabled( anIsControlsEnable );
748     SpinBox_Dx->setEnabled( anIsControlsEnable );
749     SpinBox_Dy->setEnabled( anIsControlsEnable );
750     SpinBox_Dz->setEnabled( anIsControlsEnable );
751     CBAbsoluteOrientation->setEnabled( anIsControlsEnable );
752     invertButton->setEnabled( anIsControlsEnable );
753     resetButton->setEnabled( anIsControlsEnable );
754   }
755   else if( myCurrentClipPlaneMode == Relative ) {
756     CBRelativeOrientation->setEnabled( anIsControlsEnable );
757     SliderDistance->setEnabled( anIsControlsEnable );
758     SliderRotation1->setEnabled( anIsControlsEnable );
759     SliderRotation2->setEnabled( anIsControlsEnable );
760     isActivePlane->setEnabled( anIsControlsEnable );
761   }
762   isActivePlane->setEnabled( anIsControlsEnable );
763 }
764
765 /*!
766   Displays preview of clipping plane
767 */
768 void OCCViewer_ClippingDlg::displayPreview()
769 {
770   if ( myBusy || !isValid() || !myModel)
771     return;
772
773   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
774   
775   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
776
777   for ( int i=0; i < clipPlanesCount(); i++ ) {
778   OCCViewer_ClipPlane& aClipPlane = getClipPlane(i);
779     if ( aClipPlane.IsOn ) {
780       Handle(AIS_Plane) myPreviewPlane;
781       double aSize;
782       gp_Pnt aBasePnt;
783       gp_Dir aNormal;
784       clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
785       myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
786       myPreviewPlane->SetSize( aSize, aSize );
787       ic->Display( myPreviewPlane, 1, -1, false );
788       ic->SetWidth( myPreviewPlane, 10, false );
789       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
790       ic->SetTransparency( myPreviewPlane, 0.5, false );
791       Quantity_Color c = (aCurPlaneIndex == i) ? Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ) : Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB );
792       ic->SetColor( myPreviewPlane, c , false );
793       myPreviewPlaneVector.push_back( myPreviewPlane );
794     }
795   }
796   myModel->update();
797 }
798
799 void OCCViewer_ClippingDlg::updatePreview() {
800   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
801   int count = clipPlanesCount();
802   if ( myBusy || 
803        !isValid() || 
804        myIsPlaneCreation ||
805        !myModel || 
806        count == 0 || 
807        (aCurPlaneIndex +1 > count) ||
808        !PreviewCheckBox->isChecked())
809     return;
810   
811   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
812   
813   OCCViewer_ClipPlane& aClipPlane = getClipPlane(aCurPlaneIndex);
814   Handle(AIS_Plane) myPreviewPlane;
815
816   if (aClipPlane.IsOn) {
817     double aSize;
818     gp_Pnt aBasePnt;
819     gp_Dir aNormal;
820     clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
821     if(myPreviewPlaneVector.size() < clipPlanesCount()) {
822       myPreviewPlaneVector.resize(clipPlanesCount());
823     }
824     myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
825     if(myPreviewPlane.IsNull()) {
826       //Plane was not created 
827       myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
828       myPreviewPlane->SetSize( aSize, aSize );
829       ic->Display( myPreviewPlane, 1, -1, false );
830       ic->SetWidth( myPreviewPlane, 10, false );
831       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
832       ic->SetTransparency( myPreviewPlane, 0.5, false );
833       myPreviewPlaneVector[aCurPlaneIndex] = myPreviewPlane;
834     } else {      
835       myPreviewPlane->SetComponent(new Geom_Plane( aBasePnt, aNormal ));
836       myPreviewPlane->SetSize( aSize, aSize );  
837     }
838
839     ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false );
840   } else {
841     if(myPreviewPlaneVector.size() > aCurPlaneIndex ) {
842       myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
843       if(ic->IsDisplayed(myPreviewPlane)) {
844         ic->Erase( myPreviewPlane, false );
845         ic->Remove( myPreviewPlane, false );
846       }
847       myPreviewPlaneVector[aCurPlaneIndex].Nullify();
848     }
849   }
850   for(int i = 0; i < myPreviewPlaneVector.size(); i++) {
851     if( i == aCurPlaneIndex ) continue;
852     if(!myPreviewPlaneVector[i].IsNull())
853       ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );  
854   }
855   myModel->update();
856 }
857
858 /*!
859   Erases preview of clipping plane
860 */
861 void OCCViewer_ClippingDlg::erasePreview()
862 {
863   if ( !myModel )
864     return;
865
866   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
867
868   for ( int i=0; i < myPreviewPlaneVector.size(); i++ ) {
869   Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[i];
870     if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
871       ic->Erase( myPreviewPlane, false );
872       ic->Remove( myPreviewPlane, false );
873       myPreviewPlane.Nullify();
874     }
875   }
876   myPreviewPlaneVector.clear();
877   myModel->update();
878 }
879
880 /*!
881   Return true if plane parameters are valid
882 */
883 bool OCCViewer_ClippingDlg::isValid()
884 {
885   return ( SpinBox_Dx->value() !=0 || SpinBox_Dy->value() !=0 || SpinBox_Dz->value() !=0 );
886 }
887
888 /*!
889   Update view after changes
890 */
891 void OCCViewer_ClippingDlg::updateClipping()
892 {
893   if (PreviewCheckBox->isChecked() || AutoApplyCheckBox->isChecked())
894   {
895     if (AutoApplyCheckBox->isChecked()) {
896       onApply();
897     }
898     
899     if (!PreviewCheckBox->isChecked())
900       myModel->update();
901     else 
902       updatePreview();
903   }
904 }
905
906 /*!
907   SLOT on new button click: create a new clipping plane
908 */
909 void OCCViewer_ClippingDlg::ClickOnNew()
910 {
911
912   OCCViewer_ClipPlane aPlane;
913   aPlane.PlaneMode = (ClipPlaneMode )myCurrentClipPlaneMode;
914   myLocalPlanes.push_back(aPlane);
915   synchronize();
916 }
917
918 /*!
919   SLOT on delete button click: Delete selected clipping plane
920 */
921 void OCCViewer_ClippingDlg::ClickOnDelete()
922 {
923   int aPlaneIndex = ComboBoxPlanes->currentIndex();
924   if ( (clipPlanesCount() == 0) || (aPlaneIndex+1 > clipPlanesCount()))
925     return;
926
927   myLocalPlanes.erase(myLocalPlanes.begin() + aPlaneIndex);
928
929   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
930
931   if(aPlaneIndex+1 <= myPreviewPlaneVector.size()) {
932     Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[aPlaneIndex];
933     if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
934       ic->Erase( myPreviewPlane, false );
935       ic->Remove( myPreviewPlane, false );
936     }
937     myPreviewPlaneVector.erase(myPreviewPlaneVector.begin() + aPlaneIndex);
938   }
939   synchronize();
940   if (AutoApplyCheckBox->isChecked()) {
941     onApply();
942   }
943   myModel->update();
944 }
945
946 /*!
947   SLOT on disable all button click: Restore initial state of viewer,
948   erase all clipping planes
949 */
950 void OCCViewer_ClippingDlg::ClickOnDisableAll()
951 {
952   AutoApplyCheckBox->setChecked (false);
953   int aClipPlanesCount = clipPlanesCount();
954   for ( int anIndex = 0; anIndex < aClipPlanesCount; anIndex++)
955   {
956     OCCViewer_ClipPlane& aPlane = getClipPlane(anIndex);
957     aPlane.IsOn = false;
958   }
959   erasePreview();
960   isActivePlane->setChecked(false);
961   myModel->setClipPlanes(myLocalPlanes);
962   myModel->update();
963 }
964
965 /*!
966   SLOT on ok button click: sets cutting plane and closes dialog
967 */
968 void OCCViewer_ClippingDlg::ClickOnOk()
969 {
970   onApply();
971   ClickOnClose();
972 }
973
974 /*!
975   SLOT on Apply button click: sets cutting plane and update viewer
976 */
977 void OCCViewer_ClippingDlg::ClickOnApply()
978 {
979   onApply();
980   myModel->update();
981 }
982
983 /*!
984   SLOT on close button click: erases preview and rejects dialog
985 */
986 void OCCViewer_ClippingDlg::ClickOnClose()
987 {
988   erasePreview();
989   OCCViewer_ViewWindow* v = qobject_cast<OCCViewer_ViewWindow*>(parent());
990   if(v)
991     v->onClipping(false);
992 }
993
994 /*!
995   SLOT on help button click: opens a help page
996 */
997 void OCCViewer_ClippingDlg::ClickOnHelp()
998 {
999   SUIT_Application* app = SUIT_Session::session()->activeApplication();
1000   if ( app )
1001     app->onHelpContextModule( "GUI", "occ_3d_viewer_page.html", "clipping_planes" );
1002 }
1003
1004 /*!
1005   Set absolute mode of clipping plane
1006 */
1007 void OCCViewer_ClippingDlg::onModeAbsolute()
1008 {
1009   myIsPlaneCreation = true;
1010   ModeStackedLayout->setCurrentIndex(0);
1011   myCurrentClipPlaneMode = Absolute;
1012   ClickOnNew();
1013   myIsPlaneCreation = false;
1014   updateClipping();
1015 }
1016
1017 /*!
1018   Set relative mode of clipping plane
1019 */
1020 void OCCViewer_ClippingDlg::onModeRelative()
1021 {
1022   myIsPlaneCreation = true;
1023   ModeStackedLayout->setCurrentIndex(1);
1024   myCurrentClipPlaneMode = Relative;
1025   ClickOnNew();
1026   myIsPlaneCreation = false;
1027   SetCurrentPlaneParam();
1028   updateClipping();
1029 }
1030
1031 /*!
1032   SLOT: called on value of clipping plane changed
1033 */
1034 void OCCViewer_ClippingDlg::onValueChanged()
1035 {
1036   SetCurrentPlaneParam();
1037   if ( myIsSelectPlane )
1038     return;
1039   updateClipping();
1040 }
1041
1042 /*!
1043   Set current parameters of selected plane
1044 */
1045 void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
1046 {
1047   if ( clipPlanesCount() == 0 )
1048     return;
1049
1050   OCCViewer_ClipPlane& aClipPlane = getClipPlane (theIndex);
1051
1052   myIsSelectPlane = true;
1053   if ( aClipPlane.PlaneMode == Absolute ) {
1054     ModeStackedLayout->setCurrentIndex( 0 );
1055     myCurrentClipPlaneMode = Absolute;
1056     int anOrientation = aClipPlane.Orientation;
1057     // Set plane parameters in the dialog
1058     SpinBox_X->setValue( aClipPlane.X );
1059     SpinBox_Y->setValue( aClipPlane.Y );
1060     SpinBox_Z->setValue( aClipPlane.Z );
1061     SpinBox_Dx->setValue( aClipPlane.Dx );
1062     SpinBox_Dy->setValue( aClipPlane.Dy );
1063     SpinBox_Dz->setValue( aClipPlane.Dz );
1064     CBAbsoluteOrientation->setCurrentIndex( anOrientation );
1065     onOrientationAbsoluteChanged( anOrientation );
1066   }
1067   else if( aClipPlane.PlaneMode == Relative ) {
1068     ModeStackedLayout->setCurrentIndex( 1 );
1069     myCurrentClipPlaneMode = Relative;
1070     int anOrientation = aClipPlane.RelativeMode.Orientation;
1071     // Set plane parameters in the dialog
1072     SliderDistance->setValue( aClipPlane.RelativeMode.Distance*100 );
1073     TLValueDistance->setText( QString::number(aClipPlane.RelativeMode.Distance ) );
1074     SliderRotation1->setValue( aClipPlane.RelativeMode.Rotation1 );
1075     TLValueRotation1->setText( QString( "%1\xB0" ).arg( aClipPlane.RelativeMode.Rotation1 ) );
1076     SliderRotation2->setValue( aClipPlane.RelativeMode.Rotation2 );
1077     TLValueRotation2->setText( QString( "%1\xB0" ).arg( aClipPlane.RelativeMode.Rotation2 ) );
1078     CBRelativeOrientation->setCurrentIndex( anOrientation );
1079     onOrientationRelativeChanged( anOrientation );
1080   }
1081   
1082   isActivePlane->setChecked( aClipPlane.IsOn );
1083   ComboBoxPlanes->setCurrentIndex( theIndex );
1084   myIsSelectPlane = false;
1085 }
1086
1087 /*!
1088   Restore parameters of selected plane
1089 */
1090 void OCCViewer_ClippingDlg::SetCurrentPlaneParam()
1091 {
1092   if ( clipPlanesCount() == 0 || myIsSelectPlane )
1093     return;
1094
1095   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1096
1097  OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
1098
1099   if ( aPlane.PlaneMode == Absolute ) {
1100     aPlane.Orientation = CBAbsoluteOrientation->currentIndex();
1101     aPlane.X = SpinBox_X->value();
1102     aPlane.Y = SpinBox_Y->value();
1103     aPlane.Z = SpinBox_Z->value();
1104     aPlane.Dx = SpinBox_Dx->value();
1105     aPlane.Dy = SpinBox_Dy->value();
1106     aPlane.Dz = SpinBox_Dz->value();
1107   }
1108   else if( aPlane.PlaneMode == Relative ) {
1109     aPlane.RelativeMode.Orientation = CBRelativeOrientation->currentIndex();
1110     aPlane.RelativeMode.Distance = TLValueDistance->text().toDouble();
1111     aPlane.RelativeMode.Rotation1 = TLValueRotation1->text().remove("\xB0").toInt();
1112     aPlane.RelativeMode.Rotation2 = TLValueRotation2->text().remove("\xB0").toInt();
1113     RelativePlaneToAbsolute (aPlane, myModel->getAISContext(),myModel->trihedronSize() );
1114   }
1115   aPlane.IsOn  = isActivePlane->isChecked();
1116 }
1117
1118 /*!
1119   SLOT on reset button click: sets default values
1120 */
1121 void OCCViewer_ClippingDlg::onReset()
1122 {
1123   myBusy = true;
1124   SpinBox_X->setValue(0);
1125   SpinBox_Y->setValue(0);
1126   SpinBox_Z->setValue(0);
1127   myBusy = false;
1128
1129   updateClipping();
1130 }
1131
1132 /*!
1133   SLOT on invert button click: inverts normal of cutting plane
1134 */
1135 void OCCViewer_ClippingDlg::onInvert()
1136 {
1137   double Dx = SpinBox_Dx->value();
1138   double Dy = SpinBox_Dy->value();
1139   double Dz = SpinBox_Dz->value();
1140
1141   myBusy = true;
1142   SpinBox_Dx->setValue( -Dx );
1143   SpinBox_Dy->setValue( -Dy );
1144   SpinBox_Dz->setValue( -Dz );
1145   myBusy = false;
1146
1147   if ( clipPlanesCount() != 0 ) {
1148     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1149     OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
1150     aPlane.IsInvert = !aPlane.IsInvert;
1151   }
1152   updateClipping();
1153 }
1154
1155 /*!
1156   SLOT: called on orientation of clipping plane in absolute mode changed
1157 */
1158 void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode )
1159 {
1160   bool isUserMode = (mode==0);
1161
1162   TextLabelX->setEnabled( isUserMode );
1163   TextLabelY->setEnabled( isUserMode );
1164   TextLabelZ->setEnabled( isUserMode );
1165
1166   SpinBox_X->setEnabled( isUserMode );
1167   SpinBox_Y->setEnabled( isUserMode );
1168   SpinBox_Z->setEnabled( isUserMode );
1169
1170   TextLabelDx->setEnabled( isUserMode );
1171   TextLabelDy->setEnabled( isUserMode );
1172   TextLabelDz->setEnabled( isUserMode );
1173
1174   SpinBox_Dx->setEnabled( isUserMode );
1175   SpinBox_Dy->setEnabled( isUserMode );
1176   SpinBox_Dz->setEnabled( isUserMode );
1177
1178   if ( !isUserMode ) {
1179
1180     double aDx = 0, aDy = 0, aDz = 0;
1181
1182     if ( mode == 1 )
1183       {
1184         aDz = 1;
1185         TextLabelZ->setEnabled( true );
1186         SpinBox_Z->setEnabled( true );
1187         SpinBox_Z->setFocus();
1188       }
1189     else if ( mode == 2 )
1190       {
1191         aDx = 1;
1192         TextLabelX->setEnabled( true );
1193         SpinBox_X->setEnabled( true );
1194         SpinBox_X->setFocus();
1195       }
1196     else if ( mode == 3 )
1197       {
1198         aDy = 1;
1199         TextLabelY->setEnabled( true );
1200         SpinBox_Y->setEnabled( true );
1201         SpinBox_Y->setFocus();
1202       }
1203     
1204     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1205     OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
1206     if ( aPlane.IsInvert == true ) {
1207       aDx = -aDx; aDy = -aDy; aDz = -aDz;
1208     }
1209     
1210     myBusy = true;
1211     SpinBox_Dx->setValue( aDx );
1212     SpinBox_Dy->setValue( aDy );
1213     SpinBox_Dz->setValue( aDz );
1214     myBusy = false;
1215   }
1216   SetCurrentPlaneParam();
1217   updateClipping();
1218 }
1219
1220 /*!
1221   SLOT: called on orientation of clipping plane in relative mode changed
1222 */
1223 void OCCViewer_ClippingDlg::onOrientationRelativeChanged (int theItem)
1224 {
1225   if ( clipPlanesCount() == 0 )
1226     return;
1227   
1228   if ( theItem == 0 ) {
1229     TextLabelRotation1->setText( tr( "ROTATION_AROUND_X_Y2Z" ) );
1230     TextLabelRotation2->setText( tr( "ROTATION_AROUND_Y_X2Z" ) );
1231   }
1232   else if ( theItem == 1 ) {
1233     TextLabelRotation1->setText( tr( "ROTATION_AROUND_Y_Z2X" ) );
1234     TextLabelRotation2->setText( tr( "ROTATION_AROUND_Z_Y2X" ) );
1235   }
1236   else if ( theItem == 2 ) {
1237     TextLabelRotation1->setText( tr( "ROTATION_AROUND_Z_X2Y" ) );
1238     TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) );
1239   }
1240
1241   if( (QComboBox*)sender() == CBRelativeOrientation )
1242     SetCurrentPlaneParam();
1243   updateClipping();
1244 }
1245
1246 /*!
1247   SLOT: called on preview check box toggled
1248 */
1249 void OCCViewer_ClippingDlg::onPreview( bool on )
1250 {
1251   erasePreview();
1252   if ( on ) 
1253     displayPreview();
1254 }
1255
1256 /*!
1257   SLOT: called on Auto Apply check box toggled
1258 */
1259 void OCCViewer_ClippingDlg::onAutoApply( bool toggled )
1260 {
1261   if ( toggled ) {
1262     onApply();
1263     myModel->update();
1264   }  
1265 }
1266
1267 /*!
1268   SLOT on Apply button click: sets cutting plane
1269 */
1270 void OCCViewer_ClippingDlg::onApply()
1271 {
1272   if ( myBusy )
1273     return;
1274   myIsSelectPlane = true;
1275
1276   qApp->processEvents();
1277   QApplication::setOverrideCursor( Qt::WaitCursor );
1278   qApp->processEvents();
1279
1280   myModel->setClipPlanes(myLocalPlanes);
1281
1282   QApplication::restoreOverrideCursor();
1283   myIsSelectPlane = false;
1284 }
1285
1286 /*!
1287   SLOT: Called when value of slider distance change
1288 */
1289 void OCCViewer_ClippingDlg::SliderDistanceHasMoved( int value )
1290 {
1291   double new_value = value/100.;
1292   TLValueDistance->setText( QString("%1").arg( new_value ) );
1293   onValueChanged();
1294 }
1295
1296 /*!
1297   SLOT: Called when value of slider rotation1 change
1298 */
1299 void OCCViewer_ClippingDlg::SliderRotation1HasMoved( int value )
1300 {
1301   TLValueRotation1->setText( QString("%1\xB0").arg( value ) );
1302   onValueChanged();
1303 }
1304
1305 /*!
1306   SLOT: Called when value of slider rotation2 change
1307 */
1308 void OCCViewer_ClippingDlg::SliderRotation2HasMoved( int value )
1309 {
1310   TLValueRotation2->setText( QString("%1\xB0").arg( value ) );
1311   onValueChanged();
1312 }
1313
1314 OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane (int theIndex) {
1315   return myLocalPlanes[theIndex];
1316 }
1317
1318 int OCCViewer_ClippingDlg::clipPlanesCount() {
1319   return myLocalPlanes.size();
1320 }