+ gp_Dir aPlaneN( theDx, theDy, theDz );
+
+ 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 ( theOrientationType )
+ {
+ case RelativeXY :
+ {
+ 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 RelativeYZ :
+ {
+ 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 RelativeZX :
+ {
+ 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;
+ }
+
+ theRotation1 = anAng1 * ( 180.0 / M_PI );
+ theRotation2 = anAng2 * ( 180.0 / M_PI );
+}
+
+/*!
+ Converts normal direction to relative definition.
+ @param theDx [in] the direction x component.
+ @param theDy [in] the direction y component.
+ @param theDz [in] the direction y component.
+ @param theRelativeType [in] the relative orientation type.
+ @param theRotation1 [out] the angle of rotation around first axis.
+ @param theRotation2 [out] the angle of rotation around second axis.
+*/
+void OCCViewer_ClipPlane::RelativeToDXYZ( const int theOrientationType,
+ const double theRotation1,
+ const double theRotation2,
+ double& theDx,
+ double& theDy,
+ double& theDz )
+{
+ double aNormal[3];
+ double aDir[2][3] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } };
+
+ static double aCoeff = M_PI / 180.0;
+
+ double anU[2] = { cos( aCoeff * theRotation1 ), cos( aCoeff * theRotation2 ) };
+ double aV[2] = { sqrt( 1.0 - anU[0] * anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
+
+ aV[0] = theRotation1 > 0.0 ? aV[0] : -aV[0];
+ aV[1] = theRotation2 > 0.0 ? aV[1] : -aV[1];
+
+ switch ( theOrientationType )
+ {
+ case RelativeXY :
+ aDir[0][1] = anU[0];
+ aDir[0][2] = aV[0];
+ aDir[1][0] = anU[1];
+ aDir[1][2] = aV[1];
+ break;
+
+ case RelativeYZ :
+ aDir[0][2] = anU[0];
+ aDir[0][0] = aV[0];
+ aDir[1][1] = anU[1];
+ aDir[1][0] = aV[1];
+ break;
+
+ case RelativeZX :
+ 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 aDen;
+ aDen = sqrt( aNormal[0] * aNormal[0] + aNormal[1] * aNormal[1] + aNormal[2] * aNormal[2] );
+ if ( aDen != 0.0 )
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ aNormal[i] /= aDen;
+ }
+ }
+
+ theDx = aNormal[0];
+ theDy = aNormal[1];
+ theDz = aNormal[2];