1f186185513435ad091a9f17af8244aa2f5033f1
[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_Dir.hxx>
18
19 #include <gp_Ax1.hxx>
20 #include <gp_Ax2.hxx>
21 #include <gp_Trsf.hxx>
22 #include <gp_Vec.hxx>
23 #include <gp_XYZ.hxx>
24 #include <Standard_ConstructionError.hxx>
25 #include <Standard_DomainError.hxx>
26 #include <Standard_Dump.hxx>
27 #include <Standard_OutOfRange.hxx>
28
29 Standard_Real gp_Dir::Angle (const gp_Dir& Other) const
30 {
31   //    Commentaires :
32   //    Au dessus de 45 degres l'arccos donne la meilleur precision pour le
33   //    calcul de l'angle. Sinon il vaut mieux utiliser l'arcsin.
34   //    Les erreurs commises sont loin d'etre negligeables lorsque l'on est
35   //    proche de zero ou de 90 degres.
36   //    En 3d les valeurs angulaires sont toujours positives et comprises entre
37   //    0 et PI
38   Standard_Real Cosinus = coord.Dot (Other.coord);
39   if (Cosinus > -0.70710678118655 && Cosinus < 0.70710678118655)
40     return acos (Cosinus);
41   else {
42     Standard_Real Sinus = (coord.Crossed (Other.coord)).Modulus ();
43     if(Cosinus < 0.0)  return M_PI - asin (Sinus);
44     else               return      asin (Sinus);
45   }
46 }
47
48 Standard_Real gp_Dir::AngleWithRef (const gp_Dir& Other,
49                                     const gp_Dir& Vref) const
50 {
51   Standard_Real Ang;
52   gp_XYZ XYZ = coord.Crossed (Other.coord);
53   Standard_Real Cosinus = coord.Dot(Other.coord);
54   Standard_Real Sinus   = XYZ.Modulus ();
55   if (Cosinus > -0.70710678118655 && Cosinus < 0.70710678118655)
56     Ang =  acos (Cosinus);
57   else {
58     if(Cosinus < 0.0)  Ang = M_PI - asin (Sinus);
59     else               Ang =      asin (Sinus);
60   }
61   if (XYZ.Dot (Vref.coord) >= 0.0)  return  Ang;
62   else                              return -Ang;
63
64
65 void gp_Dir::Mirror (const gp_Dir& V)
66 {
67   const gp_XYZ& XYZ = V.coord;
68   Standard_Real A = XYZ.X();
69   Standard_Real B = XYZ.Y();
70   Standard_Real C = XYZ.Z();
71   Standard_Real X = coord.X();
72   Standard_Real Y = coord.Y();
73   Standard_Real Z = coord.Z();
74   Standard_Real M1 = 2.0 * A * B;
75   Standard_Real M2 = 2.0 * A * C;
76   Standard_Real M3 = 2.0 * B * C;
77   Standard_Real XX = ((2.0 * A * A) - 1.0) * X + M1 * Y + M2 * Z;
78   Standard_Real YY = M1 * X + ((2.0 * B * B) - 1.0) * Y + M3 * Z;
79   Standard_Real ZZ = M2 * X + M3 * Y + ((2.0 * C * C) - 1.0) * Z;
80   coord.SetCoord(XX,YY,ZZ);
81 }
82
83 void gp_Dir::Mirror (const gp_Ax1& A1)
84 {
85   const gp_XYZ& XYZ = A1.Direction().coord;
86   Standard_Real A = XYZ.X();
87   Standard_Real B = XYZ.Y();
88   Standard_Real C = XYZ.Y();
89   Standard_Real X = coord.X();
90   Standard_Real Y = coord.Y();
91   Standard_Real Z = coord.Z();
92   Standard_Real M1 = 2.0 * A * B;
93   Standard_Real M2 = 2.0 * A * C;
94   Standard_Real M3 = 2.0 * B * C;
95   Standard_Real XX = ((2.0 * A * A) - 1.0) * X + M1 * Y + M2 * Z;
96   Standard_Real YY = M1 * X + ((2.0 * B * B) - 1.0) * Y + M3 * Z;
97   Standard_Real ZZ = M2 * X + M3 * Y + ((2.0 * C * C) - 1.0) * Z;
98   coord.SetCoord(XX,YY,ZZ);
99 }
100
101 void gp_Dir::Mirror (const gp_Ax2& A2)
102 {
103   const gp_Dir& Vz = A2.Direction();
104   Mirror(Vz);
105   Reverse();
106 }
107
108 void gp_Dir::Transform (const gp_Trsf& T)
109 {
110   if (T.Form() == gp_Identity ||  T.Form() == gp_Translation)    { }
111   else if (T.Form() == gp_PntMirror) { coord.Reverse(); }
112   else if (T.Form() == gp_Scale) { 
113     if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
114   }
115   else {
116     coord.Multiply (T.HVectorialPart());
117     Standard_Real D = coord.Modulus();
118     coord.Divide(D);
119     if (T.ScaleFactor() < 0.0) { coord.Reverse(); }
120   } 
121 }
122
123 gp_Dir gp_Dir::Mirrored (const gp_Dir& V) const
124 {
125   gp_Dir Vres = *this;
126   Vres.Mirror (V);
127   return Vres;
128 }
129
130 gp_Dir gp_Dir::Mirrored (const gp_Ax1& A1) const
131 {
132   gp_Dir V = *this;
133   V.Mirror (A1);
134   return V;
135 }
136
137 gp_Dir gp_Dir::Mirrored (const gp_Ax2& A2) const
138 {
139   gp_Dir V = *this;
140   V.Mirror (A2);
141   return V;
142 }
143
144 void gp_Dir::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
145 {
146   OCCT_DUMP_VECTOR_CLASS (theOStream, "gp_Dir", 3, coord.X(), coord.Y(), coord.Z())
147 }
148
149 Standard_Boolean gp_Dir::InitFromJson (const Standard_SStream& theSStream, Standard_Integer& theStreamPos)
150 {
151   Standard_Integer aPos = theStreamPos;
152
153   OCCT_INIT_VECTOR_CLASS (Standard_Dump::Text (theSStream), "gp_Dir", aPos, 3, &coord.ChangeCoord (1), &coord.ChangeCoord (2), &coord.ChangeCoord (3))
154
155   theStreamPos = aPos;
156   return Standard_True;
157 }