Salome HOME
updated copyright message
[modules/gui.git] / src / OCCViewer / OCCViewer_ClipPlane.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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 : Mode( Absolute ),
43   IsOn( true ),
44   X( 0.0 ),
45   Y( 0.0 ),
46   Z( 0.0 )
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         int anInvertCoeff = AbsoluteOrientation.IsInvert ? 1 : -1;
121         theDx = anInvertCoeff * AbsoluteOrientation.Dx;
122         theDy = anInvertCoeff * AbsoluteOrientation.Dy;
123         theDz = anInvertCoeff * AbsoluteOrientation.Dz;
124         break;
125     }
126
127     return;
128   }
129
130   // Relative definition of the clipping plane
131   RelativeToDXYZ( OrientationType,
132                   RelativeOrientation.Rotation1,
133                   RelativeOrientation.Rotation2,
134                   theDx, theDy, theDz );
135 }
136
137 /*!
138   Converts normal direction to relative definition.
139   @param theDx [in] the direction x component.
140   @param theDy [in] the direction y component.
141   @param theDz [in] the direction y component.
142   @param theRelativeType [in] the relative orientation type.
143   @param theRotation1 [out] the angle of rotation around first axis.
144   @param theRotation2 [out] the angle of rotation around second axis.
145 */
146 void OCCViewer_ClipPlane::DXYZToRelative( const double theDx,
147                                           const double theDy,
148                                           const double theDz,
149                                           const int theOrientationType,
150                                           double& theRotation1,
151                                           double& theRotation2 )
152 {
153   gp_Dir aPlaneN( theDx, theDy, theDz );
154
155   const gp_Dir& aDX = gp::DX();
156   const gp_Dir& aDY = gp::DY();
157   const gp_Dir& aDZ = gp::DZ();
158   double anAng1 = 0.0;
159   double anAng2 = 0.0;
160   switch ( theOrientationType )
161   {
162     case RelativeXY :
163     {
164       if ( aDY.IsParallel( aPlaneN, Precision::Angular() ) )
165       {
166         anAng1 = 0.0;
167         anAng2 = 0.0;
168         break;
169       }
170
171       if ( aDX.IsParallel( aPlaneN, Precision::Angular() ) )
172       {
173         anAng1 = 0.0;
174         anAng2 = 0.0;
175         break;
176       }
177
178       gp_Dir aDir1 = aPlaneN ^ aDX;
179       gp_Dir aDir2 = aDY ^ aPlaneN;
180       gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDY ^ aPlaneN );
181
182       if ( aDir1 * aRightHand.YDirection() < 0.0 )
183       {
184         aDir1.Reverse();
185       }
186       if ( aDir2 * aRightHand.XDirection() < 0.0 )
187       {
188         aDir2.Reverse();
189       }
190
191       anAng1 = aDY.AngleWithRef( aDir1,  aDX );
192       anAng2 = aDX.AngleWithRef( aDir2, -aDY );
193     }
194     break;
195
196     case RelativeYZ :
197     {
198       if ( aDZ.IsParallel( aPlaneN, Precision::Angular() ) )
199       {
200         anAng1 = 0.0;
201         anAng2 = 0.0;
202         break;
203       }
204
205       if ( aDY.IsParallel( aPlaneN, Precision::Angular() ) )
206       {
207         anAng1 = 0.0;
208         anAng2 = 0.0;
209         break;
210       }
211
212       gp_Dir aDir1 = aPlaneN ^ aDY;
213       gp_Dir aDir2 = aDZ ^ aPlaneN;
214       gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDZ ^ aPlaneN );
215
216       if ( aDir1 * aRightHand.YDirection() < 0.0 )
217       {
218         aDir1.Reverse();
219       }
220       if ( aDir2 * aRightHand.XDirection() < 0.0 )
221       {
222         aDir2.Reverse();
223       }
224
225       anAng1 = aDZ.AngleWithRef( aDir1,  aDY );
226       anAng2 = aDY.AngleWithRef( aDir2, -aDZ );
227     }
228     break;
229
230     case RelativeZX :
231     {
232       if ( aDX.IsParallel( aPlaneN, Precision::Angular() ) )
233       {
234         anAng1 = 0.0;
235         anAng2 = 0.0;
236         break;
237       }
238
239       if ( aDZ.IsParallel( aPlaneN, Precision::Angular() ) )
240       {
241         anAng1 = 0.0;
242         anAng2 = 0.0;
243         break;
244       }
245
246       gp_Dir aDir1 = aPlaneN ^ aDZ;
247       gp_Dir aDir2 = aDX ^ aPlaneN;
248       gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDX ^ aPlaneN );
249
250       if ( aDir1 * aRightHand.YDirection() < 0.0 )
251       {
252         aDir1.Reverse();
253       }
254       if ( aDir2 * aRightHand.XDirection() < 0.0 )
255       {
256         aDir2.Reverse();
257       }
258
259       anAng1 = aDX.AngleWithRef( aDir1,  aDZ );
260       anAng2 = aDZ.AngleWithRef( aDir2, -aDX );
261     }
262     break;
263   }
264
265   theRotation1 = anAng1 * ( 180.0 / M_PI );
266   theRotation2 = anAng2 * ( 180.0 / M_PI );
267 }
268
269 /*!
270   Converts normal direction to relative definition.
271   @param theDx [in] the direction x component.
272   @param theDy [in] the direction y component.
273   @param theDz [in] the direction y component.
274   @param theRelativeType [in] the relative orientation type.
275   @param theRotation1 [out] the angle of rotation around first axis.
276   @param theRotation2 [out] the angle of rotation around second axis.
277 */
278 void OCCViewer_ClipPlane::RelativeToDXYZ( const int theOrientationType,
279                                           const double theRotation1,
280                                           const double theRotation2,
281                                           double& theDx,
282                                           double& theDy,
283                                           double& theDz )
284 {
285   double aNormal[3];
286   double aDir[2][3] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } };
287
288   static double aCoeff = M_PI / 180.0;
289
290   double anU[2] = { cos( aCoeff * theRotation1 ), cos( aCoeff * theRotation2 ) };
291   double aV[2] = { sqrt( 1.0 - anU[0] * anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
292
293   aV[0] = theRotation1 > 0.0 ? aV[0] : -aV[0];
294   aV[1] = theRotation2 > 0.0 ? aV[1] : -aV[1];
295
296   switch ( theOrientationType )
297   {
298     case RelativeXY :
299       aDir[0][1] = anU[0];
300       aDir[0][2] =  aV[0];
301       aDir[1][0] = anU[1];
302       aDir[1][2] =  aV[1];
303       break;
304
305     case RelativeYZ :
306       aDir[0][2] = anU[0];
307       aDir[0][0] =  aV[0];
308       aDir[1][1] = anU[1];
309       aDir[1][0] =  aV[1];
310       break;
311
312     case RelativeZX :
313       aDir[0][0] = anU[0];
314       aDir[0][1] =  aV[0];
315       aDir[1][2] = anU[1];
316       aDir[1][1] =  aV[1];
317       break;
318   }
319
320   Cross( aDir[1], aDir[0], aNormal );
321
322   // Normalize
323   double aDen;
324   aDen = sqrt( aNormal[0] * aNormal[0] + aNormal[1] * aNormal[1] + aNormal[2] * aNormal[2] );
325   if ( aDen != 0.0 )
326   {
327     for (int i = 0; i < 3; i++)
328     {
329       aNormal[i] /= aDen;
330     }
331   }
332
333   theDx = aNormal[0];
334   theDy = aNormal[1];
335   theDz = aNormal[2];
336 }