0024288: Provide flipping text for AIS_Dimensions
[occt.git] / src / NCollection / NCollection_Vec3.hxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 #ifndef _NCollection_Vec3_H__
20 #define _NCollection_Vec3_H__
21
22 #include <cstring>
23 #include <cmath>
24 #include <NCollection_Vec2.hxx>
25
26 //! Auxiliary macros to define couple of similar access components as vector methods
27 #define NCOLLECTION_VEC_COMPONENTS_3D(theX, theY, theZ) \
28   const NCollection_Vec3<Element_t> theX##theY##theZ() const { return NCollection_Vec3<Element_t>(theX(), theY(), theZ()); } \
29   const NCollection_Vec3<Element_t> theX##theZ##theY() const { return NCollection_Vec3<Element_t>(theX(), theZ(), theY()); } \
30   const NCollection_Vec3<Element_t> theY##theX##theZ() const { return NCollection_Vec3<Element_t>(theY(), theX(), theZ()); } \
31   const NCollection_Vec3<Element_t> theY##theZ##theX() const { return NCollection_Vec3<Element_t>(theY(), theZ(), theX()); } \
32   const NCollection_Vec3<Element_t> theZ##theY##theX() const { return NCollection_Vec3<Element_t>(theZ(), theY(), theX()); } \
33   const NCollection_Vec3<Element_t> theZ##theX##theY() const { return NCollection_Vec3<Element_t>(theZ(), theX(), theY()); }
34
35 //! Generic 3-components vector.
36 //! To be used as RGB color pixel or XYZ 3D-point.
37 //! The main target for this class - to handle raw low-level arrays (from/to graphic driver etc.).
38 template<typename Element_t>
39 class NCollection_Vec3
40 {
41
42 public:
43
44   //! Returns the number of components.
45   static int Length()
46   {
47     return 3;
48   }
49
50   //! Empty constructor. Construct the zero vector.
51   NCollection_Vec3()
52   {
53     std::memset (this, 0, sizeof(NCollection_Vec3));
54   }
55
56   //! Initialize ALL components of vector within specified value.
57   explicit NCollection_Vec3 (Element_t theValue)
58   {
59     v[0] = v[1] = v[2] = theValue;
60   }
61
62   //! Per-component constructor.
63   explicit NCollection_Vec3 (const Element_t theX,
64                              const Element_t theY,
65                              const Element_t theZ)
66   {
67     v[0] = theX;
68     v[1] = theY;
69     v[2] = theZ;
70   }
71
72   //! Constructor from 2-components vector.
73   explicit NCollection_Vec3 (const NCollection_Vec2<Element_t>& theVec2)
74   {
75     v[0] = theVec2[0];
76     v[1] = theVec2[1];
77     v[2] = Element_t(0);
78   }
79
80   //! Copy constructor.
81   NCollection_Vec3 (const NCollection_Vec3& theVec3)
82   {
83     std::memcpy (this, &theVec3, sizeof(NCollection_Vec3));
84   }
85
86   //! Assignment operator.
87   const NCollection_Vec3& operator= (const NCollection_Vec3& theVec3)
88   {
89     std::memcpy (this, &theVec3, sizeof(NCollection_Vec3));
90     return *this;
91   }
92
93   //! Alias to 1st component as X coordinate in XYZ.
94   Element_t x() const { return v[0]; }
95
96   //! Alias to 1st component as RED channel in RGB.
97   Element_t r() const { return v[0]; }
98
99   //! Alias to 2nd component as Y coordinate in XYZ.
100   Element_t y() const { return v[1]; }
101
102   //! Alias to 2nd component as GREEN channel in RGB.
103   Element_t g() const { return v[1]; }
104
105   //! Alias to 3rd component as Z coordinate in XYZ.
106   Element_t z() const { return v[2]; }
107
108   //! Alias to 3rd component as BLUE channel in RGB.
109   Element_t b() const { return v[2]; }
110
111   //! @return 2 components by their names in specified order (in GLSL-style)
112   NCOLLECTION_VEC_COMPONENTS_2D(x, y);
113   NCOLLECTION_VEC_COMPONENTS_2D(x, z);
114   NCOLLECTION_VEC_COMPONENTS_2D(y, z);
115
116   //! @return 3 components by their names in specified order (in GLSL-style)
117   NCOLLECTION_VEC_COMPONENTS_3D(x, y, z);
118
119   //! Alias to 1st component as X coordinate in XYZ.
120   Element_t& x() { return v[0]; }
121
122   //! Alias to 1st component as RED channel in RGB.
123   Element_t& r() { return v[0]; }
124
125   //! Alias to 2nd component as Y coordinate in XYZ.
126   Element_t& y() { return v[1]; }
127
128   //! Alias to 2nd component as GREEN channel in RGB.
129   Element_t& g() { return v[1]; }
130
131   //! Alias to 3rd component as Z coordinate in XYZ.
132   Element_t& z() { return v[2]; }
133
134   //! Alias to 3rd component as BLUE channel in RGB.
135   Element_t& b() { return v[2]; }
136
137   //! @return XY-components modifiable vector
138   NCollection_Vec2<Element_t>& xy()
139   {
140     return *((NCollection_Vec2<Element_t>* )&v[0]);
141   }
142
143   //! @return YZ-components modifiable vector
144   NCollection_Vec2<Element_t>& yz()
145   {
146     return *((NCollection_Vec2<Element_t>* )&v[1]);
147   }
148
149   //! Raw access to the data (for OpenGL exchange).
150   const Element_t* GetData()    const { return v; }
151         Element_t* ChangeData()       { return v; }
152   operator const   Element_t*() const { return v; }
153   operator         Element_t*()       { return v; }
154
155   //! Compute per-component summary.
156   NCollection_Vec3& operator+= (const NCollection_Vec3& theAdd)
157   {
158     v[0] += theAdd.v[0];
159     v[1] += theAdd.v[1];
160     v[2] += theAdd.v[2];
161     return *this;
162   }
163
164   //! Compute per-component summary.
165   friend NCollection_Vec3 operator+ (const NCollection_Vec3& theLeft,
166                                      const NCollection_Vec3& theRight)
167   {
168     NCollection_Vec3 aSumm = NCollection_Vec3 (theLeft);
169     return aSumm += theRight;
170   }
171
172   //! Unary -.
173   NCollection_Vec3 operator-() const
174   {
175     return NCollection_Vec3 (-x(), -y(), -z());
176   }
177
178   //! Compute per-component subtraction.
179   NCollection_Vec3& operator-= (const NCollection_Vec3& theDec)
180   {
181     v[0] -= theDec.v[0];
182     v[1] -= theDec.v[1];
183     v[2] -= theDec.v[2];
184     return *this;
185   }
186
187   //! Compute per-component subtraction.
188   friend NCollection_Vec3 operator- (const NCollection_Vec3& theLeft,
189                                      const NCollection_Vec3& theRight)
190   {
191     NCollection_Vec3 aSumm = NCollection_Vec3 (theLeft);
192     return aSumm -= theRight;
193   }
194
195   //! Compute per-component multiplication by scale factor.
196   void Multiply (const Element_t theFactor)
197   {
198     v[0] *= theFactor;
199     v[1] *= theFactor;
200     v[2] *= theFactor;
201   }
202
203   //! Compute per-component multiplication.
204   NCollection_Vec3& operator*= (const NCollection_Vec3& theRight)
205   {
206     v[0] *= theRight.v[0];
207     v[1] *= theRight.v[1];
208     v[2] *= theRight.v[2];
209     return *this;
210   }
211
212   //! Compute per-component multiplication.
213   friend NCollection_Vec3 operator* (const NCollection_Vec3& theLeft,
214                                      const NCollection_Vec3& theRight)
215   {
216     NCollection_Vec3 aResult = NCollection_Vec3 (theLeft);
217     return aResult *= theRight;
218   }
219
220   //! Compute per-component multiplication by scale factor.
221   NCollection_Vec3& operator*= (const Element_t theFactor)
222   {
223     Multiply (theFactor);
224     return *this;
225   }
226
227   //! Compute per-component multiplication by scale factor.
228   NCollection_Vec3 operator* (const Element_t theFactor) const
229   {
230     return Multiplied (theFactor);
231   }
232
233   //! Compute per-component multiplication by scale factor.
234   NCollection_Vec3 Multiplied (const Element_t theFactor) const
235   {
236     NCollection_Vec3 aCopyVec3 (*this);
237     aCopyVec3 *= theFactor;
238     return aCopyVec3;
239   }
240
241   //! Compute per-component division by scale factor.
242   NCollection_Vec3& operator/= (const Element_t theInvFactor)
243   {
244     v[0] /= theInvFactor;
245     v[1] /= theInvFactor;
246     v[2] /= theInvFactor;
247     return *this;
248   }
249
250   //! Compute per-component division by scale factor.
251   NCollection_Vec3 operator/ (const Element_t theInvFactor)
252   {
253     NCollection_Vec3 aResult (this);
254     return aResult /= theInvFactor;
255   }
256
257   //! Computes the dot product.
258   Element_t Dot (const NCollection_Vec3& theOther) const
259   {
260     return x() * theOther.x() + y() * theOther.y() + z() * theOther.z();
261   }
262
263   //! Computes the vector modulus (magnitude, length).
264   Element_t Modulus() const
265   {
266     return std::sqrt (x() * x() + y() * y() + z() * z());
267   }
268
269   //! Computes the square of vector modulus (magnitude, length).
270   //! This method may be used for performance tricks.
271   Element_t SquareModulus() const
272   {
273     return x() * x() + y() * y() + z() * z();
274   }
275
276   //! Normalize the vector.
277   void Normalize()
278   {
279     Element_t aModulus = Modulus();
280     if (aModulus != Element_t(0)) // just avoid divide by zero
281     {
282       x() = x() / aModulus;
283       y() = y() / aModulus;
284       z() = z() / aModulus;
285     }
286   }
287
288   //! Normalize the vector.
289   NCollection_Vec3 Normalized() const
290   {
291     NCollection_Vec3 aCopy (*this);
292     aCopy.Normalize();
293     return aCopy;
294   }
295
296   //! Computes the cross product.
297   static NCollection_Vec3 Cross (const NCollection_Vec3& theVec1,
298                                  const NCollection_Vec3& theVec2)
299   {
300     return NCollection_Vec3(theVec1.y() * theVec2.z() - theVec1.z() * theVec2.y(),
301             theVec1.z() * theVec2.x() - theVec1.x() * theVec2.z(),
302             theVec1.x() * theVec2.y() - theVec1.y() * theVec2.x());
303   }
304
305   //! Compute linear interpolation between to vectors.
306   //! @param theT - interpolation coefficient 0..1;
307   //! @return interpolation result.
308   static NCollection_Vec3 GetLERP (const NCollection_Vec3& theFrom,
309                                    const NCollection_Vec3& theTo,
310                                    const Element_t         theT)
311   {
312     return theFrom * (Element_t(1) - theT) + theTo * theT;
313   }
314
315   //! Constuct DX unit vector.
316   static NCollection_Vec3 DX()
317   {
318     return NCollection_Vec3 (Element_t(1), Element_t(0), Element_t(0));
319   }
320
321   //! Constuct DY unit vector.
322   static NCollection_Vec3 DY()
323   {
324     return NCollection_Vec3 (Element_t(0), Element_t(1), Element_t(0));
325   }
326
327   //! Constuct DZ unit vector.
328   static NCollection_Vec3 DZ()
329   {
330     return NCollection_Vec3 (Element_t(0), Element_t(0), Element_t(1));
331   }
332
333 private:
334
335   Element_t v[3]; //!< define the vector as array to avoid structure alignment issues
336
337 };
338
339 //! Optimized concretization for float type.
340 template<> inline NCollection_Vec3<float>& NCollection_Vec3<float>::operator/= (const float theInvFactor)
341 {
342   Multiply (1.0f / theInvFactor);
343   return *this;
344 }
345
346 //! Optimized concretization for double type.
347 template<> inline NCollection_Vec3<double>& NCollection_Vec3<double>::operator/= (const double theInvFactor)
348 {
349   Multiply (1.0 / theInvFactor);
350   return *this;
351 }
352
353 #endif // _NCollection_Vec3_H__