1 /* Copyright 2011 Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file float2.h
16         @author Jukka Jyl�nki
17         @brief A 2D (x,y) ordered pair. */
18 #pragma once
19
20 #include "../MathBuildConfig.h"
21
22 #ifdef MATH_ENABLE_STL_SUPPORT
23 #include <string>
24 #include <vector>
25 #endif
26
27 #include "../MathGeoLibFwd.h"
28
29 #ifdef MATH_QT_INTEROP
30 #include <QVector2D>
31 #endif
32 #ifdef MATH_OGRE_INTEROP
33 #include <OgreVector2.h>
34 #endif
35 #ifdef MATH_URHO3D_INTEROP
36 #include <Urho3D/Math/Vector2.h>
37 #endif
38
39 MATH_BEGIN_NAMESPACE
40
41 /// A vector of form (x,y).
42 class float2
43 {
44 public:
45         enum
46         {
47                 /// Specifies the number of elements in this vector.
48                 Size = 2
49         };
50         /// The x component.
51         /** A float2 is 8 bytes in size. This element lies in the memory offsets 0-3 of this class. */
52         float x;
53         /// The y component. [similarOverload: x]
54         /** This element is packed to the memory offsets 4-7 of this class. */
55         float y;
56
57         /// The default constructor does not initialize any members of this class.
58         /** This means that the values of the members x and y are both undefined after creating a new float2 using
59                 this default constructor. Remember to assign to them before use.
60                 @see x, y. */
61         float2() {}
62
63 #ifdef MATH_EXPLICIT_COPYCTORS
64         /// The float2 copy constructor.
65         /** The copy constructor is a standard default copy-ctor, but it is explicitly written to be able to automatically pick up
66                 this function for script bindings. */
67         float2(const float2 &rhs) { x = rhs.xy = rhs.y; }
68 #endif
69
70         /// Constructs a new float2 with the value (x, y).
71         /** @see x, y. */
72         float2(float xfloat y);
73
74         /// Constructs a new float2 with the value (scalar, scalar).
75         /** @see x, y. */
76         explicit float2(float scalar);
77
78         /// Constructs this float2 from a C array, to the value (data[0], data[1]).
79         /** @param data An array containing two elements for x and y. This pointer may not be null. */
80         explicit float2(const float *data);
81
82         /// Casts this float2 to a C array.
83         /** This function does not allocate new memory or make a copy of this float2. This function simply
84                 returns a C pointer view to this data structure. Use ptr()[0] to access the x component of this float2
85                 and ptr()[1] to access the y component.
86                 @note Since the returned pointer points to this class, do not dereference the pointer after this
87                         float2 has been deleted. You should never store a copy of the returned pointer.
88                 @note This function is provided for compatibility with other APIs which require raw C pointer access
89                         to vectors. Avoid using this function in general, and instead always use the operator []
90                         or the At() function to access the elements of this vector by index.
91                 @return A pointer to the first float element of this class. The data is contiguous in memory.
92                 @see operator [](), At(). */
93         FORCE_INLINE float *ptr() { return &x; }
94         FORCE_INLINE const float *ptr() const return &x; }
95
96         /// Accesses an element of this vector using array notation.
97         /** @param index The element to get. Pass in 0 for x and 1 for y.
98                 @note If you have a non-const instance of this class, you can use this notation to set the elements of
99                         this vector as well, e.g. vec[1] = 10.f; would set the y-component of this vector.
100                 @see ptr(), At(). */
101         float &operator [](int index) { return At(index); }
102         CONST_WIN32 float operator [](int index) const return At(index); }
103
104         /// Accesses an element of this vector.
105         /** @param index The element to get. Pass in 0 for x and 1 for y.
106                 @note If you have a non-const instance of this class, you can use this notation to set the elements of
107                         this vector as well, e.g. vec.At(1) = 10.f; would set the y-component of this vector.
108                 @see ptr(), operator [](). */
109         float &At(int index);
110         CONST_WIN32 float At(int index) const;
111
112         /// Adds two vectors. [indexTitle: operators +,-,*,/]
113         /** This function is identical to the member function Add().
114                 @return float2(x + v.x, y + v.y); */
115         float2 operator +(const float2 &v) const;
116         /// Performs an unary negation of this vector. [similarOverload: operator+] [hideIndex]
117         /** This function is identical to the member function Neg().
118                 @return float2(-x, -y). */
119         float2 operator -() const;
120         /// Subtracts the given vector from this vector. [similarOverload: operator+] [hideIndex]
121         /** This function is identical to the member function Sub().
122                 @return float2(x - v.x, y - v.y); */
123         float2 operator -(const float2 &v) const;
124         /// Multiplies this vector by a scalar. [similarOverload: operator+] [hideIndex]
125         /** This function is identical to the member function Mul().
126                 @return float2(x * scalar, y * scalar); */
127         float2 operator *(float scalar) const;
128         /// Divides this vector by a scalar. [similarOverload: operator+] [hideIndex]
129         /** This function is identical to the member function Div().
130                 @return float2(x / scalar, y / scalar); */
131         float2 operator /(float scalar) const;
132         /// Unary operator + allows this structure to be used in an expression '+x'.
133         float2 operator +() const return *this; }
134
135         /// Adds a vector to this vector, in-place. [indexTitle: operators +=,-=,*=,/=]
136         /** @return A reference to this. */
137         float2 &operator +=(const float2 &v);
138         /// Subtracts a vector from this vector, in-place. [similarOverload: operator+=] [hideIndex]
139         /** @return A reference to this. */
140         float2 &operator -=(const float2 &v);
141         /// Multiplies this vector by a scalar, in-place. [similarOverload: operator+=] [hideIndex]
142         /** @return A reference to this. */
143         float2 &operator *=(float scalar);
144         /// Divides this vector by a scalar, in-place. [similarOverload: operator+=] [hideIndex]
145         /** @return A reference to this. */
146         float2 &operator /=(float scalar);
147
148 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
149         // In math textbooks, pointwise multiplication of vectors is not defined within a linear space.
150         // However, in programming it is often useful for e.g. modulating colors via pointwise multiplication.
151         // If you #define MATH_ENABLE_UNCOMMON_OPERATIONS, you'll get these operations upgraded to handy
152         // operator * and / notation and can use vec * vec and vec / vec. Otherwise, use the notation
153         // vec.Mul(vec) and vec.Div(vec) for pointwise notation. MATH_ENABLE_UNCOMMON_OPERATIONS also enables
154         // the operation scalar / vec.
155         float2 operator *(const float2 &vector) const return this->Mul(vector); }
156         float2 operator /(const float2 &vector) const return this->Div(vector); }
157         float2 &operator *=(const float2 &vector) { *this = this->Mul(vector); return *this; }
158         float2 &operator /=(const float2 &vector) { *this = this->Div(vector); return *this; }
159 #endif
160
161         /// Adds a vector to this vector. [IndexTitle: Add/Sub/Mul/Div]
162         /// @return (x+v.x, y+v.y).
163         float2 Add(const float2 &v) const return *this + v; }
164
165         /// Adds the vector (s,s) to this vector.
166         /// @note Mathematically, the addition of a vector and scalar is not defined in linear space structures,
167         ///      but this function is provided here for syntactical convenience.
168         /// @return (x+s, y+s).
169         float2 Add(float s) const;
170
171         /// Subtracts a vector from this vector. [similarOverload: Add] [hideIndex]
172         /// @return (x-v.x, y-v.y).
173         float2 Sub(const float2 &v) const return *this - v; }
174
175         /// Subtracts the vector (s,s) from this vector. [similarOverload: Add] [hideIndex]
176         /// @note Mathematically, the subtraction of a vector by a scalar is not defined in linear space structures,
177         ///      but this function is provided here for syntactical convenience.
178         /// @return (x-s, y-s).
179         float2 Sub(float s) const;
180
181         /// Subtracts this vector from the vector (s,s). [similarOverload: Add] [hideIndex]
182         /// @note Mathematically, the subtraction of a scalar by a vector is not defined in linear space structures,
183         ///      but this function is provided here for syntactical convenience.
184         /// @return (s-x, s-y).
185         float2 SubLeft(float s) const;
186
187         /// Multiplies this vector by a vector, element-wise. [similarOverload: Add] [hideIndex]
188         /// @note Mathematically, the multiplication of two vectors is not defined in linear space structures,
189         ///      but this function is provided here for syntactical convenience.
190         /// @return (x*v.x, y*v.y).
191         float2 Mul(const float2 &v) const;
192
193         /// Multiplies this vector by a scalar. [similarOverload: Add] [hideIndex]
194         /// @return (x*s, y*s).
195         float2 Mul(float s) const return *this * s; }
196
197         /// Divides this vector by a vector, element-wise. [similarOverload: Add] [hideIndex]
198         /// @note Mathematically, the division of two vectors is not defined in linear space structures,
199         ///      but this function is provided here for syntactical convenience.
200         /// @return (x/v.x, y/v.y).
201         float2 Div(const float2 &v) const;
202
203         /// Divides this vector by a scalar. [similarOverload: Add] [hideIndex]
204         /// @return (x/s, y/s).
205         float2 Div(float s) const return *this / s; }
206         
207         /// Divides the vector (s,s) by this vector, element-wise. [similarOverload: Add] [hideIndex]
208         /// @note Mathematically, the division of a scalar by a vector is not defined in linear space structures,
209         ///      but this function is provided here for syntactical convenience.
210         /// @return (s/x, s/y).
211         float2 DivLeft(float s) const;
212
213         /// Performs a 2D swizzled access to this vector. [indexTitle: xx/xy/yx/yy]
214         float2 xx() const return float2(x,x); }
215         float2 xy() const return float2(x,y); } ///< [similarOverload: xx] [hideIndex]
216         float2 yx() const return float2(y,x); } ///< [similarOverload: xx] [hideIndex]
217         float2 yy() const return float2(y,y); } ///< [similarOverload: xx] [hideIndex]
218
219         /// Performs a swizzled access to this vector.
220         /** For example, Swizzled(2,1,0) return float3(z,y,x). Swizzled(2,2,2,2) returns float4(z,z,z,z).
221                 @param i Chooses the element of this vector to pick for the x value of the returned vector, in the range [0, 2].
222                 @param j Chooses the element of this vector to pick for the y value of the returned vector, in the range [0, 2].
223                 @param k Chooses the element of this vector to pick for the z value of the returned vector, in the range [0, 2].
224                 @param l Chooses the element of this vector to pick for the w value of the returned vector, in the range [0, 2]. */
225         float4 Swizzled(int i, int j, int k, int l) const;
226         float3 Swizzled(int i, int j, int k) const;
227         float2 Swizzled(int i, int j) const;
228
229         /// Generates a new float2 by filling its entries by the given scalar.
230         /** @see float2::float2(float scalar), SetFromScalar(). */
231         static float2 FromScalar(float scalar);
232
233         /// Fills each entry of this float2 by the given scalar.
234         /** @see float2::float2(float scalar), FromScalar(). */
235         void SetFromScalar(float scalar);
236
237         /// Sets all elements of this vector.
238         /** @see x, y, At().. */
239         void Set(float xfloat y);
240
241         /// Converts the given vector represented in polar coordinates to an euclidean float2 (x,y) pair.
242         /** @param theta The direction (aimed angle, azimuth) of the vector, in radians. The value theta==0 returns a value in the +X direction,
243                 the value theta=pi/2 corresponds to +Y, theta=pi corresponds to -X and theta=-pi/2 (or 3pi/2) corresponds to -Y.
244                         This value is typically in the range [-pi, pi] (, or [0, 2pi]).
245                 @param length The magnitude of the vector. This is usually >= 0, although passing in the zero vector as radius returns (0,0), and passing
246                         in a negative radius mirrors the coordinate along the origin.
247                 @see FromPolarCoordinates, ToPolarCoordinates, AimedAngle. */
248         void SetFromPolarCoordinates(float theta, float length);
249         void SetFromPolarCoordinates(const float2 &polar) { SetFromPolarCoordinates(polar.x, polar.y); }
250         static float2 FromPolarCoordinates(float theta, float length);
251         static float2 FromPolarCoordinates(const float2 &polar) { return FromPolarCoordinates(polar.x, polar.y); }
252
253         /// Converts this euclidean (x,y) float2 to polar coordinates representation in the form (theta, length).
254         /** @note It is valid for the magnitude of this vector to be (very close to) zero, in which case the return value is the zero vector.
255                 @return A float2 that has the first component (x) representing the aimed angle (azimuth) of this direction vector, in radians,
256                 and is equal to atan2(this.y, this.x). The x component has a range of ]-pi/2, pi/2]. The second component (y) of the returned vector
257                 stores the length (radius) of this vector.
258                 @see SetFromPolarCoordinates, FromPolarCoorindates, AimedAngle. */
259         float2 ToPolarCoordinates() const;
260
261         /// Returns the aimed angle direction of this vector, in radians.
262         /** The aimed angle of a 2D vector corresponds to the theta part (or azimuth) of the polar coordinate representation of this vector. Essentially,
263                 describes the direction this vector is pointing at. A vector pointing towards +X returns 0, vector pointing towards +Y returns pi/2, vector
264                 pointing towards -X returns pi, and a vector pointing towards -Y returns -pi/2 (equal to 3pi/2).
265                 @note This vector does not need to be normalized for this function to work, but it DOES need to be non-zero (unlike the function ToPolarCoordinates).
266                 @return The aimed angle in the range ]-pi/2, pi/2].
267                 @see ToPolarCoordinates, FromPolarCoordinates, SetFromPolarCoordinates. */
268         float AimedAngle() const;
269
270         /// Computes the length of this vector.
271         /** @return Sqrt(x*x + y*y).
272                 @see LengthSq(), Distance(), DistanceSq(). */
273         float Length() const;
274
275         /// Computes the squared length of this vector.
276         /** Calling this function is faster than calling Length(), since this function avoids computing a square root.
277                 If you only need to compare lengths to each other, but are not interested in the actual length values,
278                 you can compare by using LengthSq(), instead of Length(), since Sqrt() is an order-preserving
279                 (monotonous and non-decreasing) function.
280                 @return x*x + y*y.
281                 @see LengthSq(), Distance(), DistanceSq(). */
282         float LengthSq() const;
283
284         /// Normalizes this float2.
285         /** In the case of failure, this vector is set to (1, 0), so calling this function will never result in an
286                 unnormalized vector.
287                 @note If this function fails to normalize the vector, no error message is printed, the vector is set to (1,0) and
288                         an error code 0 is returned. This is different than the behavior of the Normalized() function, which prints an
289                         error if normalization fails.
290                 @note This function operates in-place.
291                 @return The old length of this vector, or 0 if normalization failed.
292                 @see Normalized(). */
293         float Normalize();
294
295         /// Returns a normalized copy of this vector.
296         /** @note If the vector is zero and cannot be normalized, the vector (1, 0) is returned, and an error message is printed.
297                         If you do not want to generate an error message on failure, but want to handle the failure yourself, use the
298                         Normalize() function instead.
299                 @see Normalize(). */
300         float2 Normalized() const;
301
302         /// Scales this vector so that its new length is as given.
303         /** Calling this function is effectively the same as normalizing the vector first and then multiplying by newLength.
304                 In the case of failure, this vector is set to (newLength, 0), so calling this function will never result in an
305                 unnormalized vector.
306                 @note This function operates in-place.
307                 @return The old length of this vector. If this function returns 0, the scaling failed, and this vector is arbitrarily
308                         reset to (newLength, 0). In case of failure, no error message is generated. You are expected to handle the failure
309                         yourself.
310                 @see ScaledToLength(). */
311         float ScaleToLength(float newLength);
312
313         /// Returns a scaled copy of this vector which has its new length as given.
314         /** This function assumes the length of this vector is not zero. In the case of failure, an error message is printed,
315                 and the vector (newLength, 0) is returned.
316                 @see ScaleToLength(). */
317         float2 ScaledToLength(float newLength) const;
318
319         /// Tests if the length of this vector is one, up to the given epsilon.
320         /** @see IsZero(), IsFinite(), IsPerpendicular(). */
321         bool IsNormalized(float epsilonSq = 1e-5f) const;
322
323         /// Tests if this is the null vector, up to the given epsilon.
324         /** @see IsNormalized(), IsFinite(), IsPerpendicular(). */
325         bool IsZero(float epsilonSq = 1e-6f) const;
326
327         /// Tests if this vector contains valid finite elements.
328         /** @see IsNormalized(), IsZero(), IsPerpendicular(). */
329         bool IsFinite() const;
330
331         /// Tests if two vectors are perpendicular to each other.
332         /** @see IsNormalized(), IsZero(), IsPerpendicular(), Equals(). */
333         bool IsPerpendicular(const float2 &other, float epsilonSq = 1e-8f) const;
334
335         /// Tests if two vectors are equal, up to the given epsilon.
336         /** @see IsPerpendicular(). */
337         bool Equals(const float2 &other, float epsilon = 1e-3f) const;
338         bool Equals(float xfloat yfloat epsilon = 1e-3f) const;
339
340         /// Compares whether this float2 and the given float2 are identical bit-by-bit in the underlying representation.
341         /** @note Prefer using this over e.g. memcmp, since there can be SSE-related padding in the structures. */
342         bool BitEquals(const float2 &other) const;
343
344 #ifdef MATH_ENABLE_STL_SUPPORT
345         /// Returns "(x, y)".
346         std::string ToString() const;
347
348         /// Returns "x,y". This is the preferred format for the float2 if it has to be serialized to a string for machine transfer.
349         std::string SerializeToString() const;
350
351         /// Returns a string of C++ code that can be used to construct this object. Useful for generating test cases from badly behaving objects.
352         std::string SerializeToCodeString() const;
353 #endif
354
355         /// Parses a string that is of form "x,y" or "(x,y)" or "(x;y)" or "x y" to a new float2.
356         static float2 FromString(const char *str, const char **outEndStr = 0);
357 #ifdef MATH_ENABLE_STL_SUPPORT
358         static float2 FromString(const std::string &str) { return FromString(str.c_str()); }
359 #endif
360
361         /// @return x + y.
362         float SumOfElements() const;
363         /// @return x * y.
364         float ProductOfElements() const;
365         /// @return (x+y)/2.
366         float AverageOfElements() const;
367         /// @return Min(x, y).
368         /** @see MinElementIndex(). */
369         float MinElement() const;
370         /// Returns the index that has the smallest value in this vector.
371         /** @see MinElement(). */
372         int MinElementIndex() const;
373         /// @return Max(x, y).
374         /** @see MaxElementIndex(). */
375         float MaxElement() const;
376         /// Returns the index that has the smallest value in this vector.
377         /** @see MaxElement(). */
378         int MaxElementIndex() const;
379         /// Takes the element-wise absolute value of this vector.
380         /** @return float2(|x|, |y|).
381                 @see Neg(). */
382         float2 Abs() const;
383         /// Returns a copy of this vector with each element negated.
384         /** This function returns a new vector where each element x of the original vector is replaced by the value -x.
385                 @return float2(-x, -y).
386                 @see Abs(). */
387         float2 Neg() const;
388         /// Computes the element-wise reciprocal of this vector.
389         /** This function returns a new vector where each element x of the original vector is replaced by the value 1/x.
390                 @return float2(1/x, 1/y). */
391         float2 Recip() const;
392         /// Returns an element-wise minimum of this and the vector (ceil, ceil, ceil).
393         /** Each element that is larger than ceil is replaced by ceil. */
394         float2 Min(float ceil) const;
395         /// Returns an element-wise minimum of this and the given vector.
396         /** Each element that is larger than ceil is replaced by ceil.
397                 @see Max(), Clamp(). */
398         float2 Min(const float2 &ceil) const;
399         /// Returns an element-wise maximum of this and the vector (floor, floor, floor).
400         /** Each element that is smaller than floor is replaced by floor. */
401         float2 Max(float floor) const;
402         /// Returns an element-wise maximum of this and the given vector.
403         /** Each element that is smaller than floor is replaced by floor.
404                 @see Min(), Clamp(). */
405         float2 Max(const float2 &floor) const;
406         /// Returns a vector that has floor <= this[i] <= ceil for each element.
407         float2 Clamp(float floor, float ceil) const;
408         /// Limits each element of this vector between the corresponding elements in floor and ceil.
409         /** @see Min(), Max(), Clamp01(). */
410         float2 Clamp(const float2 &floor, const float2 &ceil) const;
411         /// Limits each element of this vector in the range [0, 1].
412         /** @see Min(), Max(), Clamp(). */
413         float2 Clamp01() const;
414
415         /// Computes the distance between this and the given float2.
416         /** @see DistanceSq(), Length(), LengthSq(). */
417         float Distance(const float2 &point) const;
418
419         /// Computes the squared distance between this and the given point.
420         /** Calling this function is faster than calling Distance(), since this function avoids computing a square root.
421                 If you only need to compare distances to each other, but are not interested in the actual distance values,
422                 you can compare by using DistanceSq(), instead of Distance(), since Sqrt() is an order-preserving
423                 (monotonous and non-decreasing) function.
424                 @see Distance(), Length(), LengthSq(). */
425         float DistanceSq(const float2 &point) const;
426
427         /// Computes the dot product of this and the given vector.
428         /** The dot product has a geometric interpretation of measuring how close two direction vectors are to pointing
429                 in the same direction, computing angles between vectors, or the length of a projection of one vector to another.
430                 @return x*v.x + y*v.y.
431                 @see AngleBetween(), ProjectTo(), ProjectToNorm(), Perp(), PerpDot(). */
432         float Dot(const float2 &v) const;
433
434         /// Returns this vector with the "perp" operator applied to it.
435         /** The perp operator rotates a vector 90 degrees ccw (around the "z axis"), i.e.
436                 for a 2D vector (x,y), this function returns the vector (-y, x).
437                 @note This function is identical to Rotated90CCW().
438                 @return (-y, x). The returned vector is perpendicular to this vector.
439                 @see PerpDot(), Rotated90CCW(). */
440         float2 Perp() const;
441
442         /// Computes the perp-dot product of this and the given float2 in the order this^perp (dot) rhs.
443         /** @see Dot(), Perp(). */
444         float PerpDot(const float2 &rhs) const;
445
446         /// Rotates this vector 90 degrees clock-wise.
447         /** This rotation is interpreted in a coordinate system on a plane where +x extends to the right, and +y extends upwards.
448                 @see Perp(), Rotated90CW(), Rotate90CCW(), Rotated90CCW(). */
449         void Rotate90CW();
450
451         /// Returns a vector that is perpendicular to this vector (rotated 90 degrees clock-wise).
452         /** @note This function is identical to Perp().
453                 @see Perp(), Rotate90CW(), Rotate90CCW(), Rotated90CCW(). */
454         float2 Rotated90CW() const;
455
456         /// Rotates this vector 90 degrees counterclock-wise .
457         /// This is in a coordinate system on a plane where +x extends to the right, and +y extends upwards.
458         /** @see Perp(), Rotate90CW(), Rotated90CW(), Rotated90CCW(). */
459         void Rotate90CCW();
460
461         /// Returns a vector that is perpendicular to this vector (rotated 90 degrees counter-clock-wise).
462         /** @see Perp(), Rotate90CW(), Rotated90CW(), Rotate90CCW(). */
463         float2 Rotated90CCW() const;
464
465         /// Returns this vector reflected about a plane with the given normal.
466         /** By convention, both this and the reflected vector point away from the plane with the given normal
467                 @see Refract(). */
468         float2 Reflect(const float2 &normal) const;
469
470         /// Refracts this vector about a plane with the given normal.
471         /** By convention, the this vector points towards the plane, and the returned vector points away from the plane.
472                 When the ray is going from a denser material to a lighter one, total internal reflection can occur.
473                 In this case, this function will just return a reflected vector from a call to Reflect().
474                 @param normal Specifies the plane normal direction
475                 @param negativeSideRefractionIndex The refraction index of the material we are exiting.
476                 @param positiveSideRefractionIndex The refraction index of the material we are entering.
477                 @see Reflect(). */
478         float2 Refract(const float2 &normal, float negativeSideRefractionIndex, float positiveSideRefractionIndex) const;
479
480         /// Projects this vector onto the given unnormalized direction vector.
481         /** @param direction The direction vector to project this vector onto. This function will normalize this
482                         vector, so you can pass in an unnormalized vector.
483                 @see ProjectToNorm(). */
484         float2 ProjectTo(const float2 &direction) const;
485
486         /// Projects this vector onto the given normalized direction vector.
487         /** @param direction The vector to project onto. This vector must be normalized.
488                 @see ProjectTo(). */
489         float2 ProjectToNorm(const float2 &direction) const;
490
491         /// Returns the angle between this vector and the specified vector, in radians.
492         /** @note This function takes into account that this vector or the other vector can be unnormalized, and normalizes the computations.
493                         If you are computing the angle between two normalized vectors, it is better to use AngleBetweenNorm().
494                 @see AngleBetweenNorm(). */             
495         float AngleBetween(const float2 &other) const;
496
497         /// Returns the angle between this vector and the specified normalized vector, in radians.
498         /** @param normalizedVector The direction vector to compute the angle against. This vector must be normalized.
499                 @note This vector must be normalized to call this function.
500                 @see AngleBetween(). */
501         float AngleBetweenNorm(const float2 &normalizedVector) const;
502
503         /// Breaks this vector down into parallel and perpendicular components with respect to the given direction.
504         /** @param direction The direction the decomposition is to be computed. This vector must be normalized.
505                 @param outParallel [out] Receives the part of this vector that is parallel to the given direction vector.
506                 @param outPerpendicular [out] Receives the part of this vector that is perpendicular to the given direction vector. */
507         void Decompose(const float2 &direction, float2 &outParallel, float2 &outPerpendicular) const;
508
509         /// Linearly interpolates between this and the vector b.
510         /** @param b The target endpoint to lerp towards to.
511                 @param t The interpolation weight, in the range [0, 1].
512                 @return Lerp(b, 0) returns this vector, Lerp(b, 1) returns the vector b.
513                         Lerp(b, 0.5) returns the vector half-way in between the two vectors, and so on.
514                         Lerp(b, t) returns (1-t)*this + t*b. */
515         float2 Lerp(const float2 &b, float t) const;
516         /// This function is the same as calling a.Lerp(b, t).
517         static float2 Lerp(const float2 &a, const float2 &b, float t);
518
519         /// Makes the given vectors linearly independent.
520         /** This function directly follows the Gram-Schmidt procedure on the input vectors.
521                 The vector a is kept unmodified, and vector b is modified to be perpendicular to a.
522                 @note If any of the input vectors is zero, then the resulting set of vectors cannot be made orthogonal.
523                 @see AreOrthogonal(), Orthonormalize(), AreOrthonormal(). */
524         static void Orthogonalize(const float2 &a, float2 &b);
525
526         /// Returns true if the given vectors are orthogonal to each other.
527         /** @see Orthogonalize(), Orthonormalize(), AreOrthonormal(). */
528         static bool AreOrthogonal(const float2 &a, const float2 &b, float epsilon = 1e-3f);
529
530         /// Makes the given vectors linearly independent and normalized in length.
531         /** This function directly follows the Gram-Schmidt procedure on the input vectors.
532                 The vector a is first normalized, and vector b is modified to be perpendicular to a, and also normalized.
533                 @note If either of the input vectors is zero, then the resulting set of vectors cannot be made orthonormal.
534                 @see Orthogonalize(), AreOrthogonal(), AreOrthonormal(). */
535         static void Orthonormalize(float2 &a, float2 &b);
536
537         /// Tests if the triangle a->b->c is oriented counter-clockwise.
538         /** Returns true if the triangle a->b->c is oriented counter-clockwise, when viewed in the XY-plane
539                 where x spans to the right and y spans up.
540                 Another way to think of this is that this function returns true, if the point C lies to the left
541                 of the directed line AB. */
542         static bool OrientedCCW(const float2 &a, const float2 &b, const float2 &c);
543
544 #ifdef MATH_ENABLE_STL_SUPPORT
545         /// Computes the 2D convex hull of the given point set.
546         /* @see ConvexHullInPlace */
547         static void ConvexHull(const float2 *pointArray, int numPoints, std::vector<float2> &outConvexHull);
548
549         /// Computes the 2D convex hull of the given point set, in-place.
550         /** This version of the algorithm works in-place, meaning that when the algorithm finishes,
551                 pointArray will contain the list of the points on the convex hull.
552                 @note As a convention, the convex hull winds counter-clockwise when graphed in the xy plane where
553                         +x points to the right and +y points up. That is, walking along the polylist
554                         intArray[0] -> pointArray[1] -> pointArray[2] -> ... -> pointArray[numPoints-1] -> pointArray[0] performs
555                         a counter-clockwise tour.
556                 @param pointArray [in, out] A pointer to an array of numPoints float2 points that represent a point cloud. This
557                         array will be rewritten to contain the convex hull of the original point set.
558                 @return The number of points on the convex hull, i.e. the number of elements used in pointArray after the operation.
559                 @see ConvexHull(). */
560         static int ConvexHullInPlace(float2 *pointArray, int numPoints);
561
562         /// Tests whether a 2D convex hull contains the given point.
563         /** @param convexHull [in] A pointer to an array of points in the convex hull.
564                 @param numPointsInConvexHull The number of elements in the array convexHull.
565                 @param point The target point to test. */
566         static bool ConvexHullContains(const float2 *convexHull, int numPointsInConvexHull, const float2 &point);
567 #endif
568
569         /// Computes the minimum-area rectangle that bounds the given point set. [noscript]
570         /** Implementation adapted from Christer Ericson's Real-time Collision Detection, p.111.
571                 @param pointArray [in] A pointer to an array of points to process.
572                 @param numPoints The number of elements in the array pointed to by pointArray.
573                 @param center [out] This variable will receive the center point of the rectangle.
574                 @param uDir [out] This variable will receive a normalized direction vector pointing one of the side directionss of the rectangle.
575                 @param vDir [out] This variable will receive a normalized direction vector pointing the other side direction of the rectangle.
576                 @param minU [out] Receives the minimum extent of the processed point set along the u direction.
577                 @param maxU [out] Receives the maximum extent of the processed point set along the u direction.
578                 @param minV [out] Receives the minimum extent of the processed point set along the v direction.
579                 @param maxV [out] Receives the maximum extent of the processed point set along the v direction.
580                 @note This algorithm runs in O(n^2) time to the number of points in the input.
581                 @note For best performance, the input point array should contain only the points in the convex hull of the point set. This algorithm
582                         does not compute the convex hull for you.
583                 @return The area of the resulting rectangle. */
584         static float MinAreaRectInPlace(float2 *pointArray, int numPoints, float2 &center, float2 &uDir, float2 &vDir, float &minU, float &maxU, float &minV, float &maxV);
585
586         /// Generates a direction vector of the given length pointing at a uniformly random direction.
587         static float2 RandomDir(LCG &lcg, float length = 1.f);
588
589         /// Returns a random float3 with each entry randomized between the range [minElem, maxElem].
590         static MUST_USE_RESULT float2 RandomBox(LCG &lcg, float minElem, float maxElem);
591
592         /// Specifies a compile-time constant float2 with value (0, 0).
593         /** @note Due to static data initialization order being undefined in C++, do NOT use this
594                         member to initialize other static data in other compilation units! */
595         static const float2 zero;
596         /// Specifies a compile-time constant float2 with value (1, 1). [similarOverload: zero]
597         /** @note Due to static data initialization order being undefined in C++, do NOT use this
598                         member to initialize other static data in other compilation units! */
599         static const float2 one;
600         /// Specifies a compile-time constant float2 with value (1, 0).
601         /** @note Due to static data initialization order being undefined in C++, do NOT use this
602                         member to initialize other static data in other compilation units! */
603         static const float2 unitX;
604         /// Specifies a compile-time constant float2 with value (0, 1). [similarOverload: unitX]
605         /** @note Due to static data initialization order being undefined in C++, do NOT use this
606                         member to initialize other static data in other compilation units! */
607         static const float2 unitY;
608         /// A compile-time constant float2 with value (NaN, NaN).
609         /** For this constant, each element has the value of quiet NaN, or Not-A-Number.
610                 @note Never compare a float2 to this value! Due to how IEEE floats work, "nan == nan" returns false!
611                           That is, nothing is equal to NaN, not even NaN itself!
612                 @note Due to static data initialization order being undefined in C++, do NOT use this
613                         member to initialize other static data in other compilation units! */
614         static const float2 nan;
615         /// A compile-time constant float2 with value (+infinity, +infinity). [similarOverload: nan]
616         /** @note Due to static data initialization order being undefined in C++, do NOT use this
617                         member to initialize other static data in other compilation units! */
618         static const float2 inf;
619
620 #ifdef MATH_OGRE_INTEROP
621         float2(const Ogre::Vector2 &other):x(other.x), y(other.y) {}
622         operator Ogre::Vector2() const return Ogre::Vector2(xy); }
623 #endif
624 #ifdef MATH_QT_INTEROP
625         float2(const QVector2D &other):x(other.x()), y(other.y()) {}
626         operator QVector2D() const return QVector2D(xy); }
627         operator QString() const return "float2(" + QString::number(x) + "," + QString::number(y) + ")"; }
628         QString toString() const return (QString)*this; }
629         QVector2D ToQVector2D() const return QVector2D(xy); }
630         static float2 FromQVector2D(const QVector2D &v) { return (float2)v; }
631         static float2 FromString(const QString &str) { return FromString(str.toStdString()); }
632 #endif
633 #ifdef MATH_URHO3D_INTEROP
634         float2(const Urho3D::Vector2 &other) : x(other.x_), y(other.y_) {}
635         operator Urho3D::Vector2() const return Urho3D::Vector2(xy); }
636 #endif
637 };
638
639 #ifdef MATH_ENABLE_STL_SUPPORT
640 /// Prints this float2 to the given stream.
641 std::ostream &operator <<(std::ostream &out, const float2 &rhs);
642 #endif
643
644 float2 operator *(float scalar, const float2 &rhs);
645
646 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
647 inline float2 operator /(float scalar, const float2 &rhs) { return float2::FromScalar(scalar) / rhs; }
648 #endif
649
650 inline float Dot(const float2 &a, const float2 &b) { return a.Dot(b); }
651 inline float2 Abs(const float2 &a) { return a.Abs(); }
652 inline float Length(const float2 &a) { return a.Length(); }
653 inline float Distance(const float2 &a, const float2 &b) { return a.Distance(b); }
654 inline float2 Min(const float2 &a, const float2 &b) { return a.Min(b); }
655 inline float2 Max(const float2 &a, const float2 &b) { return a.Max(b); }
656 inline float2 Clamp(const float2 &a, float floor, float ceil) { return a.Clamp(floor, ceil); }
657 inline float2 Clamp(const float2 &a, const float2 &floor, const float2 &ceil) { return a.Clamp(floor, ceil); }
658 inline float2 Clamp01(const float2 &a) { return a.Clamp01(); }
659 inline float2 Lerp(const float2 &a, const float2 &b, float t) { return a.Lerp(b, t); }
660
661 #ifdef MATH_QT_INTEROP
662 Q_DECLARE_METATYPE(float2)
663 Q_DECLARE_METATYPE(float2*)
664 #endif
665
666 MATH_END_NAMESPACE

Go back to previous page