Salome HOME
Merge branch V7_3_1_BR
[modules/gui.git] / src / OCCViewer / OCCViewer_ClipPlane.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "OCCViewer_ClipPlane.h"
24 #include <gp_Dir.hxx>
25 #include <gp_Ax3.hxx>
26 #include <Precision.hxx>
27
28 namespace
29 {
30   /*!
31     Cross product of two 3-vectors. Result vector in result[3].
32    */
33   void Cross(const double first[3], const double second[3], double result[3])
34   {
35     result[0] = first[1]*second[2] - first[2]*second[1];
36     result[1] = first[2]*second[0] - first[0]*second[2];
37     result[2] = first[0]*second[1] - first[1]*second[0];
38   }
39 };
40
41 OCCViewer_ClipPlane::OCCViewer_ClipPlane()
42 : X( 0.0 ),
43   Y( 0.0 ),
44   Z( 0.0 ),
45   Mode( Absolute ),
46   IsOn( true )
47 {
48   OrientationType = AbsoluteCustom;
49   AbsoluteOrientation.Dx = 0.0;
50   AbsoluteOrientation.Dy = 0.0;
51   AbsoluteOrientation.Dz = 1.0;
52   AbsoluteOrientation.IsInvert = false;
53 }
54
55 /*!
56   Operator of another OCCViewer_ClipPlane assignment.
57   @param   theOther the OCCViewer_ClipPlane to assign.
58   @return  the assigned OCCViewer_ClipPlane.
59 */
60 OCCViewer_ClipPlane& OCCViewer_ClipPlane::operator = ( const OCCViewer_ClipPlane& theOther )
61 {
62   X = theOther.X;
63   Y = theOther.Y;
64   Z = theOther.Z;
65   IsOn = theOther.IsOn;
66   Mode = theOther.Mode;
67
68   OrientationType = theOther.OrientationType;
69
70   switch ( Mode )
71   {
72     case Absolute :
73       AbsoluteOrientation.IsInvert = theOther.AbsoluteOrientation.IsInvert;
74       AbsoluteOrientation.Dx       = theOther.AbsoluteOrientation.Dx;
75       AbsoluteOrientation.Dy       = theOther.AbsoluteOrientation.Dy;
76       AbsoluteOrientation.Dz       = theOther.AbsoluteOrientation.Dz;
77       break;
78
79     case Relative :
80       RelativeOrientation.Rotation1 = theOther.RelativeOrientation.Rotation1;
81       RelativeOrientation.Rotation2 = theOther.RelativeOrientation.Rotation2;
82       break;
83   }
84
85   return *this;
86 }
87
88 /*!
89   Converts defined orientation to direction.
90   @param theDx [out] the direction x component.
91   @param theDy [out] the direction y component.
92   @param theDz [out] the direction y component.
93 */
94 void OCCViewer_ClipPlane::OrientationToXYZ( double &theDx, double &theDy, double &theDz ) const
95 {
96   // Absolute definition of the clipping plane
97   if ( Mode == Absolute )
98   {
99     switch ( OrientationType )
100     {
101       case AbsoluteXY :
102         theDx = 0.0;
103         theDy = 0.0;
104         theDz = AbsoluteOrientation.IsInvert ? 1.0 : -1.0;
105         break;
106
107       case AbsoluteYZ :
108         theDx = AbsoluteOrientation.IsInvert ? 1.0 : -1.0;
109         theDy = 0.0;
110         theDz = 0.0;
111         break;
112
113       case AbsoluteZX :
114         theDx = 0.0;
115         theDy = AbsoluteOrientation.IsInvert ? 1.0 : -1.0;
116         theDz = 0.0;
117         break;
118
119       case AbsoluteCustom :
120         theDx = AbsoluteOrientation.Dx;
121         theDy = AbsoluteOrientation.Dy;
122         theDz = AbsoluteOrientation.Dz;
123         break;
124     }
125
126     return;
127   }
128
129   // Relative definition of the clipping plane
130   RelativeToDXYZ( OrientationType,
131                   RelativeOrientation.Rotation1,
132                   RelativeOrientation.Rotation2,
133                   theDx, theDy, theDz );
134 }
135
136 /*!
137   Converts normal direction to relative definition.
138   @param theDx [in] the direction x component.
139   @param theDy [in] the direction y component.
140   @param theDz [in] the direction y component.
141   @param theRelativeType [in] the relative orientation type.
142   @param theRotation1 [out] the angle of rotation around first axis.
143   @param theRotation2 [out] the angle of rotation around second axis.
144 */
145 void OCCViewer_ClipPlane::DXYZToRelative( const double theDx,
146                                           const double theDy,
147                                           const double theDz,
148                                           const int theOrientationType,
149                                           double& theRotation1,
150                                           double& theRotation2 )
151 {
152   gp_Dir aPlaneN( theDx, theDy, theDz );
153
154   const gp_Dir& aDX = gp::DX();
155   const gp_Dir& aDY = gp::DY();
156   const gp_Dir& aDZ = gp::DZ();
157   double anAng1 = 0.0;
158   double anAng2 = 0.0;
159   switch ( theOrientationType )
160   {
161     case RelativeXY :
162     {
163       if ( aDY.IsParallel( aPlaneN, Precision::Angular() ) )
164       {
165         anAng1 = 0.0;
166         anAng2 = 0.0;
167         break;
168       }
169
170       if ( aDX.IsParallel( aPlaneN, Precision::Angular() ) )
171       {
172         anAng1 = 0.0;
173         anAng2 = 0.0;
174         break;
175       }
176
177       gp_Dir aDir1 = aPlaneN ^ aDX;
178       gp_Dir aDir2 = aDY ^ aPlaneN;
179       gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDY ^ aPlaneN );
180
181       if ( aDir1 * aRightHand.YDirection() < 0.0 )
182       {
183         aDir1.Reverse();
184       }
185       if ( aDir2 * aRightHand.XDirection() < 0.0 )
186       {
187         aDir2.Reverse();
188       }
189
190       anAng1 = aDY.AngleWithRef( aDir1,  aDX );
191       anAng2 = aDX.AngleWithRef( aDir2, -aDY );
192     }
193     break;
194
195     case RelativeYZ :
196     {
197       if ( aDZ.IsParallel( aPlaneN, Precision::Angular() ) )
198       {
199         anAng1 = 0.0;
200         anAng2 = 0.0;
201         break;
202       }
203
204       if ( aDY.IsParallel( aPlaneN, Precision::Angular() ) )
205       {
206         anAng1 = 0.0;
207         anAng2 = 0.0;
208         break;
209       }
210
211       gp_Dir aDir1 = aPlaneN ^ aDY;
212       gp_Dir aDir2 = aDZ ^ aPlaneN;
213       gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDZ ^ aPlaneN );
214
215       if ( aDir1 * aRightHand.YDirection() < 0.0 )
216       {
217         aDir1.Reverse();
218       }
219       if ( aDir2 * aRightHand.XDirection() < 0.0 )
220       {
221         aDir2.Reverse();
222       }
223
224       anAng1 = aDZ.AngleWithRef( aDir1,  aDY );
225       anAng2 = aDY.AngleWithRef( aDir2, -aDZ );
226     }
227     break;
228
229     case RelativeZX :
230     {
231       if ( aDX.IsParallel( aPlaneN, Precision::Angular() ) )
232       {
233         anAng1 = 0.0;
234         anAng2 = 0.0;
235         break;
236       }
237
238       if ( aDZ.IsParallel( aPlaneN, Precision::Angular() ) )
239       {
240         anAng1 = 0.0;
241         anAng2 = 0.0;
242         break;
243       }
244
245       gp_Dir aDir1 = aPlaneN ^ aDZ;
246       gp_Dir aDir2 = aDX ^ aPlaneN;
247       gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDX ^ aPlaneN );
248
249       if ( aDir1 * aRightHand.YDirection() < 0.0 )
250       {
251         aDir1.Reverse();
252       }
253       if ( aDir2 * aRightHand.XDirection() < 0.0 )
254       {
255         aDir2.Reverse();
256       }
257
258       anAng1 = aDX.AngleWithRef( aDir1,  aDZ );
259       anAng2 = aDZ.AngleWithRef( aDir2, -aDX );
260     }
261     break;
262   }
263
264   theRotation1 = anAng1 * ( 180.0 / M_PI );
265   theRotation2 = anAng2 * ( 180.0 / M_PI );
266 }
267
268 /*!
269   Converts normal direction to relative definition.
270   @param theDx [in] the direction x component.
271   @param theDy [in] the direction y component.
272   @param theDz [in] the direction y component.
273   @param theRelativeType [in] the relative orientation type.
274   @param theRotation1 [out] the angle of rotation around first axis.
275   @param theRotation2 [out] the angle of rotation around second axis.
276 */
277 void OCCViewer_ClipPlane::RelativeToDXYZ( const int theOrientationType,
278                                           const double theRotation1,
279                                           const double theRotation2,
280                                           double& theDx,
281                                           double& theDy,
282                                           double& theDz )
283 {
284   double aNormal[3];
285   double aDir[2][3] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } };
286
287   static double aCoeff = M_PI / 180.0;
288
289   double anU[2] = { cos( aCoeff * theRotation1 ), cos( aCoeff * theRotation2 ) };
290   double aV[2] = { sqrt( 1.0 - anU[0] * anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
291
292   aV[0] = theRotation1 > 0.0 ? aV[0] : -aV[0];
293   aV[1] = theRotation2 > 0.0 ? aV[1] : -aV[1];
294
295   switch ( theOrientationType )
296   {
297     case RelativeXY :
298       aDir[0][1] = anU[0];
299       aDir[0][2] =  aV[0];
300       aDir[1][0] = anU[1];
301       aDir[1][2] =  aV[1];
302       break;
303
304     case RelativeYZ :
305       aDir[0][2] = anU[0];
306       aDir[0][0] =  aV[0];
307       aDir[1][1] = anU[1];
308       aDir[1][0] =  aV[1];
309       break;
310
311     case RelativeZX :
312       aDir[0][0] = anU[0];
313       aDir[0][1] =  aV[0];
314       aDir[1][2] = anU[1];
315       aDir[1][1] =  aV[1];
316       break;
317   }
318
319   Cross( aDir[1], aDir[0], aNormal );
320
321   // Normalize
322   double aDen;
323   aDen = sqrt( aNormal[0] * aNormal[0] + aNormal[1] * aNormal[1] + aNormal[2] * aNormal[2] );
324   if ( aDen != 0.0 )
325   {
326     for (int i = 0; i < 3; i++)
327     {
328       aNormal[i] /= aDen;
329     }
330   }
331
332   theDx = aNormal[0];
333   theDy = aNormal[1];
334   theDz = aNormal[2];
335 }