Salome HOME
updated copyright message
[modules/gui.git] / src / OCCViewer / OCCViewer_ClippingDlg.cxx
index 593792d324abaa07653561da8a5affa1d52eae1a..de2c0916a1809204346b2ba689d100914789162b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include "OCCViewer_ClipPlaneInteractor.h"
 
 #include <V3d_View.hxx>
-#include <Visual3d_View.hxx>
 #include <Geom_Plane.hxx>
 #include <Prs3d_Presentation.hxx>
+#include <Prs3d_PlaneAspect.hxx>
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <AIS_ListOfInteractive.hxx>
 #include <AIS_InteractiveObject.hxx>
 #include <AIS_InteractiveContext.hxx>
+#include <Prs3d_Drawer.hxx>
 #include <IntAna_IntConicQuad.hxx>
 #include <gp_Lin.hxx>
 #include <gp_Pln.hxx>
@@ -92,7 +93,13 @@ void getMinMaxFromContext( Handle(AIS_InteractiveContext) ic,
       if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() ) {
         isFound = true;
         double xmin, ymin, zmin, xmax, ymax, zmax;
-        aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
+       Bnd_Box aBox = aPrs->MinMaxValues();
+       xmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X();
+       ymin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y();
+       zmin = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z();
+       xmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().X();
+       ymax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Y();
+       zmax = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Z();
         aXMin = qMin( aXMin, xmin );  aXMax = qMax( aXMax, xmax );
         aYMin = qMin( aYMin, ymin );  aYMax = qMax( aYMax, ymax );
         aZMin = qMin( aZMin, zmin );  aZMax = qMax( aZMax, zmax );
@@ -113,28 +120,31 @@ void getMinMaxFromContext( Handle(AIS_InteractiveContext) ic,
 /*!
   Compute the point of bounding box and current clipping plane
  */
-void ComputeBoundsParam( double theBounds[6],
-                         double theDirection[3],
+void ComputeBoundsParam( const double theBounds[6],
+                         const 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) {
+  double aEnlargeBounds[6];
+
+  // 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;
+    aEnlargeBounds[i  ] = theBounds[i  ] - aDelta;
+    aEnlargeBounds[i+1] = 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] } };
+  double aBoundPoints[8][3] = { { aEnlargeBounds[0], aEnlargeBounds[2], aEnlargeBounds[4] },
+                                { aEnlargeBounds[1], aEnlargeBounds[2], aEnlargeBounds[4] },
+                                { aEnlargeBounds[0], aEnlargeBounds[3], aEnlargeBounds[4] },
+                                { aEnlargeBounds[1], aEnlargeBounds[3], aEnlargeBounds[4] },
+                                { aEnlargeBounds[0], aEnlargeBounds[2], aEnlargeBounds[5] },
+                                { aEnlargeBounds[1], aEnlargeBounds[2], aEnlargeBounds[5] },
+                                { aEnlargeBounds[0], aEnlargeBounds[3], aEnlargeBounds[5] },
+                                { aEnlargeBounds[1], aEnlargeBounds[3], aEnlargeBounds[5] } };
 
   int aMaxId = 0;
   theMaxBoundPrj = theDirection[0] * aBoundPoints[aMaxId][0] + theDirection[1] * aBoundPoints[aMaxId][1]
@@ -160,122 +170,99 @@ void ComputeBoundsParam( double theBounds[6],
 /*!
   Compute the position of current plane by distance
  */
-void DistanceToPosition( double theBounds[6],
-                         double theDirection[3],
-                         double theDist,
+void DistanceToPosition( const double theBounds[6],
+                         const double theDirection[3],
+                         const 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;
+  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 theOrigin[3],
-                                     Handle(AIS_InteractiveContext) ic,
-                                    double theDefaultSize)
+bool ComputeClippingPlaneParameters( const Handle(AIS_InteractiveContext)& theIC,
+                                     const double theDefaultSize,
+                                     const double theNormal[3],
+                                     const double theDist,
+                                     double theOrigin[3] )
 {
   double aBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
-  getMinMaxFromContext(ic,theDefaultSize,aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5]);
+
+  getMinMaxFromContext( theIC, theDefaultSize, aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5] );
 
   DistanceToPosition( aBounds, theNormal, theDist, theOrigin );
   return true;
 }
 
 /*!
-  Cross product of two 3-vectors. Result vector in result[3].
+  \brief Converts relative plane parameters to absolute.
+  \param theIC [in] the interactive context.
+  \param theDefaultSize [in] the default trihedron size.
+  \param theDistance [in] the plane distance relative to minimum corner of model boundaries.
+  \param theDX [in] x component of plane direction.
+  \param theDY [in] y component of plane direction.
+  \param theDZ [in] z component of plane direction.
+  \param theX [out] x coordinate of plane origin.
+  \param theY [out] y coordinate of plane origin.
+  \param theZ [out] z coordinate of plane origin.
  */
-void Cross(const double first[3], const double second[3], double result[3])
+bool DistanceToXYZ ( const Handle(AIS_InteractiveContext)& theIC,
+                     const double theDefaultSize,
+                     const double theDistance,
+                     const double theDX,
+                     const double theDY,
+                     const double theDZ,
+                     double& theX,
+                     double& theY,
+                     double& theZ )
 {
-  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];
-}
+  double aNormal[3] = { theDX, theDY, theDZ };
+  double anOrigin[3] = { 0.0, 0.0, 0.0 };
 
-/*!
-  Compute relative clipping plane in absolute coordinates
- */
-void relativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) ic, double theDefaultSize )
-{
-  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;
-    }
+  bool anIsOk = ComputeClippingPlaneParameters( theIC, theDefaultSize, aNormal, theDistance, anOrigin );
 
-    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;
-      }
-    }
+  if( !anIsOk )
+  {
+    return false;
   }
 
-  double anOrigin[3];
+  theX = anOrigin[0];
+  theY = anOrigin[1];
+  theZ = anOrigin[2];
 
-  anOrigin[0] = anOrigin[1] = anOrigin[2] = 0;
-  bool anIsOk = true;
-
-  anIsOk = ComputeClippingPlaneParameters( aNormal,
-                                           thePlane.RelativeMode.Distance,
-                                           anOrigin,
-                                           ic,
-                                          theDefaultSize );
-  if( !anIsOk )
-         return;
-  thePlane.X = anOrigin[0];
-  thePlane.Y = anOrigin[1];
-  thePlane.Z = anOrigin[2];
-  thePlane.Dx = aNormal[0];
-  thePlane.Dy = aNormal[1];
-  thePlane.Dz = aNormal[2];
+  return true;
 }
 
 /*!
-  \brief Converts absolute plane definition to relative system.
-  \param thePlane [in/out] the plane to convert.
+  \brief Converts absolute position and direction to bounding box distance.
   \param theIC [in] the interactive context.
   \param theDefaultSize [in] the default trihedron size.
+  \param theX [in] x coordinate of plane origin.
+  \param theY [in] y coordinate of plane origin.
+  \param theZ [in] z coordinate of plane origin.
+  \param theDX [in] x component of plane direction.
+  \param theDY [in] y component of plane direction.
+  \param theDZ [in] z component of plane direction.
+  \param theDistance [out] the plane distance relative to minimum corner of model boundaries.
  */
-void absolutePlaneToRelative( OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) theIC, double theDefaultSize )
+void XYZToDistance ( const Handle(AIS_InteractiveContext)& theIC,
+                     const double theDefaultSize,
+                     const double theX,
+                     const double theY,
+                     const double theZ,
+                     const double theDX,
+                     const double theDY,
+                     const double theDZ,
+                     double& theDistance )
 {
-  gp_Pnt aPlaneP( thePlane.X, thePlane.Y, thePlane.Z );
-  gp_Dir aPlaneN( thePlane.Dx, thePlane.Dy, thePlane.Dz );
+  gp_Pnt aPlaneP( theX, theY, theZ );
+  gp_Dir aPlaneN( theDX, theDY, theDZ );
 
   double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
 
@@ -296,118 +283,7 @@ void absolutePlaneToRelative( OCCViewer_ClipPlane& thePlane, Handle(AIS_Interact
   double aRelativeDistance = aLength > 0.01 ? aDistance / aLength : 0.0;
   aRelativeDistance = qMin( aRelativeDistance, aLength );
   aRelativeDistance = qMax( aRelativeDistance, 0.0 );
-  thePlane.RelativeMode.Distance = aRelativeDistance;
-
-  const gp_Dir& aDX = gp::DX();
-  const gp_Dir& aDY = gp::DY();
-  const gp_Dir& aDZ = gp::DZ();
-  double anAng1 = 0.0;
-  double anAng2 = 0.0;
-  switch ( thePlane.RelativeMode.Orientation )
-  {
-    case 0:
-    {
-      if ( aDY.IsParallel( aPlaneN, Precision::Angular() ) )
-      {
-        anAng1 = 0.0;
-        anAng2 = 0.0;
-        break;
-      }
-
-      if ( aDX.IsParallel( aPlaneN, Precision::Angular() ) )
-      {
-        anAng1 = 0.0;
-        anAng2 = 0.0;
-        break;
-      }
-
-      gp_Dir aDir1 = aPlaneN ^ aDX;
-      gp_Dir aDir2 = aDY ^ aPlaneN;
-      gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDY ^ aPlaneN );
-
-      if ( aDir1 * aRightHand.YDirection() < 0.0 )
-      {
-        aDir1.Reverse();
-      }
-      if ( aDir2 * aRightHand.XDirection() < 0.0 )
-      {
-        aDir2.Reverse();
-      }
-
-      anAng1 = aDY.AngleWithRef( aDir1,  aDX );
-      anAng2 = aDX.AngleWithRef( aDir2, -aDY );
-      break;
-    }
-    case 1:
-    {
-      if ( aDZ.IsParallel( aPlaneN, Precision::Angular() ) )
-      {
-        anAng1 = 0.0;
-        anAng2 = 0.0;
-        break;
-      }
-
-      if ( aDY.IsParallel( aPlaneN, Precision::Angular() ) )
-      {
-        anAng1 = 0.0;
-        anAng2 = 0.0;
-        break;
-      }
-
-      gp_Dir aDir1 = aPlaneN ^ aDY;
-      gp_Dir aDir2 = aDZ ^ aPlaneN;
-      gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDZ ^ aPlaneN );
-
-      if ( aDir1 * aRightHand.YDirection() < 0.0 )
-      {
-        aDir1.Reverse();
-      }
-      if ( aDir2 * aRightHand.XDirection() < 0.0 )
-      {
-        aDir2.Reverse();
-      }
-
-      anAng1 = aDZ.AngleWithRef( aDir1,  aDY );
-      anAng2 = aDY.AngleWithRef( aDir2, -aDZ );
-      break;
-    }
-    case 2:
-    {
-      if ( aDX.IsParallel( aPlaneN, Precision::Angular() ) )
-      {
-        anAng1 = 0.0;
-        anAng2 = 0.0;
-        break;
-      }
-
-      if ( aDZ.IsParallel( aPlaneN, Precision::Angular() ) )
-      {
-        anAng1 = 0.0;
-        anAng2 = 0.0;
-        break;
-      }
-
-      gp_Dir aDir1 = aPlaneN ^ aDZ;
-      gp_Dir aDir2 = aDX ^ aPlaneN;
-      gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDX ^ aPlaneN );
-
-      if ( aDir1 * aRightHand.YDirection() < 0.0 )
-      {
-        aDir1.Reverse();
-      }
-      if ( aDir2 * aRightHand.XDirection() < 0.0 )
-      {
-        aDir2.Reverse();
-      }
-
-      anAng1 = aDX.AngleWithRef( aDir1,  aDZ );
-      anAng2 = aDZ.AngleWithRef( aDir2, -aDX );
-      break;
-    }
-  }
-
-  thePlane.RelativeMode.Rotation1 = anAng1 * ( 180.0 / M_PI );
-  thePlane.RelativeMode.Rotation2 = anAng2 * ( 180.0 / M_PI );
+  theDistance = aRelativeDistance;
 }
 
 /*!
@@ -423,9 +299,12 @@ void clipPlaneParams(OCCViewer_ClipPlane& theClipPlane, Handle(AIS_InteractiveCo
   getMinMaxFromContext(theContext,defaultSize,aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
   double aSize = 50;
 
-
-  gp_Pnt aBasePnt(theClipPlane.X ,  theClipPlane.Y ,  theClipPlane.Z);
-  gp_Dir aNormal(theClipPlane.Dx, theClipPlane.Dy, theClipPlane.Dz );
+  double aNormalX = 0.0;
+  double aNormalY = 0.0;
+  double aNormalZ = 0.0;
+  theClipPlane.OrientationToXYZ( aNormalX, aNormalY, aNormalZ );
+  gp_Pnt aBasePnt( theClipPlane.X, theClipPlane.Y, theClipPlane.Z );
+  gp_Dir aNormal( aNormalX, aNormalY, aNormalZ );
 
   // compute clipping plane size
   gp_Pnt aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
@@ -455,8 +334,7 @@ void clipPlaneParams(OCCViewer_ClipPlane& theClipPlane, Handle(AIS_InteractiveCo
   \param parent - parent widget
 */
 OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCViewer_Viewer* model)
-  : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
-    myCurrentClipPlaneMode (Absolute)
+  : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint )
 {
   setObjectName( "OCCViewer_ClippingDlg" );
   setModal( false );
@@ -636,7 +514,7 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
   QFont fnt = SpinSliderDistance->font(); fnt.setBold( true ); SpinSliderDistance->setFont( fnt );
   GroupParametersLayout->addWidget( SpinSliderDistance, 1, 1 );
 
-  QString aUnitRot = "\xB0";
+  QString aUnitRot = QString(QChar(0xB0));
 
   TextLabelRotation1 = new QLabel( tr("ROTATION_AROUND_X_Y2Z"), GroupParameters );
   TextLabelRotation1->setObjectName( "TextLabelRotation1" );
@@ -681,15 +559,15 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
   buttonOk = new QPushButton( GroupButtons );
   buttonOk->setObjectName( "buttonOk" );
   buttonOk->setText( tr( "BUT_APPLY_AND_CLOSE"  ) );
-  buttonOk->setAutoDefault( TRUE );
-  buttonOk->setDefault( TRUE );
+  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->setDefault( TRUE );
+  buttonApply->setAutoDefault( true );
+  buttonApply->setDefault( true );
   GroupButtonsLayout->addWidget( buttonApply );
 
   GroupButtonsLayout->addStretch();
@@ -697,11 +575,11 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
   buttonClose = new QPushButton( GroupButtons );
   buttonClose->setObjectName( "buttonClose" );
   buttonClose->setText( tr( "BUT_CLOSE"  ) );
-  buttonClose->setAutoDefault( TRUE );
+  buttonClose->setAutoDefault( true );
   GroupButtonsLayout->addWidget( buttonClose );
 
-  QPushButton* buttonHelp = new QPushButton( tr( "SMESH_BUT_HELP" ), GroupButtons );
-  buttonHelp->setAutoDefault( TRUE );
+  QPushButton* buttonHelp = new QPushButton( tr( "HELP" ), GroupButtons );
+  buttonHelp->setAutoDefault( true );
   GroupButtonsLayout->addWidget( buttonHelp );
 
   /***************************************************************/
@@ -758,8 +636,10 @@ OCCViewer_ClippingDlg::OCCViewer_ClippingDlg(OCCViewer_ViewWindow* parent , OCCV
 
   OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) myModel->getViewManager();
   myInteractor = new OCCViewer_ClipPlaneInteractor( aViewMgr, this );
-  connect( myInteractor, SIGNAL( planeClicked( const Handle_AIS_Plane& ) ), SLOT( onPlaneClicked( const Handle_AIS_Plane& ) ) );
-  connect( myInteractor, SIGNAL( planeDragged( const Handle_AIS_Plane& ) ), SLOT( onPlaneDragged( const Handle_AIS_Plane& ) ) );
+  connect( myInteractor, SIGNAL( planeClicked( const Handle_AIS_Plane& ) ),
+          SLOT( onPlaneClicked( const Handle_AIS_Plane& ) ) );
+  connect( myInteractor, SIGNAL( planeDragged( const Handle_AIS_Plane& ) ),
+          SLOT( onPlaneDragged( const Handle_AIS_Plane& ) ) );
 
   myLocalPlanes = myModel->getClipPlanes();
   synchronize();
@@ -827,6 +707,82 @@ void OCCViewer_ClippingDlg::initParam()
   SpinSliderRotation1->setValue( 0 );
   SpinSliderRotation2->setValue( 0 );
   CBRelativeOrientation->setCurrentIndex( 0 );
+
+  isActivePlane->setChecked( true );
+}
+
+/*!
+  Set plane parameters from widgets.
+*/
+void OCCViewer_ClippingDlg::setPlaneParam( OCCViewer_ClipPlane& thePlane )
+{
+  OCCViewer_ClipPlane::PlaneMode aMode = currentPlaneMode();
+
+  thePlane.Mode = aMode;
+
+  if ( aMode == OCCViewer_ClipPlane::Absolute )
+  {
+    if( qFuzzyIsNull( SpinBox_Dx->value() ) && 
+        qFuzzyIsNull( SpinBox_Dy->value() ) && 
+        qFuzzyIsNull( SpinBox_Dz->value() ) ) {
+      return;
+    }
+  }
+
+  thePlane.OrientationType = (aMode == OCCViewer_ClipPlane::Absolute)
+    ? CBAbsoluteOrientation->currentIndex()
+    : CBRelativeOrientation->currentIndex();
+
+  // Get XYZ, DXYZ
+  if ( aMode == OCCViewer_ClipPlane::Absolute )
+  {
+    if ( thePlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom )
+    {
+      thePlane.AbsoluteOrientation.Dx = SpinBox_Dx->value();
+      thePlane.AbsoluteOrientation.Dy = SpinBox_Dy->value();
+      thePlane.AbsoluteOrientation.Dz = SpinBox_Dz->value();
+      thePlane.AbsoluteOrientation.IsInvert = false;
+    }
+    else
+    {
+      thePlane.AbsoluteOrientation.IsInvert = SpinBox_Dx->value() < 0.0
+                                           || SpinBox_Dy->value() < 0.0
+                                           || SpinBox_Dz->value() < 0.0;
+    }
+
+    thePlane.X = SpinBox_X->value();
+    thePlane.Y = SpinBox_Y->value();
+    thePlane.Z = SpinBox_Z->value();
+  }
+  else
+  {
+    thePlane.RelativeOrientation.Rotation1 = SpinSliderRotation1->value();
+    thePlane.RelativeOrientation.Rotation2 = SpinSliderRotation2->value();
+
+    double aPlaneDx = 0.0;
+    double aPlaneDy = 0.0;
+    double aPlaneDz = 0.0;
+    double aX = 0.0;
+    double aY = 0.0;
+    double aZ = 0.0;
+
+    OCCViewer_ClipPlane::RelativeToDXYZ( thePlane.OrientationType,
+                                         thePlane.RelativeOrientation.Rotation1,
+                                         thePlane.RelativeOrientation.Rotation2,
+                                         aPlaneDx, aPlaneDy, aPlaneDz );
+
+    DistanceToXYZ( myModel->getAISContext(),
+                   myModel->trihedronSize(),
+                   SpinSliderDistance->value(),
+                   aPlaneDx, aPlaneDy, aPlaneDz,
+                   aX, aY, aZ );
+
+    thePlane.X = aX;
+    thePlane.Y = aY;
+    thePlane.Z = aZ;
+  }
+
+  thePlane.IsOn = isActivePlane->isChecked();
 }
 
 /*!
@@ -835,7 +791,7 @@ void OCCViewer_ClippingDlg::initParam()
 void OCCViewer_ClippingDlg::synchronize()
 {
   ComboBoxPlanes->clear();
-  int aNbPlanesAbsolute = myLocalPlanes.size();
+  int aNbPlanesAbsolute = (int)myLocalPlanes.size();
 
   QString aName;
   for(int i = 1; i<=aNbPlanesAbsolute; i++ ) {
@@ -854,7 +810,8 @@ void OCCViewer_ClippingDlg::synchronize()
     ComboBoxPlanes->addItem( tr( "NO_PLANES" ) );
     initParam();
   }
-  if ( myCurrentClipPlaneMode == Absolute ) {
+  if ( currentPlaneMode() == OCCViewer_ClipPlane::Absolute )
+  {
     SpinBox_X->setEnabled( anIsControlsEnable );
     SpinBox_Y->setEnabled( anIsControlsEnable );
     SpinBox_Z->setEnabled( anIsControlsEnable );
@@ -865,7 +822,8 @@ void OCCViewer_ClippingDlg::synchronize()
     invertButton->setEnabled( anIsControlsEnable );
     resetButton->setEnabled( anIsControlsEnable );
   }
-  else if( myCurrentClipPlaneMode == Relative ) {
+  else if ( currentPlaneMode() == OCCViewer_ClipPlane::Relative )
+  {
     CBRelativeOrientation->setEnabled( anIsControlsEnable );
     SpinSliderDistance->setEnabled( anIsControlsEnable );
     SpinSliderRotation1->setEnabled( anIsControlsEnable );
@@ -897,7 +855,9 @@ void OCCViewer_ClippingDlg::displayPreview()
       clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
       myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
       myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
-      myPreviewPlane->SetSize( aSize, aSize );
+      Handle(Prs3d_PlaneAspect) aPlaneAspect = new Prs3d_PlaneAspect();
+      aPlaneAspect->SetPlaneLength( aSize, aSize );
+      myPreviewPlane->Attributes()->SetPlaneAspect( aPlaneAspect );
       ic->SetWidth( myPreviewPlane, 10, false );
       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
       ic->SetTransparency( myPreviewPlane, 0.5, false );
@@ -945,7 +905,7 @@ void OCCViewer_ClippingDlg::updatePreview() {
     gp_Pnt aBasePnt;
     gp_Dir aNormal;
     clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
-    if(myPreviewPlaneVector.size() < clipPlanesCount()) {
+    if((int)myPreviewPlaneVector.size() < clipPlanesCount()) { //TODO: mismatch signed/unsigned
       myPreviewPlaneVector.resize(clipPlanesCount());
     }
     myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
@@ -953,7 +913,9 @@ void OCCViewer_ClippingDlg::updatePreview() {
       //Plane was not created
       myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
       myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
-      myPreviewPlane->SetSize( aSize, aSize );
+      Handle(Prs3d_PlaneAspect) aPlaneAspect = new Prs3d_PlaneAspect();
+      aPlaneAspect->SetPlaneLength( aSize, aSize );
+      myPreviewPlane->Attributes()->SetPlaneAspect( aPlaneAspect );
       ic->Display( myPreviewPlane, 1, 0, false );
       ic->SetWidth( myPreviewPlane, 10, false );
       ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
@@ -968,7 +930,7 @@ void OCCViewer_ClippingDlg::updatePreview() {
     ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false );
     ic->Update( myPreviewPlane, Standard_False );
   } else {
-    if(myPreviewPlaneVector.size() > aCurPlaneIndex ) {
+    if((int)myPreviewPlaneVector.size() > aCurPlaneIndex ) {
       myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
       if(ic->IsDisplayed(myPreviewPlane)) {
        ic->Erase( myPreviewPlane, false );
@@ -977,7 +939,7 @@ void OCCViewer_ClippingDlg::updatePreview() {
       myPreviewPlaneVector[aCurPlaneIndex].Nullify();
     }
   }
-  for(int i = 0; i < myPreviewPlaneVector.size(); i++) {
+  for(int i = 0; i < (int)myPreviewPlaneVector.size(); i++) {//TODO: mismatch signed/unsigned
     if( i == aCurPlaneIndex ) continue;
     if(!myPreviewPlaneVector[i].IsNull())
       ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
@@ -1007,7 +969,7 @@ void OCCViewer_ClippingDlg::erasePreview()
 
   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
 
-  for ( int i=0; i < myPreviewPlaneVector.size(); i++ ) {
+  for ( int i=0; i < (int)myPreviewPlaneVector.size(); i++ ) {//TODO: mismatch signed/unsigned
   Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[i];
     if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
       ic->Erase( myPreviewPlane, false );
@@ -1061,37 +1023,44 @@ void OCCViewer_ClippingDlg::updateControls()
 
   OCCViewer_ClipPlane& aPlane = getClipPlane( aPlaneIdx );
 
-  if ( aPlane.PlaneMode == Absolute )
+  double aPlaneDx  = 0.0;
+  double aPlaneDy  = 0.0;
+  double aPlaneDz  = 0.0;
+  double aDistance = 0.0;
+  aPlane.OrientationToXYZ( aPlaneDx, aPlaneDy, aPlaneDz );
+
+  if ( aPlane.Mode == OCCViewer_ClipPlane::Absolute )
   {
     ModeStackedLayout->setCurrentIndex( 0 );
-    myCurrentClipPlaneMode = Absolute;
-    int anOrientation = aPlane.Orientation;
+
     // Set plane parameters in the dialog
     SpinBox_X->setValue( aPlane.X );
     SpinBox_Y->setValue( aPlane.Y );
     SpinBox_Z->setValue( aPlane.Z );
-    SpinBox_Dx->setValue( aPlane.Dx );
-    SpinBox_Dy->setValue( aPlane.Dy );
-    SpinBox_Dz->setValue( aPlane.Dz );
-    CBAbsoluteOrientation->setCurrentIndex( anOrientation );
-    onOrientationAbsoluteChanged( anOrientation );
+    SpinBox_Dx->setValue( aPlaneDx );
+    SpinBox_Dy->setValue( aPlaneDy );
+    SpinBox_Dz->setValue( aPlaneDz );
+    CBAbsoluteOrientation->setCurrentIndex( aPlane.OrientationType );
+    onOrientationAbsoluteChanged( aPlane.OrientationType );
   }
-  else if( aPlane.PlaneMode == Relative )
+  else if( aPlane.Mode == OCCViewer_ClipPlane::Relative )
   {
     ModeStackedLayout->setCurrentIndex( 1 );
-    myCurrentClipPlaneMode = Relative;
-    int anOrientation = aPlane.RelativeMode.Orientation;
 
     // Set plane parameters in the dialog
-    double aFmtDistance  = double(aPlane.RelativeMode.Distance);
-    int aFmtRotation1 = int(aPlane.RelativeMode.Rotation1);
-    int aFmtRotation2 = int(aPlane.RelativeMode.Rotation2);
-
-    SpinSliderDistance->setValue( aFmtDistance );
-    SpinSliderRotation1->setValue( aFmtRotation1 );
-    SpinSliderRotation2->setValue( aFmtRotation2 );
-    CBRelativeOrientation->setCurrentIndex( anOrientation );
-    onOrientationRelativeChanged( anOrientation );
+    SpinSliderRotation1->setValue( int( aPlane.RelativeOrientation.Rotation1 ) );
+    SpinSliderRotation2->setValue( int( aPlane.RelativeOrientation.Rotation2 ) );
+
+    XYZToDistance( myModel->getAISContext(),
+                   myModel->trihedronSize(),
+                   aPlane.X, aPlane.Y, aPlane.Z,
+                   aPlaneDx, aPlaneDy, aPlaneDz,
+                   aDistance );
+
+    SpinSliderDistance->setValue( aDistance );
+
+    CBRelativeOrientation->setCurrentIndex( aPlane.OrientationType );
+    onOrientationRelativeChanged( aPlane.OrientationType );
   }
 
   isActivePlane->setChecked( aPlane.IsOn );
@@ -1102,9 +1071,18 @@ void OCCViewer_ClippingDlg::updateControls()
 */
 void OCCViewer_ClippingDlg::ClickOnNew()
 {
-  OCCViewer_ClipPlane aPlane;
-  aPlane.PlaneMode = (ClipPlaneMode )myCurrentClipPlaneMode;
-  myLocalPlanes.push_back(aPlane);
+  OCCViewer_ClipPlane aClipPlane;
+
+  // init controls state
+  myIsUpdatingControls = true;
+  initParam();
+  myIsUpdatingControls = false;
+
+  // init plane according to the state of controls
+  setPlaneParam( aClipPlane );
+
+  // add plane
+  myLocalPlanes.push_back( aClipPlane );
   synchronize();
 }
 
@@ -1121,7 +1099,7 @@ void OCCViewer_ClippingDlg::ClickOnDelete()
 
   Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
 
-  if(aPlaneIndex+1 <= myPreviewPlaneVector.size()) {
+  if(aPlaneIndex+1 <= (int)myPreviewPlaneVector.size()) {
     Handle(AIS_Plane) myPreviewPlane = myPreviewPlaneVector[aPlaneIndex];
     if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) ) {
       ic->Erase( myPreviewPlane, false );
@@ -1191,7 +1169,7 @@ void OCCViewer_ClippingDlg::ClickOnHelp()
 {
   SUIT_Application* app = SUIT_Session::session()->activeApplication();
   if ( app )
-    app->onHelpContextModule( "GUI", "occ_3d_viewer_page.html", "clipping_planes" );
+    app->onHelpContextModule( "GUI", "occ_3d_viewer.html", "clipping-planes" );
 }
 
 /*!
@@ -1201,7 +1179,6 @@ void OCCViewer_ClippingDlg::onModeAbsolute()
 {
   myIsPlaneCreation = true;
   ModeStackedLayout->setCurrentIndex(0);
-  myCurrentClipPlaneMode = Absolute;
   ClickOnNew();
   myIsPlaneCreation = false;
   updateClipping();
@@ -1214,7 +1191,6 @@ void OCCViewer_ClippingDlg::onModeRelative()
 {
   myIsPlaneCreation = true;
   ModeStackedLayout->setCurrentIndex(1);
-  myCurrentClipPlaneMode = Relative;
   ClickOnNew();
   myIsPlaneCreation = false;
   SetCurrentPlaneParam();
@@ -1251,7 +1227,7 @@ void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
     return;
   }
 
-  OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex );
+  //OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex ); // unused
 
   myIsSelectPlane = true;
   updateControls();
@@ -1264,38 +1240,16 @@ void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
 */
 void OCCViewer_ClippingDlg::SetCurrentPlaneParam()
 {
-  if ( clipPlanesCount() == 0 || myIsSelectPlane || myBusy)
+  if ( clipPlanesCount() == 0 || myIsSelectPlane || myBusy )
+  {
     return;
+  }
 
   int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
 
   OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
 
-  if ( aPlane.PlaneMode == Absolute )
-  {
-    if( qFuzzyIsNull( SpinBox_Dx->value() ) && 
-        qFuzzyIsNull( SpinBox_Dy->value() ) && 
-        qFuzzyIsNull( SpinBox_Dz->value() ) ) {
-      return;
-    }
-    aPlane.Orientation = CBAbsoluteOrientation->currentIndex();
-    aPlane.X  = SpinBox_X->value();
-    aPlane.Y  = SpinBox_Y->value();
-    aPlane.Z  = SpinBox_Z->value();
-    aPlane.Dx = SpinBox_Dx->value();
-    aPlane.Dy = SpinBox_Dy->value();
-    aPlane.Dz = SpinBox_Dz->value();
-    absolutePlaneToRelative( aPlane, myModel->getAISContext(),myModel->trihedronSize() );
-  }
-  else if( aPlane.PlaneMode == Relative )
-  {
-    aPlane.RelativeMode.Orientation = CBRelativeOrientation->currentIndex();
-    aPlane.RelativeMode.Distance = SpinSliderDistance->value();
-    aPlane.RelativeMode.Rotation1 = SpinSliderRotation1->value();
-    aPlane.RelativeMode.Rotation2 = SpinSliderRotation2->value();
-    relativePlaneToAbsolute( aPlane, myModel->getAISContext(),myModel->trihedronSize() );
-  }
-  aPlane.IsOn  = isActivePlane->isChecked();
+  setPlaneParam( aPlane );
 }
 
 /*!
@@ -1309,6 +1263,7 @@ void OCCViewer_ClippingDlg::onReset()
   SpinBox_Z->setValue(0);
   myBusy = false;
 
+  SetCurrentPlaneParam();
   updateClipping();
 }
 
@@ -1327,10 +1282,11 @@ void OCCViewer_ClippingDlg::onInvert()
   SpinBox_Dz->setValue( -Dz );
   myBusy = false;
 
-  if ( clipPlanesCount() != 0 ) {
+  if ( clipPlanesCount() != 0 )
+  {
     int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
     OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
-    aPlane.IsInvert = !aPlane.IsInvert;
+    aPlane.AbsoluteOrientation.IsInvert = !aPlane.AbsoluteOrientation.IsInvert;
   }
   updateClipping();
 }
@@ -1358,44 +1314,50 @@ void OCCViewer_ClippingDlg::onOrientationAbsoluteChanged( int mode )
   SpinBox_Dy->setEnabled( isUserMode );
   SpinBox_Dz->setEnabled( isUserMode );
 
-  if ( !isUserMode ) {
-
-    double aDx = 0, aDy = 0, aDz = 0;
+  int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
+  OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
+  double aDx = 0, aDy = 0, aDz = 0;
 
-    if ( mode == 1 )
-      {
-       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();
-      }
-    else if ( mode == 3 )
-      {
-       aDy = 1;
-       TextLabelY->setEnabled( true );
-       SpinBox_Y->setEnabled( true );
-       SpinBox_Y->setFocus();
-      }
-    
-    int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
-    OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
-    if ( aPlane.IsInvert == true ) {
-      aDx = -aDx; aDy = -aDy; aDz = -aDz;
-    }
+  if ( mode == 0 )
+  {
+    aDx = aPlane.AbsoluteOrientation.Dx;
+    aDy = aPlane.AbsoluteOrientation.Dy;
+    aDz = aPlane.AbsoluteOrientation.Dz;
+  }
+  else if ( mode == 1 )
+  {
+    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();
+  }
+  else if ( mode == 3 )
+  {
+    aDy = 1;
+    TextLabelY->setEnabled( true );
+    SpinBox_Y->setEnabled( true );
+    SpinBox_Y->setFocus();
+  }
     
-    myBusy = true;
-    SpinBox_Dx->setValue( aDx );
-    SpinBox_Dy->setValue( aDy );
-    SpinBox_Dz->setValue( aDz );
-    myBusy = false;
+  if ( aPlane.AbsoluteOrientation.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 ( !myIsUpdatingControls )
   {
@@ -1479,9 +1441,9 @@ void OCCViewer_ClippingDlg::onApply()
 /*!
   SLOT: Called when clip plane is clicked in viewer.
 */
-void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane )
+void OCCViewer_ClippingDlg::onPlaneClicked( const Handle_AIS_Plane& thePlane )
 {
-  for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
+  for ( int aPlaneIt = 0; aPlaneIt < (int)myPreviewPlaneVector.size(); aPlaneIt++ )
   {
     Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
     if ( aPlane != thePlane )
@@ -1498,9 +1460,9 @@ void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane )
 /*!
   SLOT: Called when clip plane is changed by dragging in viewer.
 */
-void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane )
+void OCCViewer_ClippingDlg::onPlaneDragged( const Handle_AIS_Plane& thePlane )
 {
-  for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
+  for ( int aPlaneIt = 0; aPlaneIt < (int)myPreviewPlaneVector.size(); aPlaneIt++ )
   {
     Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
     if ( aPlane != thePlane )
@@ -1517,10 +1479,24 @@ void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane )
     aClipPlane.X  = aPlaneP.X();
     aClipPlane.Y  = aPlaneP.Y();
     aClipPlane.Z  = aPlaneP.Z();
-    aClipPlane.Dx = aPlaneN.X();
-    aClipPlane.Dy = aPlaneN.Y();
-    aClipPlane.Dz = aPlaneN.Z();
-    absolutePlaneToRelative( aClipPlane, myModel->getAISContext(), myModel->trihedronSize() );
+
+    if ( aClipPlane.Mode == OCCViewer_ClipPlane::Absolute )
+    {
+      if ( aClipPlane.OrientationType == OCCViewer_ClipPlane::AbsoluteCustom )
+      {
+        int anInvertCoeff = aClipPlane.AbsoluteOrientation.IsInvert ? 1 : -1;
+        aClipPlane.AbsoluteOrientation.Dx = anInvertCoeff * aPlaneN.X();
+        aClipPlane.AbsoluteOrientation.Dy = anInvertCoeff * aPlaneN.Y();
+        aClipPlane.AbsoluteOrientation.Dz = anInvertCoeff * aPlaneN.Z();
+      }
+    }
+    else
+    {
+      OCCViewer_ClipPlane::DXYZToRelative( aPlaneN.X(), aPlaneN.Y(), aPlaneN.Z(),
+                                           aClipPlane.OrientationType,
+                                           aClipPlane.RelativeOrientation.Rotation1,
+                                           aClipPlane.RelativeOrientation.Rotation2 );
+    }
 
     myIsUpdatingControls = true;
     updateControls();
@@ -1544,3 +1520,10 @@ int OCCViewer_ClippingDlg::clipPlanesCount()
 {
   return myLocalPlanes.size();
 }
+
+OCCViewer_ClipPlane::PlaneMode OCCViewer_ClippingDlg::currentPlaneMode() const
+{
+  return ModeStackedLayout->currentIndex() == 0
+    ? OCCViewer_ClipPlane::Absolute 
+    : OCCViewer_ClipPlane::Relative;
+}