Salome HOME
0023450: Fields are not displayed in GEOM
[modules/gui.git] / src / OCCViewer / OCCViewer_ClippingDlg.cxx
1 // Copyright (C) 2007-2016  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)& ) ), SLOT( onPlaneClicked( const Handle(AIS_Plane)& ) ) );
640   connect( myInteractor, SIGNAL( planeDragged( const Handle(AIS_Plane)& ) ), SLOT( onPlaneDragged( const Handle(AIS_Plane)& ) ) );
641
642   myLocalPlanes = myModel->getClipPlanes();
643   synchronize();
644 }
645
646 /*!
647   Destructor
648   Destroys the object and frees any allocated resources
649 */
650 OCCViewer_ClippingDlg::~OCCViewer_ClippingDlg()
651 {
652   myLocalPlanes.clear();
653 }
654
655 /*!
656   Custom handling of close event: erases preview
657 */
658 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
659 {
660   erasePreview();
661   QDialog::closeEvent( e );
662   OCCViewer_ViewWindow* v = qobject_cast<OCCViewer_ViewWindow*>(parent());
663   if(v)
664     v->onClipping(false);
665 }
666
667 /*!
668   Custom handling of show event: displays preview
669 */
670 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
671 {
672   QDialog::showEvent( e );
673   onPreview( PreviewCheckBox->isChecked() );
674 }
675
676 /*!
677   Custom handling of hide event: erases preview
678 */
679 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
680 {
681   erasePreview();
682   QDialog::hideEvent( e );
683   OCCViewer_ViewWindow* v = qobject_cast<OCCViewer_ViewWindow*>(parent());
684   if(v)
685     v->onClipping(false);
686
687 }
688
689 /*!
690   Initialization of initial values of widgets
691 */
692 void OCCViewer_ClippingDlg::initParam()
693 {
694   SpinBox_X->setValue( 0.0 );
695   SpinBox_Y->setValue( 0.0 );
696   SpinBox_Z->setValue( 0.0 );
697
698   SpinBox_Dx->setValue( 1.0 );
699   SpinBox_Dy->setValue( 1.0 );
700   SpinBox_Dz->setValue( 1.0 );
701
702   CBAbsoluteOrientation->setCurrentIndex(0);
703
704   SpinSliderDistance->setValue( 0.5 );
705   SpinSliderRotation1->setValue( 0 );
706   SpinSliderRotation2->setValue( 0 );
707   CBRelativeOrientation->setCurrentIndex( 0 );
708
709   isActivePlane->setChecked( true );
710 }
711
712 /*!
713   Set plane parameters from widgets.
714 */
715 void OCCViewer_ClippingDlg::setPlaneParam( OCCViewer_ClipPlane& thePlane )
716 {
717   OCCViewer_ClipPlane::PlaneMode aMode = currentPlaneMode();
718
719   thePlane.Mode = aMode;
720
721   if ( aMode == OCCViewer_ClipPlane::Absolute )
722   {
723     if( qFuzzyIsNull( SpinBox_Dx->value() ) && 
724         qFuzzyIsNull( SpinBox_Dy->value() ) && 
725         qFuzzyIsNull( SpinBox_Dz->value() ) ) {
726       return;
727     }
728   }
729
730   thePlane.OrientationType = (aMode == OCCViewer_ClipPlane::Absolute)
731     ? CBAbsoluteOrientation->currentIndex()
732     : CBRelativeOrientation->currentIndex();
733
734   // Get XYZ, DXYZ
735   if ( aMode == OCCViewer_ClipPlane::Absolute )
736   {
737     if ( thePlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom )
738     {
739       thePlane.AbsoluteOrientation.Dx = SpinBox_Dx->value();
740       thePlane.AbsoluteOrientation.Dy = SpinBox_Dy->value();
741       thePlane.AbsoluteOrientation.Dz = SpinBox_Dz->value();
742       thePlane.AbsoluteOrientation.IsInvert = false;
743     }
744     else
745     {
746       thePlane.AbsoluteOrientation.IsInvert = SpinBox_Dx->value() < 0.0
747                                            || SpinBox_Dy->value() < 0.0
748                                            || SpinBox_Dz->value() < 0.0;
749     }
750
751     thePlane.X = SpinBox_X->value();
752     thePlane.Y = SpinBox_Y->value();
753     thePlane.Z = SpinBox_Z->value();
754   }
755   else
756   {
757     thePlane.RelativeOrientation.Rotation1 = SpinSliderRotation1->value();
758     thePlane.RelativeOrientation.Rotation2 = SpinSliderRotation2->value();
759
760     double aPlaneDx = 0.0;
761     double aPlaneDy = 0.0;
762     double aPlaneDz = 0.0;
763     double aX = 0.0;
764     double aY = 0.0;
765     double aZ = 0.0;
766
767     OCCViewer_ClipPlane::RelativeToDXYZ( thePlane.OrientationType,
768                                          thePlane.RelativeOrientation.Rotation1,
769                                          thePlane.RelativeOrientation.Rotation2,
770                                          aPlaneDx, aPlaneDy, aPlaneDz );
771
772     DistanceToXYZ( myModel->getAISContext(),
773                    myModel->trihedronSize(),
774                    SpinSliderDistance->value(),
775                    aPlaneDx, aPlaneDy, aPlaneDz,
776                    aX, aY, aZ );
777
778     thePlane.X = aX;
779     thePlane.Y = aY;
780     thePlane.Z = aZ;
781   }
782
783   thePlane.IsOn = isActivePlane->isChecked();
784 }
785
786 /*!
787   Synchronize dialog's widgets with data
788 */
789 void OCCViewer_ClippingDlg::synchronize()
790 {
791   ComboBoxPlanes->clear();
792   int aNbPlanesAbsolute = myLocalPlanes.size();
793
794   QString aName;
795   for(int i = 1; i<=aNbPlanesAbsolute; i++ ) {
796     aName = QString("Plane %1").arg(i);
797     ComboBoxPlanes->addItem( aName );
798   }
799
800   int aPos = ComboBoxPlanes->count() - 1;
801   ComboBoxPlanes->setCurrentIndex( aPos );
802
803   bool anIsControlsEnable = ( aPos >= 0 );
804   if ( anIsControlsEnable ) {
805     onSelectPlane( aPos );
806   }
807   else {
808     ComboBoxPlanes->addItem( tr( "NO_PLANES" ) );
809     initParam();
810   }
811   if ( currentPlaneMode() == OCCViewer_ClipPlane::Absolute )
812   {
813     SpinBox_X->setEnabled( anIsControlsEnable );
814     SpinBox_Y->setEnabled( anIsControlsEnable );
815     SpinBox_Z->setEnabled( anIsControlsEnable );
816     SpinBox_Dx->setEnabled( anIsControlsEnable );
817     SpinBox_Dy->setEnabled( anIsControlsEnable );
818     SpinBox_Dz->setEnabled( anIsControlsEnable );
819     CBAbsoluteOrientation->setEnabled( anIsControlsEnable );
820     invertButton->setEnabled( anIsControlsEnable );
821     resetButton->setEnabled( anIsControlsEnable );
822   }
823   else if ( currentPlaneMode() == OCCViewer_ClipPlane::Relative )
824   {
825     CBRelativeOrientation->setEnabled( anIsControlsEnable );
826     SpinSliderDistance->setEnabled( anIsControlsEnable );
827     SpinSliderRotation1->setEnabled( anIsControlsEnable );
828     SpinSliderRotation2->setEnabled( anIsControlsEnable );
829     isActivePlane->setEnabled( anIsControlsEnable );
830   }
831   isActivePlane->setEnabled( anIsControlsEnable );
832 }
833
834 /*!
835   Displays preview of clipping plane
836 */
837 void OCCViewer_ClippingDlg::displayPreview()
838 {
839   if ( myBusy || !isValid() || !myModel)
840     return;
841
842   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
843   
844   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
845
846   for ( int i=0; i < clipPlanesCount(); i++ ) {
847     OCCViewer_ClipPlane& aClipPlane = getClipPlane(i);
848     if ( aClipPlane.IsOn ) {
849       Handle(AIS_Plane) myPreviewPlane;
850       double aSize;
851       gp_Pnt aBasePnt;
852       gp_Dir aNormal;
853       clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
854       myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
855       myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
856       Handle(Prs3d_PlaneAspect) aPlaneAspect = new Prs3d_PlaneAspect();
857       aPlaneAspect->SetPlaneLength( aSize, aSize );
858       myPreviewPlane->Attributes()->SetPlaneAspect( aPlaneAspect );
859       ic->SetWidth( myPreviewPlane, 10, false );
860       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
861       ic->SetTransparency( myPreviewPlane, 0.5, false );
862       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 );
863       ic->SetColor( myPreviewPlane, c , false );
864       ic->Display( myPreviewPlane, 1, 0, false );
865       myPreviewPlaneVector.push_back( myPreviewPlane );
866     }
867   }
868   myModel->update();
869
870   double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
871   getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
872   gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5,
873                           (aYmax + aYmin) * 0.5,
874                           (aZmax + aZmin) * 0.5 );
875   Bnd_Box aMinMax;
876   aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
877
878   myInteractor->setPlanes( myPreviewPlaneVector );
879   myInteractor->setRotationCenter( aRotationCenter );
880   myInteractor->setMinMax( aMinMax );
881   myInteractor->setEnabled( true );
882 }
883
884 void OCCViewer_ClippingDlg::updatePreview() {
885   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
886   int count = clipPlanesCount();
887   if ( myBusy || 
888        !isValid() || 
889        myIsPlaneCreation ||
890        !myModel || 
891        count == 0 || 
892        (aCurPlaneIndex +1 > count) ||
893        !PreviewCheckBox->isChecked())
894     return;
895   
896   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
897   
898   OCCViewer_ClipPlane& aClipPlane = getClipPlane(aCurPlaneIndex);
899   Handle(AIS_Plane) myPreviewPlane;
900
901   if (aClipPlane.IsOn) {
902     double aSize;
903     gp_Pnt aBasePnt;
904     gp_Dir aNormal;
905     clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
906     if(myPreviewPlaneVector.size() < clipPlanesCount()) {
907       myPreviewPlaneVector.resize(clipPlanesCount());
908     }
909     myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
910     if(myPreviewPlane.IsNull()) {
911       //Plane was not created
912       myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
913       myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
914       Handle(Prs3d_PlaneAspect) aPlaneAspect = new Prs3d_PlaneAspect();
915       aPlaneAspect->SetPlaneLength( aSize, aSize );
916       myPreviewPlane->Attributes()->SetPlaneAspect( aPlaneAspect );
917       ic->Display( myPreviewPlane, 1, 0, false );
918       ic->SetWidth( myPreviewPlane, 10, false );
919       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
920       ic->SetTransparency( myPreviewPlane, 0.5, false );
921       myPreviewPlaneVector[aCurPlaneIndex] = myPreviewPlane;
922     } else {      
923       myPreviewPlane->SetComponent( new Geom_Plane( aBasePnt, aNormal ) );
924       myPreviewPlane->SetCenter( aBasePnt );
925       myPreviewPlane->SetSize( aSize, aSize );  
926     }
927
928     ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false );
929     ic->Update( myPreviewPlane, Standard_False );
930   } else {
931     if(myPreviewPlaneVector.size() > aCurPlaneIndex ) {
932       myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
933       if(ic->IsDisplayed(myPreviewPlane)) {
934         ic->Erase( myPreviewPlane, false );
935         ic->Remove( myPreviewPlane, false );
936       }
937       myPreviewPlaneVector[aCurPlaneIndex].Nullify();
938     }
939   }
940   for(int i = 0; i < myPreviewPlaneVector.size(); i++) {
941     if( i == aCurPlaneIndex ) continue;
942     if(!myPreviewPlaneVector[i].IsNull())
943       ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
944   }
945   myModel->update();
946
947   double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
948   getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
949   gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5,
950                           (aYmax + aYmin) * 0.5,
951                           (aZmax + aZmin) * 0.5 );
952   Bnd_Box aMinMax;
953   aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
954
955   myInteractor->setPlanes( myPreviewPlaneVector );
956   myInteractor->setRotationCenter( aRotationCenter );
957   myInteractor->setMinMax( aMinMax );
958 }
959
960 /*!
961   Erases preview of clipping plane
962 */
963 void OCCViewer_ClippingDlg::erasePreview()
964 {
965   if ( !myModel )
966     return;
967
968   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
969
970   for ( int i=0; i < myPreviewPlaneVector.size(); i++ ) {
971   Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[i];
972     if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
973       ic->Erase( myPreviewPlane, false );
974       ic->Remove( myPreviewPlane, false );
975       myPreviewPlane.Nullify();
976     }
977   }
978   myPreviewPlaneVector.clear();
979   myModel->update();
980   myInteractor->setEnabled( false );
981 }
982
983 /*!
984   Return true if plane parameters are valid
985 */
986 bool OCCViewer_ClippingDlg::isValid()
987 {
988   return ( SpinBox_Dx->value() !=0 || SpinBox_Dy->value() !=0 || SpinBox_Dz->value() !=0 );
989 }
990
991 /*!
992   Update view after changes
993 */
994 void OCCViewer_ClippingDlg::updateClipping()
995 {
996   if (PreviewCheckBox->isChecked() || AutoApplyCheckBox->isChecked())
997   {
998     if (AutoApplyCheckBox->isChecked()) {
999       onApply();
1000     }
1001     
1002     if (!PreviewCheckBox->isChecked())
1003       myModel->update();
1004     else 
1005       updatePreview();
1006   }
1007 }
1008
1009 /*!
1010   Updates state of user controls.
1011 */
1012 void OCCViewer_ClippingDlg::updateControls()
1013 {
1014   if ( clipPlanesCount() == 0 )
1015   {
1016     initParam();
1017     return;
1018   }
1019
1020   int aPlaneIdx = ComboBoxPlanes->currentIndex();
1021
1022   OCCViewer_ClipPlane& aPlane = getClipPlane( aPlaneIdx );
1023
1024   double aPlaneDx  = 0.0;
1025   double aPlaneDy  = 0.0;
1026   double aPlaneDz  = 0.0;
1027   double aDistance = 0.0;
1028   aPlane.OrientationToXYZ( aPlaneDx, aPlaneDy, aPlaneDz );
1029
1030   if ( aPlane.Mode == OCCViewer_ClipPlane::Absolute )
1031   {
1032     ModeStackedLayout->setCurrentIndex( 0 );
1033
1034     // Set plane parameters in the dialog
1035     SpinBox_X->setValue( aPlane.X );
1036     SpinBox_Y->setValue( aPlane.Y );
1037     SpinBox_Z->setValue( aPlane.Z );
1038     SpinBox_Dx->setValue( aPlaneDx );
1039     SpinBox_Dy->setValue( aPlaneDy );
1040     SpinBox_Dz->setValue( aPlaneDz );
1041     CBAbsoluteOrientation->setCurrentIndex( aPlane.OrientationType );
1042     onOrientationAbsoluteChanged( aPlane.OrientationType );
1043   }
1044   else if( aPlane.Mode == OCCViewer_ClipPlane::Relative )
1045   {
1046     ModeStackedLayout->setCurrentIndex( 1 );
1047
1048     // Set plane parameters in the dialog
1049     SpinSliderRotation1->setValue( int( aPlane.RelativeOrientation.Rotation1 ) );
1050     SpinSliderRotation2->setValue( int( aPlane.RelativeOrientation.Rotation2 ) );
1051
1052     XYZToDistance( myModel->getAISContext(),
1053                    myModel->trihedronSize(),
1054                    aPlane.X, aPlane.Y, aPlane.Z,
1055                    aPlaneDx, aPlaneDy, aPlaneDz,
1056                    aDistance );
1057
1058     SpinSliderDistance->setValue( aDistance );
1059
1060     CBRelativeOrientation->setCurrentIndex( aPlane.OrientationType );
1061     onOrientationRelativeChanged( aPlane.OrientationType );
1062   }
1063
1064   isActivePlane->setChecked( aPlane.IsOn );
1065 }
1066
1067 /*!
1068   SLOT on new button click: create a new clipping plane
1069 */
1070 void OCCViewer_ClippingDlg::ClickOnNew()
1071 {
1072   OCCViewer_ClipPlane aClipPlane;
1073
1074   // init controls state
1075   myIsUpdatingControls = true;
1076   initParam();
1077   myIsUpdatingControls = false;
1078
1079   // init plane according to the state of controls
1080   setPlaneParam( aClipPlane );
1081
1082   // add plane
1083   myLocalPlanes.push_back( aClipPlane );
1084   synchronize();
1085 }
1086
1087 /*!
1088   SLOT on delete button click: Delete selected clipping plane
1089 */
1090 void OCCViewer_ClippingDlg::ClickOnDelete()
1091 {
1092   int aPlaneIndex = ComboBoxPlanes->currentIndex();
1093   if ( (clipPlanesCount() == 0) || (aPlaneIndex+1 > clipPlanesCount()))
1094     return;
1095
1096   myLocalPlanes.erase(myLocalPlanes.begin() + aPlaneIndex);
1097
1098   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
1099
1100   if(aPlaneIndex+1 <= myPreviewPlaneVector.size()) {
1101     Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[aPlaneIndex];
1102     if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
1103       ic->Erase( myPreviewPlane, false );
1104       ic->Remove( myPreviewPlane, false );
1105     }
1106     myPreviewPlaneVector.erase(myPreviewPlaneVector.begin() + aPlaneIndex);
1107   }
1108   synchronize();
1109   if (AutoApplyCheckBox->isChecked()) {
1110     onApply();
1111   }
1112   myModel->update();
1113 }
1114
1115 /*!
1116   SLOT on disable all button click: Restore initial state of viewer,
1117   erase all clipping planes
1118 */
1119 void OCCViewer_ClippingDlg::ClickOnDisableAll()
1120 {
1121   AutoApplyCheckBox->setChecked (false);
1122   int aClipPlanesCount = clipPlanesCount();
1123   for ( int anIndex = 0; anIndex < aClipPlanesCount; anIndex++)
1124   {
1125     OCCViewer_ClipPlane& aPlane = getClipPlane(anIndex);
1126     aPlane.IsOn = false;
1127   }
1128   erasePreview();
1129   isActivePlane->setChecked(false);
1130   myModel->setClipPlanes(myLocalPlanes);
1131   myModel->update();
1132 }
1133
1134 /*!
1135   SLOT on ok button click: sets cutting plane and closes dialog
1136 */
1137 void OCCViewer_ClippingDlg::ClickOnOk()
1138 {
1139   onApply();
1140   ClickOnClose();
1141 }
1142
1143 /*!
1144   SLOT on Apply button click: sets cutting plane and update viewer
1145 */
1146 void OCCViewer_ClippingDlg::ClickOnApply()
1147 {
1148   onApply();
1149   myModel->update();
1150 }
1151
1152 /*!
1153   SLOT on close button click: erases preview and rejects dialog
1154 */
1155 void OCCViewer_ClippingDlg::ClickOnClose()
1156 {
1157   erasePreview();
1158   OCCViewer_ViewWindow* v = qobject_cast<OCCViewer_ViewWindow*>(parent());
1159   if(v)
1160     v->onClipping(false);
1161 }
1162
1163 /*!
1164   SLOT on help button click: opens a help page
1165 */
1166 void OCCViewer_ClippingDlg::ClickOnHelp()
1167 {
1168   SUIT_Application* app = SUIT_Session::session()->activeApplication();
1169   if ( app )
1170     app->onHelpContextModule( "GUI", "occ_3d_viewer_page.html", "clipping_planes" );
1171 }
1172
1173 /*!
1174   Set absolute mode of clipping plane
1175 */
1176 void OCCViewer_ClippingDlg::onModeAbsolute()
1177 {
1178   myIsPlaneCreation = true;
1179   ModeStackedLayout->setCurrentIndex(0);
1180   ClickOnNew();
1181   myIsPlaneCreation = false;
1182   updateClipping();
1183 }
1184
1185 /*!
1186   Set relative mode of clipping plane
1187 */
1188 void OCCViewer_ClippingDlg::onModeRelative()
1189 {
1190   myIsPlaneCreation = true;
1191   ModeStackedLayout->setCurrentIndex(1);
1192   ClickOnNew();
1193   myIsPlaneCreation = false;
1194   SetCurrentPlaneParam();
1195   updateClipping();
1196 }
1197
1198 /*!
1199   SLOT: called on value of clipping plane changed
1200 */
1201 void OCCViewer_ClippingDlg::onValueChanged()
1202 {
1203   if ( myIsUpdatingControls )
1204   {
1205     return;
1206   }
1207
1208   SetCurrentPlaneParam();
1209
1210   if ( myIsSelectPlane )
1211   {
1212     return;
1213   }
1214
1215   updateClipping();
1216 }
1217
1218 /*!
1219   Set current parameters of selected plane
1220 */
1221 void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
1222 {
1223   if ( clipPlanesCount() == 0 )
1224   {
1225     return;
1226   }
1227
1228   OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex );
1229
1230   myIsSelectPlane = true;
1231   updateControls();
1232   ComboBoxPlanes->setCurrentIndex( theIndex );
1233   myIsSelectPlane = false;
1234 }
1235
1236 /*!
1237   Restore parameters of selected plane
1238 */
1239 void OCCViewer_ClippingDlg::SetCurrentPlaneParam()
1240 {
1241   if ( clipPlanesCount() == 0 || myIsSelectPlane || myBusy )
1242   {
1243     return;
1244   }
1245
1246   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1247
1248   OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
1249
1250   setPlaneParam( aPlane );
1251 }
1252
1253 /*!
1254   SLOT on reset button click: sets default values
1255 */
1256 void OCCViewer_ClippingDlg::onReset()
1257 {
1258   myBusy = true;
1259   SpinBox_X->setValue(0);
1260   SpinBox_Y->setValue(0);
1261   SpinBox_Z->setValue(0);
1262   myBusy = false;
1263
1264   SetCurrentPlaneParam();
1265   updateClipping();
1266 }
1267
1268 /*!
1269   SLOT on invert button click: inverts normal of cutting plane
1270 */
1271 void OCCViewer_ClippingDlg::onInvert()
1272 {
1273   double Dx = SpinBox_Dx->value();
1274   double Dy = SpinBox_Dy->value();
1275   double Dz = SpinBox_Dz->value();
1276
1277   myBusy = true;
1278   SpinBox_Dx->setValue( -Dx );
1279   SpinBox_Dy->setValue( -Dy );
1280   SpinBox_Dz->setValue( -Dz );
1281   myBusy = false;
1282
1283   if ( clipPlanesCount() != 0 )
1284   {
1285     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1286     OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
1287     aPlane.AbsoluteOrientation.IsInvert = !aPlane.AbsoluteOrientation.IsInvert;
1288   }
1289   updateClipping();
1290 }
1291
1292 /*!
1293   SLOT: called on orientation of clipping plane in absolute mode changed
1294 */
1295 void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode )
1296 {
1297   bool isUserMode = (mode==0);
1298
1299   TextLabelX->setEnabled( isUserMode );
1300   TextLabelY->setEnabled( isUserMode );
1301   TextLabelZ->setEnabled( isUserMode );
1302
1303   SpinBox_X->setEnabled( isUserMode );
1304   SpinBox_Y->setEnabled( isUserMode );
1305   SpinBox_Z->setEnabled( isUserMode );
1306
1307   TextLabelDx->setEnabled( isUserMode );
1308   TextLabelDy->setEnabled( isUserMode );
1309   TextLabelDz->setEnabled( isUserMode );
1310
1311   SpinBox_Dx->setEnabled( isUserMode );
1312   SpinBox_Dy->setEnabled( isUserMode );
1313   SpinBox_Dz->setEnabled( isUserMode );
1314
1315   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
1316   OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
1317   double aDx = 0, aDy = 0, aDz = 0;
1318
1319   if ( mode == 0 )
1320   {
1321     aDx = aPlane.AbsoluteOrientation.Dx;
1322     aDy = aPlane.AbsoluteOrientation.Dy;
1323     aDz = aPlane.AbsoluteOrientation.Dz;
1324   }
1325   else if ( mode == 1 )
1326   {
1327     aDz = 1;
1328     TextLabelZ->setEnabled( true );
1329     SpinBox_Z->setEnabled( true );
1330     SpinBox_Z->setFocus();
1331   }
1332   else if ( mode == 2 )
1333   {
1334     aDx = 1;
1335     TextLabelX->setEnabled( true );
1336     SpinBox_X->setEnabled( true );
1337     SpinBox_X->setFocus();
1338   }
1339   else if ( mode == 3 )
1340   {
1341     aDy = 1;
1342     TextLabelY->setEnabled( true );
1343     SpinBox_Y->setEnabled( true );
1344     SpinBox_Y->setFocus();
1345   }
1346     
1347   if ( aPlane.AbsoluteOrientation.IsInvert == true )
1348   {
1349     aDx = -aDx;
1350     aDy = -aDy;
1351     aDz = -aDz;
1352   }
1353     
1354   myBusy = true;
1355   SpinBox_Dx->setValue( aDx );
1356   SpinBox_Dy->setValue( aDy );
1357   SpinBox_Dz->setValue( aDz );
1358   myBusy = false;
1359
1360   if ( !myIsUpdatingControls )
1361   {
1362     SetCurrentPlaneParam();
1363     updateClipping();
1364   }
1365 }
1366
1367 /*!
1368   SLOT: called on orientation of clipping plane in relative mode changed
1369 */
1370 void OCCViewer_ClippingDlg::onOrientationRelativeChanged (int theItem)
1371 {
1372   if ( clipPlanesCount() == 0 )
1373     return;
1374   
1375   if ( theItem == 0 ) {
1376     TextLabelRotation1->setText( tr( "ROTATION_AROUND_X_Y2Z" ) );
1377     TextLabelRotation2->setText( tr( "ROTATION_AROUND_Y_X2Z" ) );
1378   }
1379   else if ( theItem == 1 ) {
1380     TextLabelRotation1->setText( tr( "ROTATION_AROUND_Y_Z2X" ) );
1381     TextLabelRotation2->setText( tr( "ROTATION_AROUND_Z_Y2X" ) );
1382   }
1383   else if ( theItem == 2 ) {
1384     TextLabelRotation1->setText( tr( "ROTATION_AROUND_Z_X2Y" ) );
1385     TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) );
1386   }
1387
1388   if ( !myIsUpdatingControls )
1389   {
1390     if( (QComboBox*)sender() == CBRelativeOrientation )
1391     {
1392       SetCurrentPlaneParam();
1393     }
1394
1395     updateClipping();
1396   }
1397 }
1398
1399 /*!
1400   SLOT: called on preview check box toggled
1401 */
1402 void OCCViewer_ClippingDlg::onPreview( bool on )
1403 {
1404   erasePreview();
1405   if ( on ) 
1406     displayPreview();
1407 }
1408
1409 /*!
1410   SLOT: called on Auto Apply check box toggled
1411 */
1412 void OCCViewer_ClippingDlg::onAutoApply( bool toggled )
1413 {
1414   if ( toggled ) {
1415     onApply();
1416     myModel->update();
1417   }  
1418 }
1419
1420 /*!
1421   SLOT on Apply button click: sets cutting plane
1422 */
1423 void OCCViewer_ClippingDlg::onApply()
1424 {
1425   if ( myBusy )
1426     return;
1427   myIsSelectPlane = true;
1428
1429   qApp->processEvents();
1430   QApplication::setOverrideCursor( Qt::WaitCursor );
1431   qApp->processEvents();
1432
1433   myModel->setClipPlanes(myLocalPlanes);
1434
1435   QApplication::restoreOverrideCursor();
1436   myIsSelectPlane = false;
1437 }
1438
1439 /*!
1440   SLOT: Called when clip plane is clicked in viewer.
1441 */
1442 void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane )
1443 {
1444   for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
1445   {
1446     Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
1447     if ( aPlane != thePlane )
1448     {
1449       continue;
1450     }
1451
1452     ComboBoxPlanes->setCurrentIndex( aPlaneIt );
1453
1454     break;
1455   }
1456 }
1457
1458 /*!
1459   SLOT: Called when clip plane is changed by dragging in viewer.
1460 */
1461 void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane )
1462 {
1463   for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
1464   {
1465     Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
1466     if ( aPlane != thePlane )
1467     {
1468       continue;
1469     }
1470
1471     OCCViewer_ClipPlane& aClipPlane = getClipPlane( aPlaneIt );
1472
1473     gp_Pln aPln = thePlane->Component()->Pln();
1474     const gp_Pnt& aPlaneP = aPln.Location();
1475     const gp_Dir& aPlaneN = aPln.Axis().Direction();
1476
1477     aClipPlane.X  = aPlaneP.X();
1478     aClipPlane.Y  = aPlaneP.Y();
1479     aClipPlane.Z  = aPlaneP.Z();
1480
1481     if ( aClipPlane.Mode == OCCViewer_ClipPlane::Absolute )
1482     {
1483       if ( aClipPlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom )
1484       {
1485         int anInvertCoeff = aClipPlane.AbsoluteOrientation.IsInvert ? 1 : -1;
1486         aClipPlane.AbsoluteOrientation.Dx = anInvertCoeff * aPlaneN.X();
1487         aClipPlane.AbsoluteOrientation.Dy = anInvertCoeff * aPlaneN.Y();
1488         aClipPlane.AbsoluteOrientation.Dz = anInvertCoeff * aPlaneN.Z();
1489       }
1490     }
1491     else
1492     {
1493       OCCViewer_ClipPlane::DXYZToRelative( aPlaneN.X(), aPlaneN.Y(), aPlaneN.Z(),
1494                                            aClipPlane.OrientationType,
1495                                            aClipPlane.RelativeOrientation.Rotation1,
1496                                            aClipPlane.RelativeOrientation.Rotation2 );
1497     }
1498
1499     myIsUpdatingControls = true;
1500     updateControls();
1501     myIsUpdatingControls = false;
1502
1503     if ( AutoApplyCheckBox->isChecked() )
1504     {
1505       onApply();
1506     }
1507
1508     break;
1509   }
1510 }
1511
1512 OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane( int theIdx )
1513 {
1514   return myLocalPlanes[theIdx];
1515 }
1516
1517 int OCCViewer_ClippingDlg::clipPlanesCount()
1518 {
1519   return myLocalPlanes.size();
1520 }
1521
1522 OCCViewer_ClipPlane::PlaneMode OCCViewer_ClippingDlg::currentPlaneMode() const
1523 {
1524   return ModeStackedLayout->currentIndex() == 0
1525     ? OCCViewer_ClipPlane::Absolute 
1526     : OCCViewer_ClipPlane::Relative;
1527 }