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