3dfb999b2d5be67e42d51b6edc406082f9f93efd
[occt.git] / src / gp / gp_Dir.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 // JCV 07/12/90 Modifs suite a l'introduction des classes XYZ et Mat dans gp
16
17 #include <gp_Ax1.hxx>
18 #include <gp_Ax2.hxx>
19 #include <gp_Dir.hxx>
20 #include <gp_Trsf.hxx>
21 #include <gp_Vec.hxx>
22 #include <gp_XYZ.hxx>
23 #include <Standard_ConstructionError.hxx>
24 #include <Standard_DomainError.hxx>
25 #include <Standard_Dump.hxx>
26 #include <Standard_OutOfRange.hxx>
27
28 Standard_Real gp_Dir::Angle (const gp_Dir& Other) const
29 {
30   //    Commentaires :
31   //    Au dessus de 45 degres l'arccos donne la meilleur precision pour le
32   //    calcul de l'angle. Sinon il vaut mieux utiliser l'arcsin.
33   //    Les erreurs commises sont loin d'etre negligeables lorsque l'on est
34   //    proche de zero ou de 90 degres.
35   //    En 3d les valeurs angulaires sont toujours positives et comprises entre
36   //    0 et PI
37   Standard_Real Cosinus = coord.Dot (Other.coord);
38   if (Cosinus > -0.70710678118655 && Cosinus < 0.70710678118655)
39     return acos (Cosinus);
40   else {
41     Standard_Real Sinus = (coord.Crossed (Other.coord)).Modulus ();
42     if(Cosinus < 0.0)  return M_PI - asin (Sinus);
43     else               return      asin (Sinus);
44   }
45 }
46
47 Standard_Real gp_Dir::AngleWithRef (const gp_Dir& Other,
48                                     const gp_Dir& Vref) const
49 {
50   Standard_Real Ang;
51   gp_XYZ XYZ = coord.Crossed (Other.coord);
52   Standard_Real Cosinus = coord.Dot(Other.coord);
53   Standard_Real Sinus   = XYZ.Modulus ();
54   if (Cosinus > -0.70710678118655 && Cosinus < 0.70710678118655)
55     Ang =  acos (Cosinus);
56   else {
57     if(Cosinus < 0.0)  Ang = M_PI - asin (Sinus);
58     else               Ang =      asin (Sinus);
59   }
60   if (XYZ.Dot (Vref.coord) >= 0.0)  return  Ang;
61   else                              return -Ang;
62
63
64 void gp_Dir::Mirror (const gp_Dir& V)
65 {
66   const gp_XYZ& XYZ = V.coord;
67   Standard_Real A = XYZ.X();
68   Standard_Real B = XYZ.Y();
69   Standard_Real C = XYZ.Z();
70   Standard_Real X = coord.X();
71   Standard_Real Y = coord.Y();
72   Standard_Real Z = coord.Z();
73   Standard_Real M1 = 2.0 * A * B;
74   Standard_Real M2 = 2.0 * A * C;
75   Standard_Real M3 = 2.0 * B * C;
76   Standard_Real XX = ((2.0 * A * A) - 1.0) * X + M1 * Y + M2 * Z;
77   Standard_Real YY = M1 * X + ((2.0 * B * B) - 1.0) * Y + M3 * Z;
78   Standard_Real ZZ = M2 * X + M3 * Y + ((2.0 * C * C) - 1.0) * Z;
79   coord.SetCoord(XX,YY,ZZ);
80 }
81
82 void gp_Dir::Mirror (const gp_Ax1& A1)
83 {
84   const gp_XYZ& XYZ = A1.Direction().coord;
85   Standard_Real A = XYZ.X();
86   Standard_Real B = XYZ.Y();
87   Standard_Real C = XYZ.Y();
88   Standard_Real X = coord.X();
89   Standard_Real Y = coord.Y();
90   Standard_Real Z = coord.Z();
91   Standard_Real M1 = 2.0 * A * B;
92   Standard_Real M2 = 2.0 * A * C;
93   Standard_Real M3 = 2.0 * B * C;
94   Standard_Real XX = ((2.0 * A * A) - 1.0) * X + M1 * Y + M2 * Z;
95   Standard_Real YY = M1 * X + ((2.0 * B * B) - 1.0) * Y + M3 * Z;
96   Standard_Real ZZ = M2 * X + M3 * Y + ((2.0 * C * C) - 1.0) * Z;
97   coord.SetCoord(XX,YY,ZZ);
98 }
99
100 void gp_Dir::Mirror (const gp_Ax2& A2)
101 {
102   const gp_Dir& Vz = A2.Direction();
103   Mirror(Vz);
104   Reverse();
105 }
106
107 void gp_Dir::Transform (const gp_Trsf& T)
108 {
109   if (T.Form() == gp_Identity ||  T.Form() == gp_Translation)    { }
110   else if (T.Form() == gp_PntMirror) { coord.Reverse(); }
111   else if (T.Form() == gp_Scale) { 
112     if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
113   }
114   else {
115     coord.Multiply (T.HVectorialPart());
116     Standard_Real D = coord.Modulus();
117     coord.Divide(D);
118     if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
119   } 
120 }
121
122 gp_Dir gp_Dir::Mirrored (const gp_Dir& V) const
123 {
124   gp_Dir Vres = *this;
125   Vres.Mirror (V);
126   return Vres;
127 }
128
129 gp_Dir gp_Dir::Mirrored (const gp_Ax1& A1) const
130 {
131   gp_Dir V = *this;
132   V.Mirror (A1);
133   return V;
134 }
135
136 gp_Dir gp_Dir::Mirrored (const gp_Ax2& A2) const
137 {
138   gp_Dir V = *this;
139   V.Mirror (A2);
140   return V;
141 }
142
143 void gp_Dir::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
144 {
145   OCCT_DUMP_VECTOR_CLASS (theOStream, "gp_Dir", 3, coord.X(), coord.Y(), coord.Z())
146 }
147
148 Standard_Boolean gp_Dir::InitFromJson (const Standard_SStream& theSStream, Standard_Integer& theStreamPos)
149 {
150   Standard_Integer aPos = theStreamPos;
151
152   OCCT_INIT_VECTOR_CLASS (Standard_Dump::Text (theSStream), "gp_Dir", aPos, 3, &coord.ChangeCoord (1), &coord.ChangeCoord (2), &coord.ChangeCoord (3))
153
154   theStreamPos = aPos;
155   return Standard_True;
156 }