]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
First stage of the "0021793: [CEA 625] Clipping : from coordinates or from bounding...
authorrnv <rnv@opencascade.com>
Wed, 16 Oct 2013 12:45:53 +0000 (12:45 +0000)
committerrnv <rnv@opencascade.com>
Wed, 16 Oct 2013 12:45:53 +0000 (12:45 +0000)
doc/salome/gui/images/Clipping_Absolute.png [new file with mode: 0644]
doc/salome/gui/images/Clipping_Relative.png [new file with mode: 0644]
doc/salome/gui/input/occ_3d_viewer.doc
src/OCCViewer/OCCViewer_ClippingDlg.cxx
src/OCCViewer/OCCViewer_ClippingDlg.h
src/OCCViewer/OCCViewer_ViewWindow.cxx
src/OCCViewer/resources/OCCViewer_msg_en.ts
src/OCCViewer/resources/OCCViewer_msg_fr.ts
src/STD/resources/STD_msg_en.ts
src/STD/resources/STD_msg_fr.ts
src/SVTK/SVTK_RenderWindowInteractor.cxx

diff --git a/doc/salome/gui/images/Clipping_Absolute.png b/doc/salome/gui/images/Clipping_Absolute.png
new file mode 100644 (file)
index 0000000..943fe56
Binary files /dev/null and b/doc/salome/gui/images/Clipping_Absolute.png differ
diff --git a/doc/salome/gui/images/Clipping_Relative.png b/doc/salome/gui/images/Clipping_Relative.png
new file mode 100644 (file)
index 0000000..82fc137
Binary files /dev/null and b/doc/salome/gui/images/Clipping_Relative.png differ
index 783adee96bcb340f6c88cd82b3255f01eb6f8f35..6473189928e65abff99902b5d80da7e4b758b9c6 100644 (file)
@@ -20,9 +20,13 @@ jpeg image format.
 
 \image html occ_view_style_switch.png
 
-<b>Interaction style switch</b> - allows to switch between "Salome 
-standard controls" and "Keyboard free" \ref viewer_navigation_modes "interaction styles". 
-
+<b>Interaction style switch</b> - allows to switch between standard
+and "keyboard free" interaction styles. "Keyboard free" style allows
+to process all view transformations without using keyboard (only by
+mouse) and perform selection in view by pressing "S" key. By default,
+rotation in this mode is performed by left mouse button, panning - by
+middle mouse button, zooming - by left and middle mouse buttons
+pressed simultaneously.
 <hr>
 
 \image html occ_view_zooming_style_switch.png
@@ -151,12 +155,20 @@ scene.
 <b>Clone view</b> - opens a new duplicate scene.
 <hr>
 
+\anchor clipping_planes
 \image html occ_view_clipping.png
 
 <b>Clipping</b> - allows to create cross-section views (clipping
 planes) of geometrical objects.
 
-\image html clipping.png
+To start, click on the \em New button.
+
+Now you must specify what mode of creating plane you want to choose: 
+absolute or relative.
+
+<b>Absolute mode</b>
+
+\image html Clipping_Absolute.png
 
 - <b>Base point</b> - allows to define the coordinates of the base
   point for the clipping plane.
@@ -168,9 +180,23 @@ planes) of geometrical objects.
 
   - <b>Invert</b> - allows to select which part of the object will be
     removed and which will remain after clipping.
+    
+<b>Relative mode</b>  
+
+\image html Clipping_Relative.png
 
-- <b>Preview</b> - allows to see the results of clipping in the
-  viewer.
+- \b Orientation ( ||X-Y, ||X-Z or ||Y-Z).
+- \b Distance between the opposite extremities of the boundary box of 
+selected objects, if it is set to 0.5 the boundary box is split in two halves.
+- \b Rotation (in angle degrees) <b>around X</b> (Y to Z) and <b>around 
+Y</b> (X to Z) (depending on the chosen Orientation)
+
+
+If the <b>Show preview</b> button is on, you can see the clipping plane
+in the viewer.
+
+If the <b>Auto Apply</b> button is on, you can preview the
+cross-section in the viewer.
 
 <hr>
 
@@ -218,28 +244,8 @@ on/off.
 \image html occ_view_minimized.png
 \image html occ_view_maximized.png
 
-<b>Create sub-views/Maximize</b> - these buttons allow switching the current
+<b>Minimize/Maximize</b> - these buttons allow switching the current
 view area to the minimized / maximized state.
-
-<b>Create sub-views</b> - user can select the layout and types of child sub-views:
-
-\image html create_sub-views_dlg.png
-
-- <b>Sub-views Layout</b>
-
-  - Three radio-buttons to specify numbers of the views to arrange (2, 3 or 4).
-  
-  - Buttons (depending on the chosen number of views) with images to specify 
-    view layout.
-    
-  - Buttons "Previous" and "Next" for possibility to change split schemas.
-
-- <b>Sub-views Properties</b>
-
-  - Type of each sub-view: XZ, YZ, XY or XYZ. 
-
-<b>Maximize</b> - the current view area will be converted to maximized state.
-
 <hr>
 
 \image html occ_view_sync.png
@@ -256,5 +262,68 @@ In addition, when this button is in the "checked" state, the dynamic
 synchronization of the views is performed, i.e. any zoom, pan, rotate
 or other view operation done in one view is automatically applied to
 the other view.
+<hr>
+
+\anchor occ_background
+<h2>Background</h2>
+
+OCC Viewer background can be customized using the "Change background"
+popup menu command that opens the following dialog box:
+
+\image html change_background_dlg.png
+
+The following types of the background are supported:
+
+- Single color: the background is colored with the solid color
+  specified by the user in the dialog box.
+
+- Gradient background: the background is gradiently colored according
+  to two colors and the gradient type specified in the dialog box. The
+  following types of background are supported:
+
+  - Horizontal
+
+  - Vertical
+
+  - First diagonal
+
+  - Second diagonal
+
+  - First corner
+
+  - Second corner
+
+  - Third corner
+
+  - Fourth corner
+
+- Image: allows to set image as viewer background and define filling type:
+
+  - Center: the image is located at the center of the viewer backgound
+
+  - Tile: the image fills the entire viewer backgound one by one
+
+  - Stretch: the image is stretched to the entire viewer backgound.
+
+Default background for the viewer is specified via the
+\ref occ_preferences "application preferences".
+
+<h2>Polyline selection</h2>
+
+OCC Viewer features a special <b>Polyline Selection</b> mechanism,
+which allows selecting an arbitraty part of the graphic area using a
+polygon frame (rubber band), instead of the usual selection with a
+rectangular frame.
+
+To produce a Polyline Selection, lock the right mouse button and draw
+the first side of the polygon, then change the direction by clicking
+the left mouse button add draw another side, etc. The whole selection
+frame is drawn with the locked right mouse button.
+   
+\image html polyselection1.png
+
+As a result, only the nodes within the frame are selected.
+
+\image html polyselection2.png
 
 */
index f49c43c8eaa3f842060e1b164659d24582cb05dc..065ef91f2ff21b1b165ca059d9929fc37893079f 100644 (file)
@@ -33,6 +33,7 @@
 #include "OCCViewer_ViewModel.h"
 
 #include <V3d_View.hxx>
+#include <Visual3d_View.hxx>
 #include <Geom_Plane.hxx>
 #include <Prs3d_Presentation.hxx>
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
@@ -42,6 +43,7 @@
 #include <IntAna_IntConicQuad.hxx>
 #include <gp_Lin.hxx>
 #include <gp_Pln.hxx>
+#include <math.h>
 
 // QT Includes
 #include <QApplication>
 #include <QPushButton>
 #include <QComboBox>
 #include <QCheckBox>
+#include <QStackedLayout>
+#include <QSlider>
+#include <QMenu>
 
+/*!
+  Constructor of class ClipPlane
+ */
+ClipPlane::ClipPlane():
+  RelativeMode(),
+  X(0.0), Y(0.0), Z(0.0),
+  Dx(1.0), Dy(1.0), Dz(1.0),
+  Orientation(0),
+  IsActive( true ),
+  IsInvert( false ),
+  PlaneMode( Absolute )
+{
+}
+
+/*!
+  Constructor of class OrientedPlane
+ */
+OrientedPlane::OrientedPlane():
+  Orientation(0),
+  Distance(0.5),
+  Rotation1(0),
+  Rotation2(0)
+{
+}
+
+/**********************************************************************************
+ ************************        Internal functions        ************************
+ *********************************************************************************/
+
+/*!
+  Compute the point of bounding box and current clipping plane
+ */
+void ComputeBoundsParam( double theBounds[6],
+                         double theDirection[3],
+                         double theMinPnt[3],
+                         double& theMaxBoundPrj,
+                         double& theMinBoundPrj )
+{
+  //Enlarge bounds in order to avoid conflicts of precision
+  for(int i = 0; i < 6; i += 2) {
+    static double EPS = 1.0E-3;
+    double aDelta = (theBounds[i+1] - theBounds[i])*EPS;
+    theBounds[i] -= aDelta;
+    theBounds[i+1] += aDelta;
+  }
+
+  double aBoundPoints[8][3] = { { theBounds[0], theBounds[2], theBounds[4] },
+                                { theBounds[1], theBounds[2], theBounds[4] },
+                                { theBounds[0], theBounds[3], theBounds[4] },
+                                { theBounds[1], theBounds[3], theBounds[4] },
+                                { theBounds[0], theBounds[2], theBounds[5] },
+                                { theBounds[1], theBounds[2], theBounds[5] },
+                                { theBounds[0], theBounds[3], theBounds[5] },
+                                { theBounds[1], theBounds[3], theBounds[5] } };
+
+  int aMaxId = 0;
+  theMaxBoundPrj = theDirection[0] * aBoundPoints[aMaxId][0] + theDirection[1] * aBoundPoints[aMaxId][1]
+                   + theDirection[2] * aBoundPoints[aMaxId][2];
+  theMinBoundPrj = theMaxBoundPrj;
+  for(int i = 1; i < 8; i++) {
+    double aTmp = theDirection[0] * aBoundPoints[i][0] + theDirection[1] * aBoundPoints[i][1]
+                  + theDirection[2] * aBoundPoints[i][2];
+    if(theMaxBoundPrj < aTmp) {
+      theMaxBoundPrj = aTmp;
+      aMaxId = i;
+    }
+    if(theMinBoundPrj > aTmp) {
+      theMinBoundPrj = aTmp;
+    }
+  }
+  double *aMinPnt = aBoundPoints[aMaxId];
+  theMinPnt[0] = aMinPnt[0];
+  theMinPnt[1] = aMinPnt[1];
+  theMinPnt[2] = aMinPnt[2];
+}
+
+/*!
+  Compute the position of current plane by distance
+ */
+void DistanceToPosition( double theBounds[6],
+                         double theDirection[3],
+                         double theDist,
+                         double thePos[3] )
+{
+  double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
+  ComputeBoundsParam( theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj );
+  double aLength = (aMaxBoundPrj - aMinBoundPrj)*theDist;
+  thePos[0] = aMinPnt[0] - theDirection[0]*aLength;
+  thePos[1] = aMinPnt[1] - theDirection[1]*aLength;
+  thePos[2] = aMinPnt[2] - theDirection[2]*aLength;
+}
+
+/*!
+  Compute the parameters of clipping plane
+ */
+bool ComputeClippingPlaneParameters( double theNormal[3],
+                                     double theDist,
+                                     double theBounds[6],
+                                     double theOrigin[3],
+                                     Handle(V3d_View) theView3d )
+{
+  bool anIsOk = false;
+  theBounds[0] = theBounds[2] = theBounds[4] = 999.99;
+  theBounds[1] = theBounds[3] = theBounds[5] = -999.99;
+  double aBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+
+  theView3d->View()->MinMaxValues( aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5]);
+  if ( !theView3d->View()->ContainsFacet() ) {
+    aBounds[0] = aBounds[2] = aBounds[4] = 0.0;
+    aBounds[1] = aBounds[3] = aBounds[5] = 100.0;
+  }
+  anIsOk = true;
+
+  if( !anIsOk )
+    return false;
+
+  DistanceToPosition( aBounds, theNormal, theDist, theOrigin );
+  return true;
+}
+
+/*!
+  Cross product of two 3-vectors. Result vector in result[3].
+ */
+void Cross(const double first[3], const double second[3], double result[3])
+{
+  result[0] = first[1]*second[2] - first[2]*second[1];
+  result[1] = first[2]*second[0] - first[0]*second[2];
+  result[2] = first[0]*second[1] - first[1]*second[0];
+}
+
+/*!
+  Compute relative clipping plane in absolute coordinates
+ */
+void RelativePlaneToAbsolute ( ClipPlane* thePlane, Handle(V3d_View) theView3d )
+{
+  double aNormal[3];
+  double aDir[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };
+  {
+    static double aCoeff = M_PI/180.0;
+
+    double anU[2] = { cos( aCoeff * thePlane->RelativeMode.Rotation1 ), cos( aCoeff * thePlane->RelativeMode.Rotation2 ) };
+    double aV[2] = { sqrt( 1.0 - anU[0]*anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
+    aV[0] = thePlane->RelativeMode.Rotation1 > 0? aV[0]: -aV[0];
+    aV[1] = thePlane->RelativeMode.Rotation2 > 0? aV[1]: -aV[1];
+
+    switch ( thePlane->RelativeMode.Orientation ) {
+    case 0:
+      aDir[0][1] = anU[0];
+      aDir[0][2] = aV[0];
+      aDir[1][0] = anU[1];
+      aDir[1][2] = aV[1];
+      break;
+    case 1:
+      aDir[0][2] = anU[0];
+      aDir[0][0] = aV[0];
+      aDir[1][1] = anU[1];
+      aDir[1][0] = aV[1];
+      break;
+    case 2:
+      aDir[0][0] = anU[0];
+      aDir[0][1] = aV[0];
+      aDir[1][2] = anU[1];
+      aDir[1][1] = aV[1];
+      break;
+    }
+
+    Cross( aDir[1], aDir[0], aNormal );
+    // Normalize
+    double den;
+    den = sqrt( aNormal[0] * aNormal[0] + aNormal[1] * aNormal[1] + aNormal[2] * aNormal[2] );
+    if ( den != 0.0 ) {
+      for (int i=0; i < 3; i++) {
+        aNormal[i] /= den;
+      }
+    }
+    Cross( aNormal, aDir[1], aDir[0] );
+  }
+
+  double aBounds[6];
+  double anOrigin[3];
+
+  bool anIsOk = false;
+
+  anOrigin[0] = anOrigin[1] = anOrigin[2] = 0;
+  aBounds[0] = aBounds[2] = aBounds[4] = 0;
+  aBounds[1] = aBounds[3] = aBounds[5] = 0;
+  anIsOk = true;
+
+  anIsOk = ComputeClippingPlaneParameters( aNormal,
+                                           thePlane->RelativeMode.Distance,
+                                           aBounds,
+                                           anOrigin,
+                                           theView3d );
+  if( !anIsOk )
+         return;
+
+  thePlane->Dx = aNormal[0];
+  thePlane->Dy = aNormal[1];
+  thePlane->Dz = aNormal[2];
+  thePlane->X = anOrigin[0];
+  thePlane->Y = anOrigin[1];
+  thePlane->Z = anOrigin[2];
+}
+
+/*********************************************************************************
+ *********************      class OCCViewer_ClippingDlg      *********************
+ *********************************************************************************/
 /*!
   Constructor
   \param view - view window
@@ -73,130 +285,266 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, const
   
   QVBoxLayout* topLayout = new QVBoxLayout( this );
   topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
-  
+
   /***************************************************************/
-  GroupPoint = new QGroupBox( this );
-  GroupPoint->setObjectName( "GroupPoint" );
-  GroupPoint->setTitle( tr("Base point") );
-  QGridLayout* GroupPointLayout = new QGridLayout( GroupPoint );
-  GroupPointLayout->setAlignment( Qt::AlignTop );
-  GroupPointLayout->setSpacing( 6 );
-  GroupPointLayout->setMargin( 11 );
-  
-  // Controls
+  // Controls for selecting, creating, deleting planes
+  QGroupBox* GroupPlanes = new QGroupBox( tr("CLIPPING_PLANES"), this );
+  QHBoxLayout* GroupPlanesLayout = new QHBoxLayout( GroupPlanes );
+  ComboBoxPlanes = new QComboBox( GroupPlanes );
+  isActivePlane = new QCheckBox( tr("IS_ACTIVE_PLANE"), this );
+  buttonNew = new QPushButton( tr("BTN_NEW"), GroupPlanes );
+  buttonDelete = new QPushButton( tr("BTN_DELETE"), GroupPlanes );
+  buttonDisableAll = new QPushButton( tr("BTN_DISABLE_ALL"), GroupPlanes );
+  MenuMode = new QMenu( "MenuMode", buttonNew );
+  MenuMode->addAction( tr( "ABSOLUTE" ), this, SLOT( onModeAbsolute() ) );
+  MenuMode->addAction( tr( "RELATIVE" ), this, SLOT( onModeRelative() ) );
+  buttonNew->setMenu( MenuMode );
+  CurrentMode = Absolute;
+
+  GroupPlanesLayout->addWidget( ComboBoxPlanes );
+  GroupPlanesLayout->addWidget( isActivePlane );
+  GroupPlanesLayout->addWidget( buttonNew );
+  GroupPlanesLayout->addWidget( buttonDelete );
+  GroupPlanesLayout->addWidget( buttonDisableAll );
+
+  ModeStackedLayout = new QStackedLayout();
+
+  /**********************   Mode Absolute   **********************/
+  /* Controls for absolute mode of clipping plane:
+     X, Y, Z - coordinates of the intersection of cutting plane and the three axes
+     Dx, Dy, Dz - components of normal to the cutting plane
+     Orientation - direction of cutting plane
+   */
   const double min = -1e+7;
   const double max =  1e+7;
   const double step = 5;
   const int precision = -7;
 
-  TextLabelX = new QLabel( GroupPoint );
+  // Croup Point
+  QGroupBox* GroupAbsolutePoint = new QGroupBox( this );
+  GroupAbsolutePoint->setObjectName( "GroupPoint" );
+  GroupAbsolutePoint->setTitle( tr("BASE_POINT") );
+  QGridLayout* GroupPointLayout = new QGridLayout( GroupAbsolutePoint );
+  GroupPointLayout->setAlignment( Qt::AlignTop );
+  GroupPointLayout->setSpacing( 6 ); GroupPointLayout->setMargin( 11 );
+
+  TextLabelX = new QLabel( GroupAbsolutePoint );
   TextLabelX->setObjectName( "TextLabelX" );
   TextLabelX->setText( tr("X:") );
   GroupPointLayout->addWidget( TextLabelX, 0, 0 );
   
-  SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupPoint );
+  SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
   SpinBox_X->setObjectName("SpinBox_X" );
   SpinBox_X->setPrecision( precision );
   GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
 
-  TextLabelY = new QLabel( GroupPoint );
+  TextLabelY = new QLabel( GroupAbsolutePoint );
   TextLabelY->setObjectName( "TextLabelY" );
   TextLabelY->setText( tr("Y:") );
   GroupPointLayout->addWidget( TextLabelY, 0, 2 );
 
-  SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupPoint );
+  SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
   SpinBox_Y->setObjectName("SpinBox_Y" );
   SpinBox_Y->setPrecision( precision );
   GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
 
-  TextLabelZ = new QLabel( GroupPoint );
+  TextLabelZ = new QLabel( GroupAbsolutePoint );
   TextLabelZ->setObjectName( "TextLabelZ" );
   TextLabelZ->setText( tr("Z:") );
   GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
 
-  SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupPoint );
+  SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupAbsolutePoint );
   SpinBox_Z->setObjectName("SpinBox_Z" );
   SpinBox_Z->setPrecision( precision );
   GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
 
-  resetButton  = new QPushButton( GroupPoint );
+  resetButton  = new QPushButton( GroupAbsolutePoint );
   resetButton->setObjectName( "resetButton" );
-  resetButton->setText( tr( "Reset"  ) );
+  resetButton->setText( tr( "RESET"  ) );
   GroupPointLayout->addWidget( resetButton, 0, 6 );
 
-  /***************************************************************/
-  GroupDirection = new QGroupBox( this );
-  GroupDirection->setObjectName( "GroupDirection" );
-  GroupDirection->setTitle( tr("Direction") );
-  QGridLayout* GroupDirectionLayout = new QGridLayout( GroupDirection );
+  // Group Direction
+  GroupAbsoluteDirection = new QGroupBox( this );
+  GroupAbsoluteDirection->setObjectName( "GroupDirection" );
+  GroupAbsoluteDirection->setTitle( tr("DIRECTION") );
+  QGridLayout* GroupDirectionLayout = new QGridLayout( GroupAbsoluteDirection );
   GroupDirectionLayout->setAlignment( Qt::AlignTop );
   GroupDirectionLayout->setSpacing( 6 );
   GroupDirectionLayout->setMargin( 11 );
   
-  // Controls
-  TextLabelDx = new QLabel( GroupDirection );
+  TextLabelDx = new QLabel( GroupAbsoluteDirection );
   TextLabelDx->setObjectName( "TextLabelDx" );
   TextLabelDx->setText( tr("Dx:") );
   GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
   
-  SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupDirection );
+  SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
   SpinBox_Dx->setObjectName("SpinBox_Dx" );
   SpinBox_Dx->setPrecision( precision );
   GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
 
-  TextLabelDy = new QLabel( GroupDirection );
+  TextLabelDy = new QLabel( GroupAbsoluteDirection );
   TextLabelDy->setObjectName( "TextLabelDy" );
   TextLabelDy->setText( tr("Dy:") );
   GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
   
-  SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupDirection );
+  SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
   SpinBox_Dy->setObjectName("SpinBox_Dy" );
   SpinBox_Dy->setPrecision( precision );
   GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
 
-  TextLabelDz = new QLabel( GroupDirection );
+  TextLabelDz = new QLabel( GroupAbsoluteDirection );
   TextLabelDz->setObjectName( "TextLabelDz" );
   TextLabelDz->setText( tr("Dz:") );
   GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
   
-  SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupDirection );
+  SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupAbsoluteDirection );
   SpinBox_Dz->setObjectName("SpinBox_Dz" );
   SpinBox_Dz->setPrecision( precision );
   GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
 
-  invertButton  = new QPushButton( GroupDirection );
+  invertButton  = new QPushButton( GroupAbsoluteDirection );
   invertButton->setObjectName( "invertButton" );
-  invertButton->setText( tr( "Invert"  ) );
+  invertButton->setText( tr( "INVERT"  ) );
   GroupDirectionLayout->addWidget( invertButton, 0, 6 );
  
-  DirectionCB = new QComboBox( GroupDirection );
-  DirectionCB->setObjectName( "DirectionCB" );
-  DirectionCB->insertItem(DirectionCB->count(),tr("CUSTOM"));
-  DirectionCB->insertItem(DirectionCB->count(),tr("||X-Y"));
-  DirectionCB->insertItem(DirectionCB->count(),tr("||Y-Z"));
-  DirectionCB->insertItem(DirectionCB->count(),tr("||Z-X"));
-  GroupDirectionLayout->addWidget( DirectionCB, 1, 0, 1, 6 );
-  
+  CBAbsoluteOrientation = new QComboBox( GroupAbsoluteDirection );
+  CBAbsoluteOrientation->setObjectName( "AbsoluteOrientation" );
+  CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "CUSTOM" ) );
+  CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||X-Y" ) );
+  CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Y-Z" ) );
+  CBAbsoluteOrientation->insertItem( CBAbsoluteOrientation->count(), tr( "||Z-X" ) );
+  GroupDirectionLayout->addWidget( CBAbsoluteOrientation, 1, 0, 1, 6 );
+
+  QVBoxLayout* ModeActiveLayout = new QVBoxLayout();
+  ModeActiveLayout->setMargin( 11 ); ModeActiveLayout->setSpacing( 6 );
+  ModeActiveLayout->addWidget( GroupAbsolutePoint );
+  ModeActiveLayout->addWidget( GroupAbsoluteDirection );
+
+  QWidget* ModeActiveWidget = new QWidget( this );
+  ModeActiveWidget->setLayout( ModeActiveLayout );
+
+  /**********************   Mode Relative   **********************/
+  /* Controls for relative mode of clipping plane:
+     Distance - Value from 0 to 1.
+     Specifies the distance from the minimum value in a given direction of bounding box to the current position
+     Rotation1, Rotation2 - turn angles of cutting plane in given directions
+     Orientation - direction of cutting plane
+   */
+  QGroupBox* GroupParameters = new QGroupBox( tr("PARAMETERS"), this );
+  QGridLayout* GroupParametersLayout = new QGridLayout( GroupParameters );
+  GroupParametersLayout->setMargin( 11 ); GroupParametersLayout->setSpacing( 6 );
+
+  TextLabelOrientation = new QLabel( tr("ORIENTATION"), GroupParameters);
+  TextLabelOrientation->setObjectName( "TextLabelOrientation" );
+  GroupParametersLayout->addWidget( TextLabelOrientation, 0, 0 );
+
+  CBRelativeOrientation = new QComboBox(GroupParameters);
+  CBRelativeOrientation->setObjectName( "RelativeOrientation" );
+  CBRelativeOrientation->addItem( tr("ALONG_XY") );
+  CBRelativeOrientation->addItem( tr("ALONG_YZ") );
+  CBRelativeOrientation->addItem( tr("ALONG_ZX") );
+  GroupParametersLayout->addWidget( CBRelativeOrientation, 0, 1 );
+
+  TLValueDistance = new QLabel( GroupParameters );
+  TLValueDistance->setObjectName( "TLValueDistance" );
+  TLValueDistance->setAlignment( Qt::AlignCenter );
+  TLValueDistance->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
+  QFont fnt = TLValueDistance->font(); fnt.setBold( true ); TLValueDistance->setFont( fnt );
+  GroupParametersLayout->addWidget( TLValueDistance, 1, 1 );
+
+  TextLabelDistance = new QLabel( tr("DISTANCE"), GroupParameters );
+  TextLabelDistance->setObjectName( "TextLabelDistance" );
+  GroupParametersLayout->addWidget( TextLabelDistance, 2, 0 );
+
+  SliderDistance = new QSlider( Qt::Horizontal, GroupParameters );
+  SliderDistance->setObjectName( "SliderDistance" );
+  SliderDistance->setFocusPolicy( Qt::NoFocus );
+  SliderDistance->setMinimumSize( 300, 0 );
+  SliderDistance->setMinimum( 0 );
+  SliderDistance->setMaximum( 100 );
+  SliderDistance->setSingleStep( 1 );
+  SliderDistance->setPageStep( 10 );
+  SliderDistance->setTracking( false );
+  GroupParametersLayout->addWidget( SliderDistance, 2, 1 );
+
+  TLValueRotation1 = new QLabel( GroupParameters );
+  TLValueRotation1->setObjectName( "TLValueRotation1" );
+  TLValueRotation1->setAlignment( Qt::AlignCenter );
+  TLValueRotation1->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
+  TLValueRotation1->setFont( fnt );
+  GroupParametersLayout->addWidget( TLValueRotation1, 3, 1 );
+
+  TextLabelRotation1 = new QLabel( tr("ROTATION_AROUND_X_Y2Z"), GroupParameters );
+  TextLabelRotation1->setObjectName( "TextLabelRotation1" );
+  GroupParametersLayout->addWidget( TextLabelRotation1, 4, 0 );
+
+  SliderRotation1 = new QSlider( Qt::Horizontal, GroupParameters );
+  SliderRotation1->setObjectName( "SliderRotation1" );
+  SliderRotation1->setFocusPolicy( Qt::NoFocus );
+  SliderRotation1->setMinimumSize( 300, 0 );
+  SliderRotation1->setMinimum( -180 );
+  SliderRotation1->setMaximum( 180 );
+  SliderRotation1->setSingleStep( 1 );
+  SliderRotation1->setPageStep( 10 );
+  SliderRotation1->setTracking(false);
+  GroupParametersLayout->addWidget( SliderRotation1, 4, 1 );
+
+  TLValueRotation2 = new QLabel( GroupParameters );
+  TLValueRotation2->setObjectName( "TLValueRotation2" );
+  TLValueRotation2->setAlignment( Qt::AlignCenter );
+  TLValueRotation2->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
+  TLValueRotation2->setFont( fnt );
+  GroupParametersLayout->addWidget( TLValueRotation2, 5, 1 );
+
+  TextLabelRotation2 = new QLabel(tr("ROTATION_AROUND_Y_X2Z"), GroupParameters);
+  TextLabelRotation2->setObjectName( "TextLabelRotation2" );
+  TextLabelRotation2->setObjectName( "TextLabelRotation2" );
+  GroupParametersLayout->addWidget( TextLabelRotation2, 6, 0 );
+
+  SliderRotation2 = new QSlider( Qt::Horizontal, GroupParameters );
+  SliderRotation2->setObjectName( "SliderRotation2" );
+  SliderRotation2->setFocusPolicy( Qt::NoFocus );
+  SliderRotation2->setMinimumSize( 300, 0 );
+  SliderRotation2->setMinimum( -180 );
+  SliderRotation2->setMaximum( 180 );
+  SliderRotation2->setSingleStep( 1 );
+  SliderRotation2->setPageStep( 10 );
+  SliderRotation2->setTracking(false);
+  GroupParametersLayout->addWidget( SliderRotation2, 6, 1 );
+
   /***************************************************************/
+  QGroupBox* CheckBoxWidget = new QGroupBox( this );
+  QHBoxLayout* CheckBoxLayout = new QHBoxLayout( CheckBoxWidget );
   
-  PreviewChB = new QCheckBox( tr("Preview") ,this );
-  PreviewChB->setObjectName( "PreviewChB" );
-  PreviewChB->setChecked( true );
+  PreviewCheckBox = new QCheckBox( tr("PREVIEW"), CheckBoxWidget );
+  PreviewCheckBox->setObjectName( "PreviewCheckBox" );
+  PreviewCheckBox->setChecked( true );
+  CheckBoxLayout->addWidget( PreviewCheckBox, 0, Qt::AlignCenter );
   
+  AutoApplyCheckBox = new QCheckBox( tr("AUTO_APPLY"), CheckBoxWidget );
+  AutoApplyCheckBox->setObjectName( "AutoApplyCheckBox" );
+  CheckBoxLayout->addWidget( AutoApplyCheckBox, 0, Qt::AlignCenter );
+
   /***************************************************************/
   QGroupBox* GroupButtons = new QGroupBox( this );
-  GroupButtons->setObjectName( "GroupButtons" );
   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons );
   GroupButtonsLayout->setAlignment( Qt::AlignTop );
   GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 );
   
+  buttonOk = new QPushButton( GroupButtons );
+  buttonOk->setObjectName( "buttonOk" );
+  buttonOk->setText( tr( "BUT_APPLY_AND_CLOSE"  ) );
+  buttonOk->setAutoDefault( TRUE );
+  buttonOk->setDefault( TRUE );
+  GroupButtonsLayout->addWidget( buttonOk );
+
   buttonApply = new QPushButton( GroupButtons );
   buttonApply->setObjectName( "buttonApply" );
   buttonApply->setText( tr( "BUT_APPLY"  ) );
-  buttonApply->setAutoDefault( TRUE ); 
+  buttonApply->setAutoDefault( TRUE );
   buttonApply->setDefault( TRUE );
   GroupButtonsLayout->addWidget( buttonApply );
-  
+
   GroupButtonsLayout->addStretch();
   
   buttonClose = new QPushButton( GroupButtons );
@@ -205,47 +553,65 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, const
   buttonClose->setAutoDefault( TRUE );
   GroupButtonsLayout->addWidget( buttonClose );
 
+  QPushButton* buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons );
+  buttonHelp->setAutoDefault( TRUE );
+  GroupButtonsLayout->addWidget( buttonHelp );
+
   /***************************************************************/
-  
-  topLayout->addWidget( GroupPoint );
-  topLayout->addWidget( GroupDirection );
-  
-  topLayout->addWidget( PreviewChB );
+  ModeStackedLayout->addWidget( ModeActiveWidget );
+  ModeStackedLayout->addWidget( GroupParameters );
 
+  topLayout->addWidget( GroupPlanes );
+  topLayout->addLayout( ModeStackedLayout );
+  topLayout->addWidget( CheckBoxWidget );
   topLayout->addWidget( GroupButtons );
 
-  /* initializations */
+  this->setLayout( topLayout );
 
-  SpinBox_X->setValue( 0.0 );
-  SpinBox_Y->setValue( 0.0 );
-  SpinBox_Z->setValue( 0.0 );
+  // Initializations
+  initParam();
 
-  SpinBox_Dx->setValue( 1.0 );
-  SpinBox_Dy->setValue( 1.0 );
-  SpinBox_Dz->setValue( 1.0 );
+  // Signals and slots connections
+  connect( ComboBoxPlanes, SIGNAL( activated( int ) ), this, SLOT( onSelectPlane( int ) ) );
+  connect( isActivePlane,  SIGNAL ( toggled ( bool ) ),  this, SLOT( onValueChanged() ) );
+  connect( buttonNew, SIGNAL( clicked() ), buttonNew, SLOT( showMenu() ) );
+  connect( buttonDelete, SIGNAL( clicked() ), this, SLOT( ClickOnDelete() ) );
+  connect( buttonDisableAll, SIGNAL( clicked() ), this, SLOT( ClickOnDisableAll() ) );
 
-  /* signals and slots connections */
   connect( resetButton,  SIGNAL (clicked() ), this, SLOT( onReset() ) );
   connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
-
   connect( SpinBox_X,  SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
   connect( SpinBox_Y,  SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
   connect( SpinBox_Z,  SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
   connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
   connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
   connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ),  this, SLOT( onValueChanged() ) );
-   
-  connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
-
-  connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
+  connect( CBAbsoluteOrientation, SIGNAL ( activated ( int ) ), this, SLOT( onOrientationAbsoluteChanged( int ) ) ) ;
+
+  connect( CBRelativeOrientation, SIGNAL( activated( int ) ), this, SLOT( onOrientationRelativeChanged( int ) ) );
+  connect( SliderDistance,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderDistanceHasMoved( int ) ) );
+  connect( SliderDistance,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderDistanceHasMoved( int ) ) );
+  connect( SliderRotation1,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderRotation1HasMoved( int ) ) );
+  connect( SliderRotation1,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderRotation1HasMoved( int ) ) );
+  connect( SliderRotation2,   SIGNAL( sliderMoved( int ) ),  this, SLOT( SliderRotation2HasMoved( int ) ) );
+  connect( SliderRotation2,   SIGNAL( valueChanged( int ) ),  this, SLOT( SliderRotation2HasMoved( int ) ) );
+
+  connect( PreviewCheckBox, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
+  connect( AutoApplyCheckBox, SIGNAL ( toggled( bool ) ), this, SLOT( onAutoApply( bool ) ) );
   
   connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
+  connect( buttonOk, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
   connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
+  connect( buttonHelp, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) );
   
+  connect(view, SIGNAL(Show( QShowEvent* ) ), this, SLOT( onViewShow() ) );
+  connect(view, SIGNAL(Hide( QHideEvent* ) ), this, SLOT( onViewHide() ) );
+
   myBusy = false;
+  myIsSelectPlane = false;
+  myView3d = myView->getViewPort()->getView();
 
-  connect(view, SIGNAL(Show( QShowEvent * )), this, SLOT(onViewShow()));
-  connect(view, SIGNAL(Hide( QHideEvent * )), this, SLOT(onViewHide()));
+  synchronize();
 }
 
 /*!
@@ -255,39 +621,29 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, const
 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
 {
   // no need to delete child widgets, Qt does it all for us
+  foreach( ClipPlane* aPlane, myClippingPlanes )
+    delete aPlane;
 }
 
-
 /*!
   Custom handling of close event: erases preview
 */
 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
 {
   erasePreview();
-  
-  // Set the clipping plane back
-  /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
-  if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
-  aView3d->SetPlaneOn( myClippingPlane );*/
-  
   myAction->setChecked( false );
-  
   QDialog::closeEvent( e );
 }
 
-
 /*!
   Custom handling of show event: displays preview
 */
 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
 {
-  //ReserveClippingPlane();
-  
   QDialog::showEvent( e );
-  onPreview( PreviewChB->isChecked() );
+  onPreview( PreviewCheckBox->isChecked() );
 }
 
-
 /*!
   Custom handling of hide event: erases preview
 */
@@ -297,42 +653,400 @@ void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
   QDialog::hideEvent( e );
 }
 
+/*!
+  Initialization of initial values of widgets
+*/
+void OCCViewer_ClippingDlg::initParam()
+{
+  SpinBox_X->setValue( 0.0 );
+  SpinBox_Y->setValue( 0.0 );
+  SpinBox_Z->setValue( 0.0 );
+
+  SpinBox_Dx->setValue( 1.0 );
+  SpinBox_Dy->setValue( 1.0 );
+  SpinBox_Dz->setValue( 1.0 );
+
+  CBAbsoluteOrientation->setCurrentIndex(0);
+
+  TLValueDistance->setText( "0" );
+  TLValueRotation1->setText( "0\xB0" );
+  TLValueRotation2->setText( "0\xB0" );
+  CBRelativeOrientation->setCurrentIndex( 0 );
+  SliderDistance->setValue( 50 );
+  SliderRotation1->setValue( 0 );
+  SliderRotation2->setValue( 0 );
+}
 
 /*!
-  SLOT on close button click: erases preview and rejects dialog
+  Synchronize dialog's widgets with data
 */
-void OCCViewer_ClippingDlg::ClickOnClose()
+void OCCViewer_ClippingDlg::synchronize()
 {
-  erasePreview();
+  ComboBoxPlanes->clear();
+  int aNbPlanesAbsolute = myClippingPlanes.size();
 
-  // Set the clipping plane back
-  /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
-  if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
-    aView3d->SetPlaneOn( myClippingPlane );
-  */
-  myAction->setChecked( false );
-  
-  reject();
+  QString aName;
+  for(int i = 1; i<=aNbPlanesAbsolute; i++ ) {
+    aName = QString("Plane %1").arg(i);
+    ComboBoxPlanes->addItem( aName );
+  }
+
+  int aPos = ComboBoxPlanes->count() - 1;
+  ComboBoxPlanes->setCurrentIndex( aPos );
+
+  bool anIsControlsEnable = ( aPos >= 0 );
+  if ( anIsControlsEnable ) {
+    onSelectPlane( aPos );
+  }
+  else {
+    ComboBoxPlanes->addItem( tr( "NO_PLANES" ) );
+    initParam();
+    ClickOnDisableAll();
+  }
+  if ( CurrentMode == Absolute ) {
+    SpinBox_X->setEnabled( anIsControlsEnable );
+    SpinBox_Y->setEnabled( anIsControlsEnable );
+    SpinBox_Z->setEnabled( anIsControlsEnable );
+    SpinBox_Dx->setEnabled( anIsControlsEnable );
+    SpinBox_Dy->setEnabled( anIsControlsEnable );
+    SpinBox_Dz->setEnabled( anIsControlsEnable );
+    CBAbsoluteOrientation->setEnabled( anIsControlsEnable );
+    invertButton->setEnabled( anIsControlsEnable );
+    resetButton->setEnabled( anIsControlsEnable );
+  }
+  else if( CurrentMode == Relative ) {
+    CBRelativeOrientation->setEnabled( anIsControlsEnable );
+    SliderDistance->setEnabled( anIsControlsEnable );
+    SliderRotation1->setEnabled( anIsControlsEnable );
+    SliderRotation2->setEnabled( anIsControlsEnable );
+    isActivePlane->setEnabled( anIsControlsEnable );
+  }
+  isActivePlane->setEnabled( anIsControlsEnable );
 }
 
+/*!
+  Displays preview of clipping plane
+*/
+void OCCViewer_ClippingDlg::displayPreview()
+{
+  if ( myBusy || !isValid() )
+    return;
+
+  OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
+  if ( !anOCCViewer )
+    return;
+
+  Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
+
+  double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
+  aXMin = aYMin = aZMin = DBL_MAX;
+  aXMax = aYMax = aZMax = -DBL_MAX;
+
+  bool isFound = false;
+  AIS_ListOfInteractive aList;
+  ic->DisplayedObjects( aList );
+  for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
+  {
+    Handle(AIS_InteractiveObject) anObj = it.Value();
+    if ( !anObj.IsNull() && anObj->HasPresentation() &&
+         !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) ) {
+      Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
+      if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() ) {
+        isFound = true;
+        double xmin, ymin, zmin, xmax, ymax, zmax;
+        aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
+        aXMin = qMin( aXMin, xmin );  aXMax = qMax( aXMax, xmax );
+        aYMin = qMin( aYMin, ymin );  aYMax = qMax( aYMax, ymax );
+        aZMin = qMin( aZMin, zmin );  aZMax = qMax( aZMax, zmax );
+      }
+    }
+  }
+
+  double aSize = 50;
+
+  ClipPlane* aClipPlane;
+  for ( int i=0; i < myClippingPlanes.size(); i++ ) {
+  Pnt_ClipPlane aPlane = myClippingPlanes[i];
+  aClipPlane = aPlane;
+
+  double Epsilon = 0.0001;
+  double Epsilon_Dx = ( aClipPlane->Dx > 0 ) ? Epsilon: -Epsilon;
+  double Epsilon_Dy = ( aClipPlane->Dy > 0 ) ? Epsilon: -Epsilon;
+  double Epsilon_Dz = ( aClipPlane->Dz > 0 ) ? Epsilon: -Epsilon;
+
+  gp_Pnt aBasePnt( aClipPlane->X + Epsilon_Dx,  aClipPlane->Y + Epsilon_Dy,  aClipPlane->Z + Epsilon_Dz );
+  gp_Dir aNormal( aClipPlane->Dx, aClipPlane->Dy, aClipPlane->Dz );
+  gp_Pnt aCenter = aBasePnt;
+
+  if ( isFound )
+  {
+    // compute clipping plane size
+    aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
+    double aDiag = aCenter.Distance( gp_Pnt( aXMax, aYMax, aZMax ) )*2;
+    aSize = aDiag * 1.1;
+
+    // compute clipping plane center ( redefine the base point )
+    IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
+
+    intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
+    if ( intersector.IsDone() && intersector.NbPoints() == 1 )
+      aBasePnt = intersector.Point( 1 );
+    }
+
+    if ( aClipPlane->IsActive == true ) {
+      Handle(AIS_Plane) myPreviewPlane;
+      myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
+      myPreviewPlane->SetSize( aSize, aSize );
+
+      ic->Display( myPreviewPlane, 1, -1, false );
+      ic->SetWidth( myPreviewPlane, 10, false );
+      ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
+      ic->SetTransparency( myPreviewPlane, 0.5, false );
+      ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
+
+      myPreviewPlaneVector.push_back( myPreviewPlane );
+    }
+  }
+  anOCCViewer->update();
+}
 
 /*!
-  SLOT on apply button click: sets cutting plane
+  Erases preview of clipping plane
 */
-void OCCViewer_ClippingDlg::ClickOnApply()
+void OCCViewer_ClippingDlg::erasePreview()
 {
-  qApp->processEvents();
-  QApplication::setOverrideCursor( Qt::WaitCursor );
-  qApp->processEvents();
-  
-  myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
-                                 SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
+  OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
+  if ( !anOCCViewer )
+    return;
   
-  QApplication::restoreOverrideCursor(); 
+  Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
   
+  for ( int i=0; i < myPreviewPlaneVector.size(); i++ ) {
+  Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[i];
+    if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
+      ic->Erase( myPreviewPlane, false );
+      ic->Remove( myPreviewPlane, false );
+      myPreviewPlane.Nullify();
+    }
+  }
+  anOCCViewer->update();
+}
+
+/*!
+  Return true if plane parameters are valid
+*/
+bool OCCViewer_ClippingDlg::isValid()
+{
+  return ( SpinBox_Dx->value() !=0 || SpinBox_Dy->value() !=0 || SpinBox_Dz->value() !=0 );
+}
+
+/*!
+  Update view after changes
+*/
+void OCCViewer_ClippingDlg::updateView()
+{
+  if ( PreviewCheckBox->isChecked() || AutoApplyCheckBox->isChecked() ) {
+    erasePreview();
+    if ( AutoApplyCheckBox->isChecked() )
+      onApply();
+    if ( PreviewCheckBox->isChecked() && !isRestore )
+      displayPreview();
+  }
+}
+
+/*!
+  SLOT on new button click: create a new clipping plane
+*/
+void OCCViewer_ClippingDlg::ClickOnNew()
+{
+  ClipPlane* aPlane = new ClipPlane();
+  aPlane->PlaneMode = CurrentMode;
+  myClippingPlanes.push_back( aPlane );
+  synchronize();
+}
+
+/*!
+  SLOT on delete button click: Delete selected clipping plane
+*/
+void OCCViewer_ClippingDlg::ClickOnDelete()
+{
+  if ( myClippingPlanes.empty() )
+    return;
+
+  int aPlaneIndex = ComboBoxPlanes->currentIndex();
+
+  ClipPlaneVector::iterator anIter = myClippingPlanes.begin() + aPlaneIndex;
+  myClippingPlanes.erase( anIter );
+  updateView();
+  synchronize();
+}
+
+/*!
+  SLOT on disable all button click: Restore initial state of viewer,
+  erase all clipping planes
+*/
+void OCCViewer_ClippingDlg::ClickOnDisableAll()
+{
+  AutoApplyCheckBox->setChecked( false );
+  Graphic3d_SetOfHClipPlane aPlanes = myView3d->GetClipPlanes();
+  Graphic3d_SetOfHClipPlane::Iterator anIter (aPlanes);
+  for( ;anIter.More();anIter.Next() ){
+    Handle(Graphic3d_ClipPlane) aClipPlane = anIter.Value();
+    aClipPlane->SetOn(Standard_False);
+  }
+  myView3d->Update();
+  myView3d->Redraw();
+}
+
+/*!
+  SLOT on ok button click: sets cutting plane and closes dialog
+*/
+void OCCViewer_ClippingDlg::ClickOnOk()
+{
+  onApply();
   erasePreview();
-  
-  //ReserveClippingPlane();
+  myAction->setChecked( false );
+}
+
+/*!
+  SLOT on Apply button click: sets cutting plane and update viewer
+*/
+void OCCViewer_ClippingDlg::ClickOnApply()
+{
+  onApply();
+  myView3d->Update();
+  myView3d->Redraw();
+}
+
+/*!
+  SLOT on close button click: erases preview and rejects dialog
+*/
+void OCCViewer_ClippingDlg::ClickOnClose()
+{
+  erasePreview();
+  myAction->setChecked( false );
+}
+
+/*!
+  SLOT on help button click: opens a help page
+*/
+void OCCViewer_ClippingDlg::ClickOnHelp()
+{
+  SUIT_Application* app = SUIT_Session::session()->activeApplication();
+  if ( app )
+    app->onHelpContextModule( "GUI", "occ_3d_viewer_page.html", "clipping_planes" );
+}
+
+/*!
+  Set absolute mode of clipping plane
+*/
+void OCCViewer_ClippingDlg::onModeAbsolute()
+{
+  ModeStackedLayout->setCurrentIndex(0);
+  CurrentMode = Absolute;
+  ClickOnNew();
+  onValueChanged();
+}
+
+/*!
+  Set relative mode of clipping plane
+*/
+void OCCViewer_ClippingDlg::onModeRelative()
+{
+  ModeStackedLayout->setCurrentIndex(1);
+  CurrentMode = Relative;
+  ClickOnNew();
+  onValueChanged();
+}
+
+/*!
+  SLOT: called on value of clipping plane changed
+*/
+void OCCViewer_ClippingDlg::onValueChanged()
+{
+  SetCurrentPlaneParam();
+  if ( myIsSelectPlane )
+    return;
+  updateView();
+}
+
+/*!
+  Set current parameters of selected plane
+*/
+void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
+{
+  if ( myClippingPlanes.empty() )
+    return;
+
+  Pnt_ClipPlane aPlane = myClippingPlanes[theIndex];
+  ClipPlane* aClipPlane = aPlane;
+
+  myIsSelectPlane = true;
+  if ( aClipPlane->PlaneMode == Absolute ) {
+    ModeStackedLayout->setCurrentIndex( 0 );
+    CurrentMode = Absolute;
+    int anOrientation = aClipPlane->Orientation;
+    // Set plane parameters in the dialog
+    SpinBox_X->setValue( aClipPlane->X );
+    SpinBox_Y->setValue( aClipPlane->Y );
+    SpinBox_Z->setValue( aClipPlane->Z );
+    SpinBox_Dx->setValue( aClipPlane->Dx );
+    SpinBox_Dy->setValue( aClipPlane->Dy );
+    SpinBox_Dz->setValue( aClipPlane->Dz );
+    CBAbsoluteOrientation->setCurrentIndex( anOrientation );
+    onOrientationAbsoluteChanged( anOrientation );
+  }
+  else if( aClipPlane->PlaneMode == Relative ) {
+    ModeStackedLayout->setCurrentIndex( 1 );
+    CurrentMode = Relative;
+    int anOrientation = aClipPlane->RelativeMode.Orientation;
+    // Set plane parameters in the dialog
+    SliderDistance->setValue( aClipPlane->RelativeMode.Distance*100 );
+    TLValueDistance->setText( QString::number(aClipPlane->RelativeMode.Distance ) );
+    SliderRotation1->setValue( aClipPlane->RelativeMode.Rotation1 );
+    TLValueRotation1->setText( QString( "%1\xB0" ).arg( aClipPlane->RelativeMode.Rotation1 ) );
+    SliderRotation2->setValue( aClipPlane->RelativeMode.Rotation2 );
+    TLValueRotation2->setText( QString( "%1\xB0" ).arg( aClipPlane->RelativeMode.Rotation2 ) );
+    CBRelativeOrientation->setCurrentIndex( anOrientation );
+    onOrientationRelativeChanged( anOrientation );
+  }
+  isActivePlane->setChecked( aClipPlane->IsActive );
+  ComboBoxPlanes->setCurrentIndex( theIndex );
+
+  myIsSelectPlane = false;
+}
+
+/*!
+  Restore parameters of selected plane
+*/
+void OCCViewer_ClippingDlg::SetCurrentPlaneParam()
+{
+  if ( myClippingPlanes.empty() || myIsSelectPlane )
+    return;
+
+  int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
+
+  Pnt_ClipPlane aPlane = myClippingPlanes[aCurPlaneIndex];
+  ClipPlane* aPlaneData = aPlane;
+
+  if ( aPlaneData->PlaneMode == Absolute ) {
+    aPlaneData->Orientation = CBAbsoluteOrientation->currentIndex();
+    aPlaneData->X = SpinBox_X->value();
+    aPlaneData->Y = SpinBox_Y->value();
+    aPlaneData->Z = SpinBox_Z->value();
+    aPlaneData->Dx = SpinBox_Dx->value();
+    aPlaneData->Dy = SpinBox_Dy->value();
+    aPlaneData->Dz = SpinBox_Dz->value();
+  }
+  else if( aPlaneData->PlaneMode == Relative ) {
+    aPlaneData->RelativeMode.Orientation = CBRelativeOrientation->currentIndex();
+    aPlaneData->RelativeMode.Distance = TLValueDistance->text().toDouble();
+    aPlaneData->RelativeMode.Rotation1 = TLValueRotation1->text().remove("\xB0").toInt();
+    aPlaneData->RelativeMode.Rotation2 = TLValueRotation2->text().remove("\xB0").toInt();
+    erasePreview();
+    RelativePlaneToAbsolute( aPlane, myView3d );
+  }
+  aPlaneData->IsActive = isActivePlane->isChecked();
 }
 
 /*!
@@ -346,11 +1060,7 @@ void OCCViewer_ClippingDlg::onReset()
   SpinBox_Z->setValue(0);
   myBusy = false;
 
-  if ( PreviewChB->isChecked() )
-    {
-      erasePreview();
-      displayPreview();
-    }
+  updateView();
 }
 
 /*!
@@ -361,27 +1071,29 @@ void OCCViewer_ClippingDlg::onInvert()
   double Dx = SpinBox_Dx->value();
   double Dy = SpinBox_Dy->value();
   double Dz = SpinBox_Dz->value();
-  
+
   myBusy = true;
   SpinBox_Dx->setValue( -Dx );
   SpinBox_Dy->setValue( -Dy );
   SpinBox_Dz->setValue( -Dz );
   myBusy = false;
 
-  if ( PreviewChB->isChecked() )
-    {
-      erasePreview();
-      displayPreview();
-    }
+  if ( !myClippingPlanes.empty() ) {
+    int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
+    Pnt_ClipPlane aPlane = myClippingPlanes[aCurPlaneIndex];
+    ClipPlane* aPlaneData = aPlane;
+    aPlaneData->IsInvert = !aPlaneData->IsInvert;
+  }
+  updateView();
 }
 
 /*!
-  SLOT: called on mode changed
+  SLOT: called on orientation of clipping plane in absolute mode changed
 */
-void OCCViewer_ClippingDlg::onModeChanged( int mode )
+void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode )
 {
   bool isUserMode = (mode==0);
-  
+
   TextLabelX->setEnabled( isUserMode );
   TextLabelY->setEnabled( isUserMode );
   TextLabelZ->setEnabled( isUserMode );
@@ -397,196 +1109,126 @@ void OCCViewer_ClippingDlg::onModeChanged( int mode )
   SpinBox_Dx->setEnabled( isUserMode );
   SpinBox_Dy->setEnabled( isUserMode );
   SpinBox_Dz->setEnabled( isUserMode );
-  
+
   if ( isUserMode )
     return;
 
   double aDx = 0, aDy = 0, aDz = 0;
 
   if ( mode == 1 )
-    {
-      aDz = 1;
-      TextLabelZ->setEnabled( true );
-      SpinBox_Z->setEnabled( true );
-      SpinBox_Z->setFocus();
-    }
+  {
+    aDz = 1;
+    TextLabelZ->setEnabled( true );
+    SpinBox_Z->setEnabled( true );
+    SpinBox_Z->setFocus();
+  }
   else if ( mode == 2 )
-    {
-      aDx = 1;
-      TextLabelX->setEnabled( true );
-      SpinBox_X->setEnabled( true );
-      SpinBox_X->setFocus();
-    }
+  {
+    aDx = 1;
+    TextLabelX->setEnabled( true );
+    SpinBox_X->setEnabled( true );
+    SpinBox_X->setFocus();
+  }
   else if ( mode == 3 )
-    {
-      aDy = 1;
-      TextLabelY->setEnabled( true );
-      SpinBox_Y->setEnabled( true );
-      SpinBox_Y->setFocus();
-    }
-  
+  {
+    aDy = 1;
+    TextLabelY->setEnabled( true );
+    SpinBox_Y->setEnabled( true );
+    SpinBox_Y->setFocus();
+  }
+
+  int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
+  Pnt_ClipPlane aPlane = myClippingPlanes[aCurPlaneIndex];
+  ClipPlane* aPlaneData = aPlane;
+  if ( aPlaneData->IsInvert == true ) {
+    aDx = -aDx; aDy = -aDy; aDz = -aDz;
+  }
+
   myBusy = true;
   SpinBox_Dx->setValue( aDx );
   SpinBox_Dy->setValue( aDy );
   SpinBox_Dz->setValue( aDz );
   myBusy = false;
 
-  if ( PreviewChB->isChecked() )
-    {
-      erasePreview();
-      displayPreview();
-    }
+  SetCurrentPlaneParam();
+  updateView();
 }
 
-
 /*!
-  Displays preview of clipping plane
+  SLOT: called on orientation of clipping plane in relative mode changed
 */
-void OCCViewer_ClippingDlg::displayPreview()
+void OCCViewer_ClippingDlg::onOrientationRelativeChanged (int theItem)
 {
-  if ( myBusy || !isValid() )
+  if ( myClippingPlanes.empty() )
     return;
 
-  OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
-  if (!anOCCViewer)
-    return;
-  
-  Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
-
-  double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
-  aXMin = aYMin = aZMin = DBL_MAX;
-  aXMax = aYMax = aZMax = -DBL_MAX;
-
-  bool isFound = false;
-  AIS_ListOfInteractive aList;
-  ic->DisplayedObjects( aList );
-  for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
-  {
-    Handle(AIS_InteractiveObject) anObj = it.Value();
-    if ( !anObj.IsNull() && anObj->HasPresentation() &&
-         !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
-    {
-      Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
-      if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
-      {
-        isFound = true;
-        double xmin, ymin, zmin, xmax, ymax, zmax;
-        aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
-        aXMin = qMin( aXMin, xmin );  aXMax = qMax( aXMax, xmax );
-        aYMin = qMin( aYMin, ymin );  aYMax = qMax( aYMax, ymax );
-        aZMin = qMin( aZMin, zmin );  aZMax = qMax( aZMax, zmax );
-      }
-    }
+  if ( theItem == 0 ) {
+    TextLabelRotation1->setText( tr( "ROTATION_AROUND_X_Y2Z" ) );
+    TextLabelRotation2->setText( tr( "ROTATION_AROUND_Y_X2Z" ) );
+  }
+  else if ( theItem == 1 ) {
+    TextLabelRotation1->setText( tr( "ROTATION_AROUND_Y_Z2X" ) );
+    TextLabelRotation2->setText( tr( "ROTATION_AROUND_Z_Y2X" ) );
+  }
+  else if ( theItem == 2 ) {
+    TextLabelRotation1->setText( tr( "ROTATION_AROUND_Z_X2Y" ) );
+    TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) );
   }
 
-  double aSize = 50;
-  
-  gp_Pnt aBasePnt( SpinBox_X->value(),  SpinBox_Y->value(),  SpinBox_Z->value() );
-  gp_Dir aNormal( SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
-  gp_Pnt aCenter = aBasePnt;
-  
-  if ( isFound )
-    {
-      // compute clipping plane size
-      aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
-      double aDiag = aCenter.Distance(gp_Pnt(aXMax, aYMax, aZMax ))*2;
-      aSize = aDiag * 1.1;
-
-      // compute clipping plane center ( redefine the base point )
-      IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
-      
-      intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
-      if ( intersector.IsDone() && intersector.NbPoints() == 1 )
-        aBasePnt = intersector.Point( 1 );
-    }
-  
-  myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
-  myPreviewPlane->SetSize( aSize, aSize );
-  
-  // Deactivate clipping planes
-  //myView->getViewPort()->getView()->SetPlaneOff();
-  //myView->setPlaneOff();
-
-  ic->Display( myPreviewPlane, 1, -1, false );
-  ic->SetWidth( myPreviewPlane, 10, false );
-  ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
-  ic->SetTransparency( myPreviewPlane, 0.5, false );
-  ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
-  
-  anOCCViewer->update();
-}
-
-
-/*!
-  Erases preview of clipping plane
-*/
-void OCCViewer_ClippingDlg::erasePreview ()
-{
-  OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
-  if (!anOCCViewer)
-    return;
-  
-  Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
-  
-  if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
-    {
-#if OCC_VERSION_LARGE <= 0x06060000
-      ic->Erase( myPreviewPlane, false, false );
-#else
-      ic->Erase( myPreviewPlane, false );
-#endif
-      ic->Remove( myPreviewPlane, false );
-      myPreviewPlane.Nullify();
-    }
-  
-  anOCCViewer->update();
-}
-
-
-/*!
-  SLOT: called on value changes (co-ordinates of point or normal)
-*/
-void OCCViewer_ClippingDlg::onValueChanged()
-{
-  if ( PreviewChB->isChecked() )
-    {
-      erasePreview();
-      displayPreview();
-    }
+  if( (QComboBox*)sender() == CBRelativeOrientation )
+    SetCurrentPlaneParam();
+  updateView();
 }
 
-
 /*!
   SLOT: called on preview check box toggled
 */
 void OCCViewer_ClippingDlg::onPreview( bool on )
 {
   erasePreview();
-
   if ( on ) 
     displayPreview();
 }
 
 /*!
-  \return true if plane parameters are valid
+  SLOT: called on Auto Apply check box toggled
 */
-bool OCCViewer_ClippingDlg::isValid()
+void OCCViewer_ClippingDlg::onAutoApply( bool toggled )
 {
-  return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
+  if ( toggled ) onApply();
+  myView3d->Update();
+  myView3d->Redraw();
 }
 
 /*!
-  Remember the current clipping plane
+  SLOT on Apply button click: sets cutting plane
 */
-void OCCViewer_ClippingDlg::ReserveClippingPlane()
+void OCCViewer_ClippingDlg::onApply()
 {
-  /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
-  if ( !aView3d.IsNull() )
-    {
-      aView3d->InitActivePlanes();
-      if ( aView3d->MoreActivePlanes() )
-        myClippingPlane = aView3d->ActivePlane();
-        }*/
+  if ( myBusy )
+    return;
+  myIsSelectPlane = true;
+  Graphic3d_SetOfHClipPlane aPlanes = myView3d->GetClipPlanes();
+  Graphic3d_SetOfHClipPlane::Iterator anIter (aPlanes);
+  for( ;anIter.More();anIter.Next() ){
+    Handle(Graphic3d_ClipPlane) aClipPlane = anIter.Value();
+    aClipPlane->SetOn(Standard_False);
+  }
+
+  qApp->processEvents();
+  QApplication::setOverrideCursor( Qt::WaitCursor );
+  qApp->processEvents();
+
+  for ( int i=0;i<myClippingPlanes.size();i++ ) {
+    Pnt_ClipPlane aPlane = myClippingPlanes[i];
+    ClipPlane* aClipPlane = aPlane;
+    if ( aClipPlane->IsActive == true )
+      myView->setCuttingPlane( true, aClipPlane->X , aClipPlane->Y , aClipPlane->Z,
+                               aClipPlane->Dx, aClipPlane->Dy, aClipPlane->Dz );
+  }
+
+  QApplication::restoreOverrideCursor();
+  myIsSelectPlane = false;
 }
 
 void OCCViewer_ClippingDlg::onViewShow()
@@ -602,3 +1244,30 @@ void OCCViewer_ClippingDlg::onViewHide()
   hide();
 }
 
+/*!
+  SLOT: Called when value of slider distance change
+*/
+void OCCViewer_ClippingDlg::SliderDistanceHasMoved( int value )
+{
+  double new_value = value/100.;
+  TLValueDistance->setText( QString("%1").arg( new_value ) );
+  onValueChanged();
+}
+
+/*!
+  SLOT: Called when value of slider rotation1 change
+*/
+void OCCViewer_ClippingDlg::SliderRotation1HasMoved( int value )
+{
+  TLValueRotation1->setText( QString("%1\xB0").arg( value ) );
+  onValueChanged();
+}
+
+/*!
+  SLOT: Called when value of slider rotation2 change
+*/
+void OCCViewer_ClippingDlg::SliderRotation2HasMoved( int value )
+{
+  TLValueRotation2->setText( QString("%1\xB0").arg( value ) );
+  onValueChanged();
+}
index 92c785ab31873e461568efc09257065df03172c8..63ee8d84fd8c065c98377fc715eee61ad1429d59 100644 (file)
@@ -37,9 +37,43 @@ class QComboBox;
 class QCheckBox;
 class QtxDoubleSpinBox;
 class QtxAction;
+class QStackedLayout;
+class QSlider;
+class QMenu;
 
 class OCCViewer_ViewWindow;
 
+enum Mode { Absolute, Relative };
+
+/*!
+  \class OrientedPlane
+  \brief Parameters of clipping plane in relative mode
+*/
+class OrientedPlane {
+public:
+  int Orientation;
+  double Distance;
+  double Rotation1;
+  double Rotation2;
+  OrientedPlane();
+};
+
+/*!
+  \class ClipPlane
+  \brief Parameters of clipping plane
+*/
+class ClipPlane {
+public:
+  OrientedPlane RelativeMode;
+  double X,Y,Z,Dx,Dy,Dz;
+  int Orientation;
+  bool IsActive;
+  bool IsInvert;
+  Mode PlaneMode;
+  ClipPlane();
+};
+typedef ClipPlane* Pnt_ClipPlane;
+typedef std::vector<Pnt_ClipPlane> ClipPlaneVector;
 
 /*!
   \class OCCViewer_ClippingDlg
@@ -49,69 +83,121 @@ class OCCViewer_ClippingDlg : public QDialog
 {
     Q_OBJECT
     
-    public:
-    OCCViewer_ClippingDlg(OCCViewer_ViewWindow* , const char* name = 0, bool modal = FALSE, Qt::WindowFlags fl = 0);
-    ~OCCViewer_ClippingDlg();
+  public:
+  OCCViewer_ClippingDlg(OCCViewer_ViewWindow* , const char* name = 0, bool modal = FALSE, Qt::WindowFlags fl = 0);
+  ~OCCViewer_ClippingDlg();
 
-    void SetAction( QtxAction* theAction ) { myAction = theAction; }
+  void SetAction( QtxAction* theAction ) { myAction = theAction; }
+  void synchronize();
+  void SetCurrentPlaneParam();
     
+  ClipPlaneVector myClippingPlanes;
+  bool isRestore;
+
 private :
 
-    virtual void closeEvent( QCloseEvent* e );
-    virtual void showEvent ( QShowEvent * );
-    virtual void hideEvent ( QHideEvent * );
-    void displayPreview();
-    void erasePreview();
-    void ReserveClippingPlane();
-
-    bool isValid();
-     
-    QGroupBox* GroupPoint;
-    QLabel* TextLabelX;
-    QLabel* TextLabelY;
-    QLabel* TextLabelZ;
-    QtxDoubleSpinBox* SpinBox_X;
-    QtxDoubleSpinBox* SpinBox_Y;
-    QtxDoubleSpinBox* SpinBox_Z;
-    QPushButton* resetButton;
+  virtual void closeEvent( QCloseEvent* e );
+  virtual void showEvent ( QShowEvent * );
+  virtual void hideEvent ( QHideEvent * );
+  void initParam();
+  void displayPreview();
+  void erasePreview();
+  bool isValid();
+  void updateView();
+
+  QComboBox* ComboBoxPlanes;
+  QCheckBox* isActivePlane;
+  QPushButton* buttonNew;
+  QMenu* MenuMode;
+  QPushButton* buttonDelete;
+  QPushButton* buttonDisableAll;
+
+  QStackedLayout *ModeStackedLayout;
+
+  QGroupBox* GroupAbsolutePoint;
+  QLabel* TextLabelX;
+  QLabel* TextLabelY;
+  QLabel* TextLabelZ;
+  QtxDoubleSpinBox* SpinBox_X;
+  QtxDoubleSpinBox* SpinBox_Y;
+  QtxDoubleSpinBox* SpinBox_Z;
+  QPushButton* resetButton;
+    
+  QGroupBox* GroupAbsoluteDirection;
+  QLabel* TextLabelDx;
+  QLabel* TextLabelDy;
+  QLabel* TextLabelDz;
+  QtxDoubleSpinBox* SpinBox_Dx;
+  QtxDoubleSpinBox* SpinBox_Dy;
+  QtxDoubleSpinBox* SpinBox_Dz;
+  QPushButton* invertButton;
+  QComboBox* CBAbsoluteOrientation;
     
-    QGroupBox* GroupDirection;
-    QLabel* TextLabelDx;
-    QLabel* TextLabelDy;
-    QLabel* TextLabelDz;
-    QtxDoubleSpinBox* SpinBox_Dx;
-    QtxDoubleSpinBox* SpinBox_Dy;
-    QtxDoubleSpinBox* SpinBox_Dz;
-    QPushButton* invertButton;
+  QGroupBox* GroupRelative;
+  QLabel* TextLabelOrientation;
+  QLabel* TextLabelDistance;
+  QLabel* TextLabelRotation1;
+  QLabel* TextLabelRotation2;
+  QLabel* TLValueDistance;
+  QLabel* TLValueRotation1;
+  QLabel* TLValueRotation2;
+  QSlider* SliderDistance;
+  QSlider* SliderRotation1;
+  QSlider* SliderRotation2;
+  QComboBox* CBRelativeOrientation;
+
+  QCheckBox* PreviewCheckBox;
+  QCheckBox* AutoApplyCheckBox;
+
+  QPushButton* buttonOk;
+  QPushButton* buttonApply;
+  QPushButton* buttonClose;
     
-    QComboBox* DirectionCB;
+  OCCViewer_ViewWindow* myView;
+  Handle(V3d_View) myView3d;
 
-    QCheckBox* PreviewChB;
+  std::vector<Handle(AIS_Plane)> myPreviewPlaneVector;
 
-    QPushButton*    buttonApply;
-    QPushButton*    buttonClose;
-    
-    OCCViewer_ViewWindow* myView;
+  bool myIsSelectPlane;
+  bool myBusy;
 
-    Handle(AIS_Plane) myPreviewPlane;
-    //Handle(V3d_Plane) myClippingPlane;
-    
-    bool myBusy;
+  Mode CurrentMode;
+
+  QtxAction* myAction;
 
-    QtxAction* myAction;
+public slots:
+  void onApply();
     
 private slots:
+
+  void ClickOnNew();
+  void ClickOnDelete();
+  void ClickOnDisableAll();
+  void ClickOnOk();
   void ClickOnApply();
   void ClickOnClose();
+  void ClickOnHelp();
+
+  void onModeAbsolute();
+  void onModeRelative();
+
+  void onValueChanged();
+  void onSelectPlane( int );
 
   void onReset();
   void onInvert();
-  void onModeChanged( int mode );
-  void onValueChanged();
+  void onOrientationAbsoluteChanged( int );
+  void onOrientationRelativeChanged (int);
+
   void onPreview( bool on );
+  void onAutoApply(bool);
 
   void onViewShow();
   void onViewHide();
+
+  void SliderDistanceHasMoved(int);
+  void SliderRotation1HasMoved(int);
+  void SliderRotation2HasMoved(int);
 };
 
 #endif // OCCVIEWER_CLIPPINGDLG_H
index c783846ce556a7f9b48525576a791b63cf123bc6..4697e6acbaf45eb231285c7a5a7ec30d8907c4e7 100755 (executable)
@@ -1216,7 +1216,8 @@ void OCCViewer_ViewWindow::createActions()
   myClippingAction->setStatusTip(tr("DSC_CLIPPING"));
   myClippingAction->setCheckable( true );
   connect(myClippingAction, SIGNAL(toggled( bool )), this, SLOT(onClipping( bool )));
-  toolMgr()->registerAction( myClippingAction, ClippingId );
+  // RNV: Temporary commented, this functionality will be moved into Geometry module
+  //toolMgr()->registerAction( myClippingAction, ClippingId );
 
   aAction = new QtxAction(tr("MNU_SHOOT_VIEW"), aResMgr->loadPixmap( "OCCViewer", tr( "ICON_OCCVIEWER_SHOOT_VIEW" ) ),
                            tr( "MNU_SHOOT_VIEW" ), 0, this);
@@ -1587,7 +1588,6 @@ void OCCViewer_ViewWindow::onClipping( bool on )
     {
       if ( myClippingDlg->isVisible() )
         myClippingDlg->hide();
-      aParent->setCuttingPlane(false);
     }
 }
 
@@ -1671,6 +1671,10 @@ void OCCViewer_ViewWindow::performRestoring( const viewAspect& anItem, bool base
   aView3d->SetEye( anItem.eyeX, anItem.eyeY, anItem.eyeZ );
   aView3d->SetProj( anItem.projX, anItem.projY, anItem.projZ );
   aView3d->SetAxialScale( anItem.scaleX, anItem.scaleY, anItem.scaleZ );
+  if ( myClippingDlg ) {
+    myClippingDlg->onApply();
+    myClippingDlg->isRestore = false;
+  }
 
   if ( !baseParamsOnly ) {
 
@@ -1957,15 +1961,15 @@ void OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x,  const doub
     gp_Pln pln (gp_Pnt(x, y, z), gp_Dir(dx, dy, dz));
     double a, b, c, d;
     pln.Coefficients(a, b, c, d);
-
+    
 #if OCC_VERSION_LARGE > 0x06060000 // Porting to OCCT higher 6.6.0 version
     Graphic3d_SetOfHClipPlane aPlanes = view->GetClipPlanes();
     Handle(Graphic3d_ClipPlane) aClipPlane;
     if(aPlanes.Size() > 0 ) {
       Graphic3d_SetOfHClipPlane::Iterator anIter (aPlanes);
-      anIter.Next();
       aClipPlane = anIter.Value();
       aClipPlane->SetEquation(pln);
+      aClipPlane->SetOn(Standard_True);
     } else {
       aClipPlane = new Graphic3d_ClipPlane(pln);
       view->AddClipPlane(aClipPlane);
@@ -1981,13 +1985,8 @@ void OCCViewer_ViewWindow::setCuttingPlane( bool on, const double x,  const doub
       view->SetPlaneOn(clipPlane);
     }
 #else
-    if (view->MoreActivePlanes())
-      clipPlane = view->ActivePlane();
-    else
-      clipPlane = new V3d_Plane (viewer);
-    
+    clipPlane = new V3d_Plane (viewer);
     clipPlane->SetPlane(a, b, c, d);
-    view->SetPlaneOn(clipPlane);
 #endif
   }
   else {
@@ -2023,7 +2022,17 @@ bool OCCViewer_ViewWindow::isCuttingPlane()
 {
   Handle(V3d_View) view = myViewPort->getView();
 #if OCC_VERSION_LARGE > 0x06060000 // Porting to OCCT higher 6.6.0 version
-  return (view->GetClipPlanes().Size());
+  bool res = false;
+  Graphic3d_SetOfHClipPlane aPlanes = view->GetClipPlanes();
+  Graphic3d_SetOfHClipPlane::Iterator anIter (aPlanes);
+  for( ;anIter.More();anIter.Next() ) {
+    Handle(Graphic3d_ClipPlane) aClipPlane = anIter.Value();
+    if(aClipPlane->IsOn()) {
+      res = true;
+      break;
+    }
+  }
+  return res;
 #else
   view->InitActivePlanes();
   return (view->MoreActivePlanes());
@@ -2127,7 +2136,6 @@ viewAspect OCCViewer_ViewWindow::getViewParams() const
   return params;
 }
 
-
 /*!
   \brief Get visual parameters of this view window.
   \return visual parameters of view window
@@ -2157,6 +2165,34 @@ QString OCCViewer_ViewWindow::getVisualParameters()
   data << QString( "isVisible=%1" ).arg( params.isVisible );
   data << QString( "size=%1" )     .arg( params.size,    0, 'f',  2 );
 
+  if ( myClippingDlg ) {
+    if ( !myClippingDlg->myClippingPlanes.empty() ) {
+      for ( int i=0; i < myClippingDlg->myClippingPlanes.size(); i++ ) {
+        QString ClippingPlane = QString( "ClippingPlane%1=").arg( i+1 );
+        Pnt_ClipPlane aPlane = myClippingDlg->myClippingPlanes[i];
+        ClippingPlane +=  QString( "Mode~%1;").arg( (int)aPlane->PlaneMode );
+        ClippingPlane +=  QString( "IsActive~%1;").arg( aPlane->IsActive );
+        if ( aPlane->PlaneMode == Absolute ) {
+          ClippingPlane += QString( "AbsoluteOrientation~%1;" ).arg( aPlane->Orientation );
+          ClippingPlane += QString( "IsInvert~%1;" ).arg( aPlane->IsInvert );
+          ClippingPlane +=  QString( "X~%1;" ).arg( aPlane->X );
+          ClippingPlane +=  QString( "Y~%1;" ).arg( aPlane->Y );
+          ClippingPlane +=  QString( "Z~%1;" ).arg( aPlane->Z );
+          ClippingPlane +=  QString( "Dx~%1;" ).arg( aPlane->Dx );
+          ClippingPlane +=  QString( "Dy~%1;" ).arg( aPlane->Dy );;
+          ClippingPlane +=  QString( "Dz~%1" ).arg( aPlane->Dz );
+        }
+        else if ( aPlane->PlaneMode == Relative ) {
+          ClippingPlane +=  QString( "RelativeOrientation~%1;" ).arg( aPlane->RelativeMode.Orientation );
+          ClippingPlane +=  QString( "Distance~%1;" ).arg( aPlane->RelativeMode.Distance );
+          ClippingPlane +=  QString( "Rotation1~%1;" ).arg( aPlane->RelativeMode.Rotation1 );
+          ClippingPlane +=  QString( "Rotation2~%1" ).arg( aPlane->RelativeMode.Rotation2 );
+        }
+        data << ClippingPlane;
+      }
+    }
+  }
+
 #if OCC_VERSION_LARGE > 0x06030009 // available only with OCC-6.3-sp10 or newer version
   // graduated trihedron
   data << QString( "gtIsVisible=%1" )      .arg( params.gtIsVisible );
@@ -2239,6 +2275,41 @@ void OCCViewer_ViewWindow::setVisualParameters( const QString& parameters )
       else if ( paramName == "scaleZ" )            params.scaleZ            = paramValue.toDouble();
       else if ( paramName == "isVisible" )         params.isVisible         = paramValue.toInt();
       else if ( paramName == "size" )              params.size              = paramValue.toDouble();
+      else if ( paramName.contains( "ClippingPlane" ) ) {
+        OCCViewer_ViewWindow* aParent = dynamic_cast<OCCViewer_ViewWindow*>(parent()->parent());
+        if (!aParent)
+          aParent = this;
+        if ( !myClippingDlg )
+        {
+          myClippingDlg = new OCCViewer_ClippingDlg( aParent );
+          myClippingDlg->SetAction( myClippingAction );
+          myClippingDlg->hide();
+        }
+       QStringList ClipPlaneData = paramValue.split( ';' );
+        ClipPlane* aPlane = new ClipPlane();
+       foreach( QString ClipPlaneParam, ClipPlaneData ) {
+          QString ClipPlane_paramName  = ClipPlaneParam.section( '~', 0, 0 ).trimmed();
+          QString ClipPlane_paramValue = ClipPlaneParam.section( '~', 1, 1 ).trimmed();
+          if      ( ClipPlane_paramName == "Mode" )                aPlane->PlaneMode                  = ( Mode )ClipPlane_paramValue.toInt();
+          else if ( ClipPlane_paramName == "IsActive" )            aPlane->IsActive                   = ClipPlane_paramValue.toInt();
+          else if ( ClipPlane_paramName == "AbsoluteOrientation" ) aPlane->Orientation                = ClipPlane_paramValue.toInt();
+          else if ( ClipPlane_paramName == "IsInvert" )            aPlane->IsInvert                   = ClipPlane_paramValue.toInt();
+          else if ( ClipPlane_paramName == "X" )                   aPlane->X                          = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Y" )                   aPlane->Y                          = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Z" )                   aPlane->Z                          = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Dx" )                  aPlane->Dx                         = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Dy" )                  aPlane->Dy                         = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Dz" )                  aPlane->Dz                         = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "RelativeOrientation" ) aPlane->RelativeMode.Orientation   = ClipPlane_paramValue.toInt();
+          else if ( ClipPlane_paramName == "Distance" )            aPlane->RelativeMode.Distance      = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Rotation1" )           aPlane->RelativeMode.Rotation1     = ClipPlane_paramValue.toDouble();
+          else if ( ClipPlane_paramName == "Rotation2" )           aPlane->RelativeMode.Rotation2     = ClipPlane_paramValue.toDouble();
+       }
+       myClippingDlg->myClippingPlanes.push_back( aPlane );
+       myClippingDlg->isRestore = true;
+       myClippingDlg->synchronize();
+       myClippingDlg->SetCurrentPlaneParam();
+      }
       // graduated trihedron
       else if ( paramName == "gtIsVisible" )       params.gtIsVisible       = paramValue.toInt();
       else if ( paramName == "gtDrawNameX" )       params.gtDrawNameX       = paramValue.toInt();
index d9d1f0d99104746f081fbe8267be045c9fb739f1..705f737b3a80274549e8a56174ce5861ccb48688 100644 (file)
     </message>
     <message>
         <source>MNU_MINIMIZE_VIEW</source>
-        <translation>Create sub-views</translation>
+        <translation>Minimize</translation>
     </message>
 </context>
 <context>
         <translation>Z:</translation>
     </message>
 </context>
+<context>
+    <name>OCCViewer_ClippingDlg</name>
+    <message>
+        <source>CLIPPING_PLANES</source>
+        <translation>Clipping planes</translation>
+    </message>
+    <message>
+        <source>NO_PLANES</source>
+        <translation>No planes</translation>
+    </message>
+    <message>
+        <source>IS_ACTIVE_PLANE</source>
+        <translation>Active</translation>
+    </message>
+    <message>
+        <source>BTN_NEW</source>
+        <translation>New</translation>
+    </message>  
+        <message>
+        <source>BTN_DELETE</source>
+        <translation>Delete</translation>
+    </message>   
+    <message>
+        <source>AUTO_APPLY</source>
+        <translation>Auto Apply</translation>
+    </message>
+    <message>
+        <source>MODE</source>
+        <translation>Mode</translation>
+    </message>
+    <message>
+        <source>ORIENTATION</source>
+        <translation>Orientation</translation>
+    </message>
+    <message>
+        <source>DISTANCE</source>
+        <translation>Distance</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_X_Y2Z</source>
+        <translation>Rotation around X (Y to Z):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Y_X2Z</source>
+        <translation>Rotation around Y (X to Z):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Z_Y2X</source>
+        <translation>Rotation around Z (Y to X):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_X_Z2Y</source>
+        <translation>Rotation around X (Z to Y):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Y_Z2X</source>
+        <translation>Rotation around Y (Z to X):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Z_X2Y</source>
+        <translation>Rotation around Z (X to Y):</translation>
+    </message>
+    <message>
+        <source>ALONG_XY</source>
+        <translation>|| X-Y</translation>
+    </message>
+    <message>
+        <source>ALONG_YZ</source>
+        <translation>|| Y-Z</translation>
+    </message>
+    <message>
+        <source>ALONG_ZX</source>
+        <translation>|| Z-X</translation>
+    </message>
+    <message>
+        <source>ABSOLUTE</source>
+        <translation>Absolute</translation>
+    </message>
+    <message>
+        <source>RELATIVE</source>
+        <translation>Relative</translation>
+    </message>
+    <message>
+        <source>BTN_DISABLE_ALL</source>
+        <translation>Disable all</translation>
+    </message>
+    <message>
+        <source>PREVIEW</source>
+        <translation>Preview</translation>
+    </message>
+    <message>
+        <source>RESET</source>
+        <translation>Reset</translation>
+    </message>
+    <message>
+        <source>INVERT</source>
+        <translation>Invert</translation>
+    </message>
+    <message>
+        <source>BASE_POINT</source>
+        <translation>Base point</translation>
+    </message>
+    <message>
+        <source>DIRECTION</source>
+        <translation>Direction</translation>
+    </message>
+    <message>
+        <source>PARAMETERS</source>
+        <translation>Parameters</translation>
+    </message>
+</context>
 </TS>
index 0f09189f07806a8537cd547327721859e8933ba3..250fda174ce514618a8716ba48d5d8975bdcef22 100755 (executable)
     </message>
     <message>
         <source>MNU_MINIMIZE_VIEW</source>
-        <translation>Créer les sous-vues</translation>
+        <translation>Minimiser</translation>
     </message>
 </context>
 <context>
         <translation>Z:</translation>
     </message>
 </context>
+<context>
+    <name>OCCViewer_ClippingDlg</name>
+    <message>
+        <source>CLIPPING_PLANES</source>
+        <translation>Les plans de coupe</translation>
+    </message>
+    <message>
+        <source>NO_PLANES</source>
+        <translation>Aucuns plans</translation>
+    </message>
+    <message>
+        <source>IS_ACTIVE_PLANE</source>
+        <translation>Active</translation>
+    </message>
+    <message>
+        <source>BTN_NEW</source>
+        <translation>Nouveau</translation>
+    </message>
+    <message>
+        <source>BTN_DELETE</source>
+        <translation>Supprimer</translation>
+    </message>
+    <message>
+        <source>AUTO_APPLY</source>
+        <translation>Appliquer automatiquement</translation>
+    </message>
+    <message>
+        <source>MODE</source>
+        <translation>Mode</translation>
+    </message>
+    <message>
+        <source>ORIENTATION</source>
+        <translation>Orientation</translation>
+    </message>
+    <message>
+        <source>DISTANCE</source>
+        <translation>Distance</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_X_Y2Z</source>
+        <translation>Rotation autour de X (Y à Z):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Y_X2Z</source>
+        <translation>Rotation autour de Y (X à Z):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Z_Y2X</source>
+        <translation>Rotation autour de Z (Y à X):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_X_Z2Y</source>
+        <translation>Rotation autour de X (Z à Y):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Y_Z2X</source>
+        <translation>Rotation autour de Y (Z à X):</translation>
+    </message>
+    <message>
+        <source>ROTATION_AROUND_Z_X2Y</source>
+        <translation>Rotation autour de Z (X à Y):</translation>
+    </message>
+    <message>
+        <source>ALONG_XY</source>
+        <translation>|| X-Y</translation>
+    </message>
+    <message>
+        <source>ALONG_YZ</source>
+        <translation>|| Y-Z</translation>
+    </message>
+    <message>
+        <source>ALONG_ZX</source>
+        <translation>|| Z-X</translation>
+    </message>
+    <message>
+        <source>ABSOLUTE</source>
+        <translation>Absolute</translation>
+    </message>
+    <message>
+        <source>RELATIVE</source>
+        <translation>Relative</translation>
+    </message>
+    <message>
+        <source>BTN_DISABLE_ALL</source>
+        <translation>Désactiver tous</translation>
+    </message>
+    <message>
+        <source>PREVIEW</source>
+        <translation>Prévisualiser</translation>
+    </message>
+    <message>
+        <source>RESET</source>
+        <translation>Réinitialiser</translation>
+    </message>
+    <message>
+        <source>INVERT</source>
+        <translation>Inverser</translation>
+    </message>
+    <message>
+        <source>BASE_POINT</source>
+        <translation>Le point fondamental</translation>
+    </message>
+    <message>
+        <source>DIRECTION</source>
+        <translation>Direction</translation>
+    </message>
+    <message>
+        <source>PARAMETERS</source>
+        <translation>Paramètres</translation>
+    </message>
+</context>
 </TS>
index 84899db0f9e649e0e36bb50124f2d1d2b3c4026a..dd91f9b929e6c16ce8d789719d6e5aa4a43edef1 100644 (file)
@@ -215,6 +215,10 @@ Do you want to reload it ?</translation>
         <source>BUT_CLOSE</source>
         <translation>&amp;Close</translation>
     </message>
+    <message>
+        <source>BUT_APPLY_AND_CLOSE</source>
+        <translation>A&amp;pply and Close</translation>
+    </message>
     <message>
         <source>INF_DESK_EXIT</source>
         <translation>Exit</translation>
index e8f4b4e7947870892ff8f86ca94425fe9d9ef42f..87c71765e33b467f4c8cd3c0c72b255ebb6e5b7d 100755 (executable)
@@ -215,6 +215,10 @@ Voulez-vous le réouvrir?</translation>
         <source>BUT_CLOSE</source>
         <translation>&amp;Fermer</translation>
     </message>
+    <message>
+        <source>BUT_APPLY_AND_CLOSE</source>
+        <translation>A&amp;ppliquer et Fermer</translation>
+    </message>
     <message>
         <source>INF_DESK_EXIT</source>
         <translation>&amp;Quitter</translation>
index 560cef7c3707cefdded8d63e2cffea2e85f18488..6301ece1d32fefcc99d673b3c30f78447905c695 100644 (file)
@@ -292,8 +292,20 @@ QVTK_RenderWindowInteractor
     GetDevice()->LeftButtonReleaseEvent();
   else if( event->button() & Qt::MidButton )
     GetDevice()->MiddleButtonReleaseEvent();
-  else if( event->button() & Qt::RightButton )
+  else if( event->button() & Qt::RightButton ) {
+    #ifndef Fix_Of_vtkImplicitPlaneWidget_bug
+    GetDevice()->SetEventInformationFlipY( -99999, -99999,
+                                           event->modifiers() & Qt::ControlModifier,
+                                           event->modifiers() & Qt::ShiftModifier);
+    GetDevice()->LeftButtonPressEvent();
+    GetDevice()->LeftButtonReleaseEvent();
+    GetDevice()->SetEventInformationFlipY(event->x(),
+                                          event->y(),
+                                          event->modifiers() & Qt::ControlModifier,
+                                          event->modifiers() & Qt::ShiftModifier);
+    #endif
     GetDevice()->RightButtonReleaseEvent();
+  }
 }