jaulib v1.3.0
Jau Support Library (C++, Java, ..)
vec2f.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#ifndef JAU_VEC2F_HPP_
25#define JAU_VEC2F_HPP_
26
27#include <cmath>
28#include <cstdarg>
29#include <cstdint>
30#include <cassert>
31#include <limits>
32#include <string>
33#include <iostream>
34
35#include <jau/float_math.hpp>
36
37namespace jau::math {
38
39 /** \addtogroup Math
40 *
41 * @{
42 */
43
44 /**
45 * 2D vector using two value_type components.
46 */
47 template<typename Value_type,
48 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> = true>
49 class alignas(Value_type) Vector2F {
50 public:
53 typedef const value_type* const_pointer;
57 typedef const value_type* const_iterator;
58
59 constexpr static const value_type zero = value_type(0);
60 constexpr static const value_type one = value_type(1);
61
62 /** Number of components */
63 constexpr static const size_t components = 2;
64
65 /** Size in bytes (aligned) */
66 constexpr static const size_t byte_size = components * sizeof(value_type);
67
70
71 static constexpr_cxx26 Vector2F from_length_angle(const value_type magnitude, const value_type radians) noexcept {
72 return Vector2F(magnitude * std::cos(radians), magnitude * std::sin(radians));
73 }
74
75 constexpr Vector2F() noexcept
76 : x(zero), y(zero) {}
77
78 constexpr Vector2F(const value_type v) noexcept
79 : x(v), y(v) {}
80
81 constexpr Vector2F(const value_type x_, const value_type y_) noexcept
82 : x(x_), y(y_) {}
83
84 constexpr Vector2F(const Vector2F& o) noexcept = default;
85 constexpr Vector2F(Vector2F&& o) noexcept = default;
86 constexpr Vector2F& operator=(const Vector2F&) noexcept = default;
87 constexpr Vector2F& operator=(Vector2F&&) noexcept = default;
88
89 /** Returns read-only component */
90 constexpr value_type operator[](size_t i) const noexcept {
91 assert(i < 2);
92 return (&x)[i];
93 }
94
95 explicit operator const_pointer() const noexcept { return &x; }
96 constexpr const_iterator cbegin() const noexcept { return &x; }
97
98 /** Returns writeable reference to component */
99 constexpr reference operator[](size_t i) noexcept {
100 assert(i < 2);
101 return (&x)[i];
102 }
103
104 explicit operator pointer() noexcept { return &x; }
105 constexpr iterator begin() noexcept { return &x; }
106
107 /** xy = this, returns xy. */
108 constexpr iterator get(iterator xy) const noexcept {
109 xy[0] = x;
110 xy[1] = y;
111 return xy;
112 }
113
114 constexpr bool operator==(const Vector2F& rhs ) const noexcept {
115 if( this == &rhs ) {
116 return true;
117 }
118 return jau::is_zero(x - rhs.x) && jau::is_zero(y - rhs.y);
119 }
120 /** TODO
121 constexpr bool operator<=>(const vec2f_t& rhs ) const noexcept {
122 return ...
123 } */
124
125 constexpr Vector2F& set(const value_type vx, const value_type vy) noexcept
126 { x=vx; y=vy; return *this; }
127
128 /** this = xy, returns this. */
129 constexpr Vector2F& set(const_iterator xy) noexcept
130 { x=xy[0]; y=xy[1]; return *this; }
131
132 /** this = this + {sx, sy}, returns this. */
133 constexpr Vector2F& add(const value_type dx, const value_type dy) noexcept
134 { x+=dx; y+=dy; return *this; }
135
136 /** this = this * {sx, sy}, returns this. */
137 constexpr Vector2F& mul(const value_type sx, const value_type sy) noexcept
138 { x*=sx; y*=sy; return *this; }
139
140 /** this = this * s, returns this. */
141 constexpr Vector2F& scale(const value_type s) noexcept
142 { x*=s; y*=s; return *this; }
143
144 /** this = this + rhs, returns this. */
145 constexpr Vector2F& operator+=(const Vector2F& rhs ) noexcept {
146 x+=rhs.x; y+=rhs.y;
147 return *this;
148 }
149
150 /** this = this - rhs, returns this. */
151 constexpr Vector2F& operator-=(const Vector2F& rhs ) noexcept {
152 x-=rhs.x; y-=rhs.y;
153 return *this;
154 }
155
156 /**
157 * Scale this vector with given scale factor
158 * @param s scale factor
159 * @return this instance
160 */
161 constexpr Vector2F& operator*=(const value_type s ) noexcept {
162 x*=s; y*=s;
163 return *this;
164 }
165
166 /**
167 * Divide this vector with given scale factor
168 * @param s scale factor
169 * @return this instance
170 */
171 constexpr Vector2F& operator/=(const value_type s ) noexcept {
172 x/=s; y/=s;
173 return *this;
174 }
175
176 /** Rotates this vector in place, returns *this */
177 constexpr_cxx26 Vector2F& rotate(const value_type radians, const Vector2F& ctr) noexcept {
178 return rotate(std::sin(radians), std::cos(radians), ctr);
179 }
180
181 /** Rotates this vector in place, returns *this */
182 constexpr Vector2F& rotate(const value_type sin, const value_type cos, const Vector2F& ctr) noexcept {
183 const value_type x0 = x - ctr.x;
184 const value_type y0 = y - ctr.y;
185 x = x0 * cos - y0 * sin + ctr.x;
186 y = x0 * sin + y0 * cos + ctr.y;
187 return *this;
188 }
189
190 /** Rotates this vector in place, returns *this */
191 constexpr_cxx26 Vector2F& rotate(const value_type radians) noexcept {
192 return rotate(std::sin(radians), std::cos(radians));
193 }
194
195 /** Rotates this vector in place, returns *this */
196 constexpr Vector2F& rotate(const value_type sin, const value_type cos) noexcept {
197 const value_type x0 = x;
198 x = x0 * cos - y * sin;
199 y = x0 * sin + y * cos;
200 return *this;
201 }
202
203 std::string toString() const noexcept { return std::to_string(x)+" / "+std::to_string(y); }
204
205 constexpr bool is_zero() const noexcept {
206 return jau::is_zero(x) && jau::is_zero(y);
207 }
208
209 /**
210 * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
211 */
212 constexpr value_type length_sq() const noexcept {
213 return x*x + y*y;
214 }
215
216 /**
217 * Return the length of this vector, a.k.a the <i>norm</i> or <i>magnitude</i>
218 */
219 constexpr value_type length() const noexcept {
220 return std::sqrt(length_sq());
221 }
222
223 /** Normalize this vector in place, returns *this */
224 constexpr Vector2F& normalize() noexcept {
225 const value_type lengthSq = length_sq();
226 if ( jau::is_zero( lengthSq ) ) {
227 x = zero;
228 y = zero;
229 } else {
230 const value_type invSqr = one / std::sqrt(lengthSq);
231 x *= invSqr;
232 y *= invSqr;
233 }
234 return *this;
235 }
236
237 /**
238 * Return the direction angle of this vector in radians
239 */
241 // Utilize atan2 taking y=sin(a) and x=cos(a), resulting in proper direction angle for all quadrants.
242 return std::atan2( y, x );
243 }
244
245 /**
246 * Return the squared distance between this vector and the given one.
247 * <p>
248 * When comparing the relative distance between two points it is usually sufficient to compare the squared
249 * distances, thus avoiding an expensive square root operation.
250 * </p>
251 */
252 constexpr value_type dist_sq(const Vector2F& o) const noexcept {
253 const value_type dx = x - o.x;
254 const value_type dy = y - o.y;
255 return dx*dx + dy*dy;
256 }
257
258 /**
259 * Return the distance between this vector and the given one.
260 */
261 constexpr value_type dist(const Vector2F& o) const noexcept {
262 return std::sqrt(dist_sq(o));
263 }
264
265 /**
266 * Return the dot product of this vector and the given one
267 * @return the dot product as value_type
268 */
269 constexpr value_type dot(const Vector2F& o) const noexcept {
270 return x*o.x + y*o.y;
271 }
272
273 /**
274 * Returns cross product of this vectors and the given one, i.e. *this x o.
275 *
276 * The 2D cross product is identical with the 2D perp dot product.
277 *
278 * @return the resulting scalar
279 */
280 constexpr value_type cross(const Vector2F& o) const noexcept {
281 return x * o.y - y * o.x;
282 }
283
284 /**
285 * Return the cosines of the angle between two vectors
286 */
287 constexpr value_type cos_angle(const Vector2F& o) const noexcept {
288 return dot(o) / ( length() * o.length() ) ;
289 }
290
291 /**
292 * Return the angle between two vectors in radians
293 */
294 constexpr_cxx26 value_type angle(const Vector2F& o) const noexcept {
295 return std::acos( cos_angle(o) );
296 }
297
298 /**
299 * Return the counter-clock-wise (CCW) normal of this vector, i.e. perp(endicular) vector
300 */
301 constexpr Vector2F normal_ccw() const noexcept {
302 return Vector2F(-y, x);
303 }
304
305 constexpr_cxx23 bool intersects(const Vector2F& o) const noexcept {
306 const value_type eps = std::numeric_limits<value_type>::epsilon();
307 if( std::abs(x-o.x) >= eps || std::abs(y-o.y) >= eps ) {
308 return false;
309 }
310 return true;
311 }
312 };
313
314 template<typename T,
315 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
316 constexpr Vector2F<T> operator+(const Vector2F<T>& lhs, const Vector2F<T>& rhs ) noexcept {
317 // Returning a Vector2F<T> object from the returned reference of operator+=()
318 // may hinder copy-elision or "named return value optimization" (NRVO).
319 // return Vector2F<T>(lhs) += rhs;
320
321 // Returning named object allows copy-elision (NRVO),
322 // only one object is created 'on target'.
323 Vector2F<T> r(lhs); r += rhs; return r;
324 }
325
326 template<typename T,
327 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
328 constexpr Vector2F<T> operator-(const Vector2F<T>& lhs, const Vector2F<T>& rhs ) noexcept {
329 Vector2F<T> r(lhs); r -= rhs; return r;
330 }
331
332 template<typename T,
333 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
334 constexpr Vector2F<T> operator*(const Vector2F<T>& lhs, const T s ) noexcept {
335 Vector2F<T> r(lhs); r *= s; return r;
336 }
337
338 template<typename T,
339 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
340 constexpr Vector2F<T> operator*(const T s, const Vector2F<T>& rhs) noexcept {
341 Vector2F<T> r(rhs); r *= s; return r;
342 }
343
344 template<typename T,
345 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
346 constexpr Vector2F<T> operator/(const Vector2F<T>& lhs, const T s ) noexcept {
347 Vector2F<T> r(lhs); r /= s; return r;
348 }
349
350 template<typename T,
351 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
352 std::ostream& operator<<(std::ostream& out, const Vector2F<T>& v) noexcept {
353 return out << v.toString();
354 }
355
357 static_assert(alignof(float) == alignof(Vec2f));
358 static_assert(sizeof(float)*2 == sizeof(Vec2f));
359
360 /**
361 * Point2F alias of Vector2F
362 */
363 template<typename T,
364 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
366
368 static_assert(alignof(float) == alignof(Point2f));
369 static_assert(sizeof(float)*2 == sizeof(Point2f));
370
371 /**
372 * Simple compound denoting a ray.
373 * <p>
374 * A ray, also known as a half line, consists out of it's <i>origin</i>
375 * and <i>direction</i>. Hence it is bound to only the <i>origin</i> side,
376 * where the other end is +infinitive.
377 * <pre>
378 * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0
379 * </pre>
380 * </p>
381 */
382 template<typename T,
383 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
384 class alignas(T) Ray2F {
385 public:
386 /** Origin of Ray. */
388
389 /** Normalized direction vector of ray. */
391
392 std::string toString() const noexcept { return "Ray[orig "+orig.toString()+", dir "+dir.toString() +"]"; }
393 };
394
395 template<typename T,
396 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
397 std::ostream& operator<<(std::ostream& out, const Ray2F<T>& v) noexcept {
398 return out << v.toString();
399 }
400
402 static_assert(alignof(float) == alignof(Ray2f));
403 static_assert(sizeof(float)*4 == sizeof(Ray2f));
404
405 /**@}*/
406
407} // namespace jau::math
408
409#endif /* JAU_VEC2F_HPP_ */
Simple compound denoting a ray.
Definition: vec2f.hpp:384
std::string toString() const noexcept
Definition: vec2f.hpp:392
Vector2F< T > dir
Normalized direction vector of ray.
Definition: vec2f.hpp:390
Point2F< T > orig
Origin of Ray.
Definition: vec2f.hpp:387
2D vector using two value_type components.
Definition: vec2f.hpp:49
const value_type * const_pointer
Definition: vec2f.hpp:53
constexpr Vector2F & mul(const value_type sx, const value_type sy) noexcept
this = this * {sx, sy}, returns this.
Definition: vec2f.hpp:137
constexpr Vector2F & operator-=(const Vector2F &rhs) noexcept
this = this - rhs, returns this.
Definition: vec2f.hpp:151
value_type x
Definition: vec2f.hpp:68
constexpr Vector2F & normalize() noexcept
Normalize this vector in place, returns *this.
Definition: vec2f.hpp:224
constexpr Vector2F & set(const value_type vx, const value_type vy) noexcept
TODO constexpr bool operator<=>(const vec2f_t& rhs ) const noexcept { return ... }.
Definition: vec2f.hpp:125
constexpr iterator begin() noexcept
Definition: vec2f.hpp:105
constexpr Vector2F & add(const value_type dx, const value_type dy) noexcept
this = this + {sx, sy}, returns this.
Definition: vec2f.hpp:133
Value_type value_type
Definition: vec2f.hpp:51
constexpr Vector2F(Vector2F &&o) noexcept=default
constexpr_cxx26 Vector2F & rotate(const value_type radians, const Vector2F &ctr) noexcept
Rotates this vector in place, returns *this.
Definition: vec2f.hpp:177
constexpr value_type length_sq() const noexcept
Return the squared length of this vector, a.k.a the squared norm or squared magnitude
Definition: vec2f.hpp:212
constexpr Vector2F normal_ccw() const noexcept
Return the counter-clock-wise (CCW) normal of this vector, i.e.
Definition: vec2f.hpp:301
constexpr reference operator[](size_t i) noexcept
Returns writeable reference to component.
Definition: vec2f.hpp:99
constexpr value_type cross(const Vector2F &o) const noexcept
Returns cross product of this vectors and the given one, i.e.
Definition: vec2f.hpp:280
constexpr_cxx26 value_type angle() const noexcept
Return the direction angle of this vector in radians.
Definition: vec2f.hpp:240
constexpr iterator get(iterator xy) const noexcept
xy = this, returns xy.
Definition: vec2f.hpp:108
constexpr Vector2F(const value_type x_, const value_type y_) noexcept
Definition: vec2f.hpp:81
const value_type & const_reference
Definition: vec2f.hpp:55
std::string toString() const noexcept
Definition: vec2f.hpp:203
constexpr Vector2F & rotate(const value_type sin, const value_type cos, const Vector2F &ctr) noexcept
Rotates this vector in place, returns *this.
Definition: vec2f.hpp:182
constexpr Vector2F() noexcept
Definition: vec2f.hpp:75
constexpr Vector2F & scale(const value_type s) noexcept
this = this * s, returns this.
Definition: vec2f.hpp:141
constexpr Vector2F & operator/=(const value_type s) noexcept
Divide this vector with given scale factor.
Definition: vec2f.hpp:171
constexpr Vector2F & operator+=(const Vector2F &rhs) noexcept
this = this + rhs, returns this.
Definition: vec2f.hpp:145
value_type y
Definition: vec2f.hpp:69
constexpr value_type length() const noexcept
Return the length of this vector, a.k.a the norm or magnitude
Definition: vec2f.hpp:219
constexpr Vector2F & rotate(const value_type sin, const value_type cos) noexcept
Rotates this vector in place, returns *this.
Definition: vec2f.hpp:196
constexpr const_iterator cbegin() const noexcept
Definition: vec2f.hpp:96
constexpr_cxx23 bool intersects(const Vector2F &o) const noexcept
Definition: vec2f.hpp:305
constexpr Vector2F & operator*=(const value_type s) noexcept
Scale this vector with given scale factor.
Definition: vec2f.hpp:161
constexpr Vector2F & set(const_iterator xy) noexcept
this = xy, returns this.
Definition: vec2f.hpp:129
constexpr Vector2F & operator=(const Vector2F &) noexcept=default
const value_type * const_iterator
Definition: vec2f.hpp:57
constexpr bool operator==(const Vector2F &rhs) const noexcept
Definition: vec2f.hpp:114
constexpr value_type dot(const Vector2F &o) const noexcept
Return the dot product of this vector and the given one.
Definition: vec2f.hpp:269
constexpr Vector2F & operator=(Vector2F &&) noexcept=default
constexpr_cxx26 Vector2F & rotate(const value_type radians) noexcept
Rotates this vector in place, returns *this.
Definition: vec2f.hpp:191
constexpr_cxx26 value_type angle(const Vector2F &o) const noexcept
Return the angle between two vectors in radians.
Definition: vec2f.hpp:294
value_type & reference
Definition: vec2f.hpp:54
constexpr value_type cos_angle(const Vector2F &o) const noexcept
Return the cosines of the angle between two vectors.
Definition: vec2f.hpp:287
static constexpr_cxx26 Vector2F from_length_angle(const value_type magnitude, const value_type radians) noexcept
Definition: vec2f.hpp:71
constexpr value_type dist(const Vector2F &o) const noexcept
Return the distance between this vector and the given one.
Definition: vec2f.hpp:261
value_type * iterator
Definition: vec2f.hpp:56
value_type * pointer
Definition: vec2f.hpp:52
constexpr Vector2F(const value_type v) noexcept
Definition: vec2f.hpp:78
constexpr Vector2F(const Vector2F &o) noexcept=default
constexpr value_type dist_sq(const Vector2F &o) const noexcept
Return the squared distance between this vector and the given one.
Definition: vec2f.hpp:252
constexpr bool is_zero() const noexcept
Definition: vec2f.hpp:205
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
#define constexpr_cxx23
#define constexpr_cxx26
std::enable_if< std::is_floating_point_v< T >, bool >::type constexpr is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
Definition: float_math.hpp:255
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
Definition: base_math.hpp:155
constexpr Quaternion< T > operator-(const Quaternion< T > &lhs, const Quaternion< T > &rhs) noexcept
constexpr Vector2F< T > operator/(const Vector2F< T > &lhs, const T s) noexcept
Definition: vec2f.hpp:346
Vector2F< float > Vec2f
Definition: vec2f.hpp:356
constexpr Matrix4< T > operator*(const Matrix4< T > &lhs, const Matrix4< T > &rhs) noexcept
Definition: mat4f.hpp:1859
Point2F< float > Point2f
Definition: vec2f.hpp:367
Ray2F< float > Ray2f
Definition: vec2f.hpp:401
constexpr Quaternion< T > operator+(const Quaternion< T > &lhs, const Quaternion< T > &rhs) noexcept
std::ostream & operator<<(std::ostream &out, const Matrix4< T > &v) noexcept
Definition: mat4f.hpp:1877
constexpr const jau::fraction_i64 zero(0l, 1lu)
zero is 0/1
constexpr const jau::fraction_i64 one(1l, 1lu)
one is 10^0 or 1/1
uint8_t Value_type