+/*!
+ Compute the point of bounding box and current clipping plane
+ */
+void ComputeBoundsParam( const double theBounds[6],
+ const double theDirection[3],
+ double theMinPnt[3],
+ double& theMaxBoundPrj,
+ double& theMinBoundPrj )
+{
+ 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;
+ aEnlargeBounds[i ] = theBounds[i ] - aDelta;
+ aEnlargeBounds[i+1] = theBounds[i+1] + aDelta;
+ }
+
+ 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]
+ + 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( 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;
+}
+
+/*!
+ Compute the parameters of clipping plane
+ */
+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( theIC, theDefaultSize, aBounds[0], aBounds[2], aBounds[4], aBounds[1], aBounds[3], aBounds[5] );
+
+ DistanceToPosition( aBounds, theNormal, theDist, theOrigin );
+ return true;
+}
+
+/*!
+ \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.
+ */
+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 )
+{
+ double aNormal[3] = { theDX, theDY, theDZ };
+ double anOrigin[3] = { 0.0, 0.0, 0.0 };
+
+ bool anIsOk = ComputeClippingPlaneParameters( theIC, theDefaultSize, aNormal, theDistance, anOrigin );
+
+ if( !anIsOk )
+ {
+ return false;
+ }
+
+ theX = anOrigin[0];
+ theY = anOrigin[1];
+ theZ = anOrigin[2];
+
+ return true;
+}
+
+/*!
+ \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 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( theX, theY, theZ );
+ gp_Dir aPlaneN( theDX, theDY, theDZ );
+
+ double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+
+ getMinMaxFromContext( theIC, theDefaultSize, aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ Bnd_Box aMinMax;
+ aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ gp_Trsf aRelativeTransform;
+ aRelativeTransform.SetTransformation( gp_Ax3(), gp_Ax3( aPlaneP, aPlaneN ) );
+ Bnd_Box aRelativeBounds = aMinMax.Transformed( aRelativeTransform );
+
+ aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ double aLength = aZmax - aZmin;
+ double aDistance = aZmax;
+
+ double aRelativeDistance = aLength > 0.01 ? aDistance / aLength : 0.0;
+ aRelativeDistance = qMin( aRelativeDistance, aLength );
+ aRelativeDistance = qMax( aRelativeDistance, 0.0 );
+ theDistance = aRelativeDistance;
+}
+
+/*!
+ Compute clipping plane size base point and normal
+ */
+
+void clipPlaneParams(OCCViewer_ClipPlane& theClipPlane, Handle(AIS_InteractiveContext) theContext,
+ double& theSize, gp_Pnt& theBasePnt, gp_Dir& theNormal, double defaultSize) {
+ double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
+ aXMin = aYMin = aZMin = DBL_MAX;
+ aXMax = aYMax = aZMax = -DBL_MAX;
+
+ getMinMaxFromContext(theContext,defaultSize,aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
+ double aSize = 50;
+
+ 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 );
+ 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 );
+
+ theSize = aSize;
+ theBasePnt = aBasePnt;
+ theNormal = aNormal;
+}
+
+
+/*********************************************************************************
+ ********************* class OCCViewer_ClippingDlg *********************
+ *********************************************************************************/