source: GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoVector2.h @ 774

Revision 774, 12.5 KB checked in by gumbau, 18 years ago (diff)

GTGeometry and GeoTool? initial imports

Line 
1#ifndef __GEO_VECTOR2__
2#define __GEO_VECTOR2__
3#ifndef DOXYGEN_SHOULD_SKIP_THIS
4
5
6#include "GeoBase.h"
7#include <cmath>
8#include <cassert>
9#include <ostream>
10
11namespace Geometry
12{
13
14        class Vector2
15    {
16    public:
17        union {
18            struct {
19                Real x, y;       
20            };
21            Real val[2];
22        };
23
24    public:
25        inline Vector2()
26        {
27        }
28
29        inline Vector2( Real fX, Real fY )
30            : x( fX ), y( fY )
31        {
32        }
33
34        inline Vector2( const Real* const r )
35            : x( r[0] ), y( r[1] )
36        {
37        }
38
39        inline Vector2( const Vector2& rkVector )
40            : x( rkVector.x ), y( rkVector.y )
41        {
42        }
43
44                inline Real operator [] ( size_t i ) const
45        {
46            assert( i < 2 );
47
48            return *(&x+i);
49        }
50
51                inline Real& operator [] ( size_t i )
52        {
53            assert( i < 2 );
54
55            return *(&x+i);
56        }
57
58        /** Assigns the value of the other vector.
59            @param
60                rkVector The other vector
61        */
62        inline Vector2& operator = ( const Vector2& rkVector )
63        {
64            x = rkVector.x;
65            y = rkVector.y;       
66
67            return *this;
68        }
69
70        inline bool operator == ( const Vector2& rkVector ) const
71        {
72            return ( x == rkVector.x && y == rkVector.y );
73        }
74
75        inline bool operator != ( const Vector2& rkVector ) const
76        {
77            return ( x != rkVector.x || y != rkVector.y  );
78        }
79
80        // arithmetic operations
81        inline Vector2 operator + ( const Vector2& rkVector ) const
82        {
83            Vector2 kSum;
84
85            kSum.x = x + rkVector.x;
86            kSum.y = y + rkVector.y;
87
88            return kSum;
89        }
90
91        inline Vector2 operator - ( const Vector2& rkVector ) const
92        {
93            Vector2 kDiff;
94
95            kDiff.x = x - rkVector.x;
96            kDiff.y = y - rkVector.y;
97
98            return kDiff;
99        }
100
101        inline Vector2 operator * ( Real fScalar ) const
102        {
103            Vector2 kProd;
104
105            kProd.x = fScalar*x;
106            kProd.y = fScalar*y;
107
108            return kProd;
109        }
110
111        inline Vector2 operator * ( const Vector2& rhs) const
112        {
113            Vector2 kProd;
114
115            kProd.x = rhs.x * x;
116            kProd.y = rhs.y * y;
117
118            return kProd;
119        }
120
121        inline Vector2 operator / ( Real fScalar ) const
122        {
123            assert( fScalar != 0.0f );
124
125            Vector2 kDiv;
126
127            Real fInv = 1.0f / fScalar;
128            kDiv.x = x * fInv;
129            kDiv.y = y * fInv;
130
131            return kDiv;
132        }
133
134        inline Vector2 operator - () const
135        {
136            Vector2 kNeg;
137
138            kNeg.x = -x;
139            kNeg.y = -y;
140
141            return kNeg;
142        }
143
144        inline friend Vector2 operator * ( Real fScalar, const Vector2& rkVector )
145        {
146            Vector2 kProd;
147
148            kProd.x = fScalar * rkVector.x;
149            kProd.y = fScalar * rkVector.y;
150
151            return kProd;
152        }
153
154        // arithmetic updates
155        inline Vector2& operator += ( const Vector2& rkVector )
156        {
157            x += rkVector.x;
158            y += rkVector.y;
159
160            return *this;
161        }
162
163        inline Vector2& operator -= ( const Vector2& rkVector )
164        {
165            x -= rkVector.x;
166            y -= rkVector.y;
167
168            return *this;
169        }
170
171        inline Vector2& operator *= ( Real fScalar )
172        {
173            x *= fScalar;
174            y *= fScalar;
175
176            return *this;
177        }
178
179        inline Vector2& operator /= ( Real fScalar )
180        {
181            assert( fScalar != 0.0f );
182
183            Real fInv = 1.0f / fScalar;
184
185            x *= fInv;
186            y *= fInv;
187
188            return *this;
189        }
190
191        /** Returns the length (magnitude) of the vector.
192            @warning
193                This operation requires a square root and is expensive in
194                terms of CPU operations. If you don't need to know the exact
195                length (e.g. for just comparing lengths) use squaredLength()
196                instead.
197        */
198        inline Real length () const
199        {
200            return sqrt( x * x + y * y );
201        }
202
203        /** Returns the square of the length(magnitude) of the vector.
204            @remarks
205                This  method is for efficiency - calculating the actual
206                length of a vector requires a square root, which is expensive
207                in terms of the operations required. This method returns the
208                square of the length of the vector, i.e. the same as the
209                length but before the square root is taken. Use this if you
210                want to find the longest / shortest vector without incurring
211                the square root.
212        */
213        inline Real squaredLength () const
214        {
215            return x * x + y * y;
216        }
217
218        /** Calculates the dot (scalar) product of this vector with another.
219            @remarks
220                The dot product can be used to calculate the angle between 2
221                vectors. If both are unit vectors, the dot product is the
222                cosine of the angle; otherwise the dot product must be
223                divided by the product of the lengths of both vectors to get
224                the cosine of the angle. This result can further be used to
225                calculate the distance of a point from a plane.
226            @param
227                vec Vector with which to calculate the dot product (together
228                with this one).
229            @returns
230                A float representing the dot product value.
231        */
232        inline Real dotProduct(const Vector2& vec) const
233        {
234            return x * vec.x + y * vec.y;
235        }
236
237        /** Normalises the vector.
238            @remarks
239                This method normalises the vector such that it's
240                length / magnitude is 1. The result is called a unit vector.
241            @note
242                This function will not crash for zero-sized vectors, but there
243                will be no changes made to their components.
244            @returns The previous length of the vector.
245        */
246        inline Real normalise()
247        {
248            Real fLength = sqrt( x * x + y * y);
249
250            // Will also work for zero-sized vectors, but will change nothing
251            if ( fLength > 1e-08f )
252            {
253                Real fInvLength = 1.0f / fLength;
254                x *= fInvLength;
255                y *= fInvLength;
256            }
257
258            return fLength;
259        }
260
261   
262   
263        /** Returns a vector at a point half way between this and the passed
264            in vector.
265        */
266        inline Vector2 midPoint( const Vector2& vec ) const
267        {
268            return Vector2(
269                ( x + vec.x ) * 0.5f,
270                ( y + vec.y ) * 0.5f );
271        }
272
273        /** Returns true if the vector's scalar components are all greater
274            that the ones of the vector it is compared against.
275        */
276        inline bool operator < ( const Vector2& rhs ) const
277        {
278            if( x < rhs.x && y < rhs.y )
279                return true;
280            return false;
281        }
282
283        /** Returns true if the vector's scalar components are all smaller
284            that the ones of the vector it is compared against.
285        */
286        inline bool operator > ( const Vector2& rhs ) const
287        {
288            if( x > rhs.x && y > rhs.y )
289                return true;
290            return false;
291        }
292
293        /** Sets this vector's components to the minimum of its own and the
294            ones of the passed in vector.
295            @remarks
296                'Minimum' in this case means the combination of the lowest
297                value of x, y and z from both vectors. Lowest is taken just
298                numerically, not magnitude, so -1 < 0.
299        */
300        inline void makeFloor( const Vector2& cmp )
301        {
302            if( cmp.x < x ) x = cmp.x;
303            if( cmp.y < y ) y = cmp.y;
304        }
305
306        /** Sets this vector's components to the maximum of its own and the
307            ones of the passed in vector.
308            @remarks
309                'Maximum' in this case means the combination of the highest
310                value of x, y and z from both vectors. Highest is taken just
311                numerically, not magnitude, so 1 > -3.
312        */
313        inline void makeCeil( const Vector2& cmp )
314        {
315            if( cmp.x > x ) x = cmp.x;
316            if( cmp.y > y ) y = cmp.y;
317        }
318
319        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
320            @remarks
321                This method will return a vector which is perpendicular to this
322                vector. There are an infinite number of possibilities but this
323                method will guarantee to generate one of them. If you need more
324                control you should use the Quaternion class.
325        */
326        inline Vector2 perpendicular(void) const
327        {         
328            return Vector2 (-y, x);
329        }
330        /** Calculates the cross-product of 2 vectors, i.e. the vector that
331            lies perpendicular to them both.
332            @remarks
333                The cross-product is normally used to calculate the normal
334                vector of a plane, by calculating the cross-product of 2
335                non-equivalent vectors which lie on the plane (e.g. 2 edges
336                of a triangle).
337            @param
338                vec Vector which, together with this one, will be used to
339                calculate the cross-product.
340            @returns
341                A vector which is the result of the cross-product. This
342                vector will <b>NOT</b> be normalised, to maximise efficiency
343                - call Vector3::normalise on the result if you wish this to
344                be done. As for which side the resultant vector will be on, the
345                returned vector will be on the side from which the arc from 'this'
346                to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
347                = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
348            @par
349                For a clearer explanation, look a the left and the bottom edges
350                of your monitor's screen. Assume that the first vector is the
351                left edge and the second vector is the bottom edge, both of
352                them starting from the lower-left corner of the screen. The
353                resulting vector is going to be perpendicular to both of them
354                and will go <i>inside</i> the screen, towards the cathode tube
355                (assuming you're using a CRT monitor, of course).
356        */
357        inline Vector2 crossProduct( const Vector2& rkVector ) const
358        {
359            return Vector2(-rkVector.y, rkVector.x);
360        }
361               
362        /** Returns true if this vector is zero length. */
363        inline bool isZeroLength(void) const
364        {
365            Real sqlen = (x * x) + (y * y);
366            return (sqlen < (1e-06 * 1e-06));
367
368        }
369
370        /** As normalise, except that this vector is unaffected and the
371            normalised vector is returned as a copy. */
372        inline Vector2 normalisedCopy(void) const
373        {
374            Vector2 ret = *this;
375            ret.normalise();
376            return ret;
377        }
378
379        /** Calculates a reflection vector to the plane with the given normal .
380        @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
381        */
382        inline Vector2 reflect(const Vector2& normal)
383        {
384            return Vector2( *this - ( 2 * this->dotProduct(normal) * normal ) );
385        }
386
387        // special points
388        static const Vector2 ZERO;
389        static const Vector2 UNIT_X;
390        static const Vector2 UNIT_Y;
391        static const Vector2 NEGATIVE_UNIT_X;
392        static const Vector2 NEGATIVE_UNIT_Y;
393        static const Vector2 UNIT_SCALE;
394
395        /** Function for writing to a stream.
396                 */
397        inline friend std::ostream& operator <<
398            ( std::ostream& o, const Vector2& v )
399        {
400            o << "Vector2(" << v.x << ", " << v.y <<  ")";
401            return o;
402        }
403       
404               
405    };
406
407}
408#endif /* DOXYGEN_SHOULD_SKIP_THIS */
409#endif
Note: See TracBrowser for help on using the repository browser.