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