jaulib v1.3.0
Jau Support Library (C++, Java, ..)
vec3f.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_VEC3F_HPP_
25#define JAU_VEC3F_HPP_
26
27#include <cmath>
28#include <cstdarg>
29#include <cstdint>
30#include <cassert>
31#include <limits>
32#include <string>
33#include <initializer_list>
34#include <iostream>
35
36#include <jau/float_math.hpp>
37#include <jau/math/vec2f.hpp>
38
39namespace jau::math {
40
41 /** \addtogroup Math
42 *
43 * @{
44 */
45
46 /**
47 * 3D vector using three value_type components.
48 */
49 template<typename Value_type,
50 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> = true>
51 class alignas(Value_type) Vector3F {
52 public:
55 typedef const value_type* const_pointer;
59 typedef const value_type* const_iterator;
60
62
63 constexpr static const value_type zero = value_type(0);
64 constexpr static const value_type one = value_type(1);
65
66 /** Number of components */
67 constexpr static const size_t components = 3;
68
69 /** Size in bytes (aligned) */
70 constexpr static const size_t byte_size = components * sizeof(value_type);
71
75
76 constexpr Vector3F() noexcept
77 : x(zero), y(zero), z(zero) {}
78
79 constexpr Vector3F(const value_type v) noexcept
80 : x(v), y(v), z(v) {}
81
82 constexpr Vector3F(const value_type x_, const value_type y_, const value_type z_) noexcept
83 : x(x_), y(y_), z(z_) {}
84
85 constexpr Vector3F(const Vec2& o2, const value_type z_) noexcept
86 : x(o2.x), y(o2.y), z(z_) {}
87
88 constexpr Vector3F(const_iterator v) noexcept
89 : x(v[0]), y(v[1]), z(v[2]) {}
90
91 constexpr Vector3F(std::initializer_list<value_type> v) noexcept
92 : x(v[0]), y(v[1]), z(v[2]) {}
93
94 constexpr Vector3F(const Vector3F& o) noexcept = default;
95 constexpr Vector3F(Vector3F&& o) noexcept = default;
96 constexpr Vector3F& operator=(const Vector3F&) noexcept = default;
97 constexpr Vector3F& operator=(Vector3F&&) noexcept = default;
98
99 /** Returns read-only component */
100 constexpr value_type operator[](size_t i) const noexcept {
101 assert(i < 3);
102 return (&x)[i];
103 }
104
105 explicit operator const_pointer() const noexcept { return &x; }
106 constexpr const_iterator cbegin() const noexcept { return &x; }
107
108 /** Returns writeable reference to component */
109 constexpr reference operator[](size_t i) noexcept {
110 assert(i < 3);
111 return (&x)[i];
112 }
113
114 explicit operator pointer() noexcept { return &x; }
115 constexpr iterator begin() noexcept { return &x; }
116
117 /** xyz = this, returns xyz. */
118 constexpr iterator get(iterator xyz) const noexcept {
119 xyz[0] = x;
120 xyz[1] = y;
121 xyz[2] = z;
122 return xyz;
123 }
124
125 constexpr bool equals(const Vector3F& o, const value_type epsilon=std::numeric_limits<value_type>::epsilon()) const noexcept {
126 if( this == &o ) {
127 return true;
128 } else {
129 return jau::equals(x, o.x, epsilon) &&
130 jau::equals(y, o.y, epsilon) &&
131 jau::equals(z, o.z, epsilon);
132 }
133 }
134 constexpr bool operator==(const Vector3F& rhs) const noexcept {
135 return equals(rhs);
136 }
137 /** TODO
138 constexpr bool operator<=>(const vec3f_t& rhs ) const noexcept {
139 return ...
140 } */
141
142 /** this = { o, z }, returns this. */
143 constexpr Vector3F& set(const Vec2f& o, const value_type z_) noexcept {
144 x = o.x;
145 y = o.y;
146 z = z_;
147 return *this;
148 }
149
150 constexpr Vector3F& set(const value_type vx, const value_type vy, const value_type vz) noexcept
151 { x=vx; y=vy; z=vz; return *this; }
152
153 /** this = xyz, returns this. */
154 constexpr Vector3F& set(const_iterator xyz) noexcept
155 { x=xyz[0]; y=xyz[1]; z=xyz[2]; return *this; }
156
157 /** this = this + {dx, dy, dz}, returns this. */
158 constexpr Vector3F& add(const value_type dx, const value_type dy, const value_type dz) noexcept
159 { x+=dx; y+=dy; z+=dz; return *this; }
160
161 /** this = this * {sx, sy, sz}, returns this. */
162 constexpr Vector3F& mul(const value_type sx, const value_type sy, const value_type sz) noexcept
163 { x*=sx; y*=sy; z*=sz; return *this; }
164
165 /** this = this * s, returns this. */
166 constexpr Vector3F& scale(const value_type s) noexcept
167 { x*=s; y*=s; z*=s; return *this; }
168
169 /** this = this + rhs, returns this. */
170 constexpr Vector3F& operator+=(const Vector3F& rhs ) noexcept {
171 x+=rhs.x; y+=rhs.y; z+=rhs.z;
172 return *this;
173 }
174
175 /** this = this - rhs, returns this. */
176 constexpr Vector3F& operator-=(const Vector3F& rhs ) noexcept {
177 x-=rhs.x; y-=rhs.y; z-=rhs.z;
178 return *this;
179 }
180
181 /**
182 * Scale this vector with given scale factor
183 * @param s scale factor
184 * @return this instance
185 */
186 constexpr Vector3F& operator*=(const value_type s ) noexcept {
187 x*=s; y*=s; z*=s;
188 return *this;
189 }
190
191 /**
192 * Divide this vector with given scale factor
193 * @param s scale factor
194 * @return this instance
195 */
196 constexpr Vector3F& operator/=(const value_type s ) noexcept {
197 x/=s; y/=s; z/=s;
198 return *this;
199 }
200
201 /** Rotates this vector around the Z-axis in place, returns *this */
202 constexpr_cxx26 Vector3F& rotateZ(const value_type radians) noexcept {
203 return rotateZ(std::sin(radians), std::cos(radians));
204 }
205
206 /** Rotates this vector in place, returns *this */
207 constexpr Vector3F& rotateZ(const value_type sin, const value_type cos) noexcept {
208 const value_type x0 = x;
209 x = x0 * cos - y * sin;
210 y = x0 * sin + y * cos;
211 return *this;
212 }
213
214 std::string toString() const noexcept { return std::to_string(x)+" / "+std::to_string(y)+" / "+std::to_string(z); }
215
216 constexpr bool is_zero() const noexcept {
217 return jau::is_zero(x) && jau::is_zero(y) && jau::is_zero(z);
218 }
219
220 /**
221 * Return the squared length of a vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
222 */
223 constexpr value_type length_sq() const noexcept {
224 return x*x + y*y + z*z;
225 }
226
227 /**
228 * Return the length of a vector, a.k.a the <i>norm</i> or <i>magnitude</i>
229 */
230 constexpr value_type length() const noexcept {
231 return std::sqrt(length_sq());
232 }
233
234 /**
235 * Normalize this vector in place
236 */
237 constexpr Vector3F& normalize() noexcept {
238 const value_type lengthSq = length_sq();
239 if ( jau::is_zero( lengthSq ) ) {
240 x = zero;
241 y = zero;
242 z = zero;
243 } else {
244 const value_type invSqr = one / std::sqrt(lengthSq);
245 x *= invSqr;
246 y *= invSqr;
247 z *= invSqr;
248 }
249 return *this;
250 }
251
252 /**
253 * Return the squared distance between this vector and the given one.
254 * <p>
255 * When comparing the relative distance between two points it is usually sufficient to compare the squared
256 * distances, thus avoiding an expensive square root operation.
257 * </p>
258 */
259 constexpr value_type dist_sq(const Vector3F& o) const noexcept {
260 const value_type dx = x - o.x;
261 const value_type dy = y - o.y;
262 const value_type dz = z - o.z;
263 return dx*dx + dy*dy + dz*dz;
264 }
265
266 /**
267 * Return the distance between this vector and the given one.
268 */
269 constexpr value_type dist(const Vector3F& o) const noexcept {
270 return std::sqrt(dist_sq(o));
271 }
272
273 /**
274 * Return the dot product of this vector and the given one
275 * @return the dot product as value_type
276 */
277 constexpr value_type dot(const Vector3F& o) const noexcept {
278 return x*o.x + y*o.y + z*o.z;
279 }
280
281 /**
282 * cross product this x b
283 * @return new resulting vector
284 */
285 constexpr Vector3F cross(const Vector3F& b) const noexcept {
286 return Vector3F( y * b.z - z * b.y,
287 z * b.x - x * b.z,
288 x * b.y - y * b.x);
289 }
290
291 /**
292 * cross product this = a x b, with a, b different from this
293 * @return this for chaining
294 */
295 constexpr Vector3F& cross(const Vector3F& a, const Vector3F& b) noexcept {
296 x = a.y * b.z - a.z * b.y;
297 y = a.z * b.x - a.x * b.z;
298 z = a.x * b.y - a.y * b.x;
299 return *this;
300 }
301
302 /**
303 * Return the cosines of the angle between to vectors
304 * @param vec1 vector 1
305 * @param vec2 vector 2
306 */
307 constexpr value_type cos_angle(const Vector3F& o) const noexcept {
308 return dot(o) / ( length() * o.length() ) ;
309 }
310
311 /**
312 * Return the angle between to vectors in radians
313 * @param vec1 vector 1
314 * @param vec2 vector 2
315 */
316 constexpr_cxx26 value_type angle(const Vector3F& o) const noexcept {
317 return std::acos( cos_angle(o) );
318 }
319
320 constexpr_cxx23 bool intersects(const Vector3F& o) const noexcept {
321 const value_type eps = std::numeric_limits<value_type>::epsilon();
322 if( std::abs(x-o.x) >= eps || std::abs(y-o.y) >= eps || std::abs(z-o.z) >= eps ) {
323 return false;
324 }
325 return true;
326 }
327 };
328
329 template<typename T,
330 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
331 constexpr Vector3F<T> operator+(const Vector3F<T>& lhs, const Vector3F<T>& rhs ) noexcept {
332 // Returning a Vector3 object from the returned reference of operator+=()
333 // may hinder copy-elision or "named return value optimization" (NRVO).
334 // return Vector3<T>(lhs) += rhs;
335
336 // Returning named object allows copy-elision (NRVO),
337 // only one object is created 'on target'.
338 Vector3F<T> r(lhs); r += rhs; return r;
339 }
340
341 template<typename T,
342 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
343 constexpr Vector3F<T> operator-(const Vector3F<T>& lhs, const Vector3F<T>& rhs ) noexcept {
344 Vector3F<T> r(lhs); r -= rhs; return r;
345 }
346
347 template<typename T,
348 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
349 constexpr Vector3F<T> operator*(const Vector3F<T>& lhs, const T s ) noexcept {
350 Vector3F<T> r(lhs); r *= s; return r;
351 }
352
353 template<typename T,
354 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
355 constexpr Vector3F<T> operator*(const T s, const Vector3F<T>& rhs) noexcept {
356 Vector3F<T> r(rhs); r *= s; return r;
357 }
358
359 template<typename T,
360 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
361 constexpr Vector3F<T> operator/(const Vector3F<T>& lhs, const T s ) noexcept {
362 Vector3F<T> r(lhs); r /= s; return r;
363 }
364
365 template<typename T,
366 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
367 std::ostream& operator<<(std::ostream& out, const Vector3F<T>& v) noexcept {
368 return out << v.toString();
369 }
370
372 static_assert(alignof(float) == alignof(Vec3f));
373 static_assert(sizeof(float)*3 == sizeof(Vec3f));
374
375 /**
376 * Point3F alias of Vector3F
377 */
378 template<typename T,
379 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
381
383 static_assert(alignof(float) == alignof(Point3f));
384 static_assert(sizeof(float)*3 == sizeof(Point3f));
385
386 /**
387 * Simple compound denoting a ray.
388 * <p>
389 * A ray, also known as a half line, consists out of it's <i>origin</i>
390 * and <i>direction</i>. Hence it is bound to only the <i>origin</i> side,
391 * where the other end is +infinitive.
392 * <pre>
393 * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0
394 * </pre>
395 * </p>
396 */
397 template<typename T,
398 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
399 struct alignas(T) Ray3F {
400 /** Origin of Ray. */
402
403 /** Normalized direction vector of ray. */
405
406 std::string toString() const noexcept { return "Ray[orig "+orig.toString()+", dir "+dir.toString() +"]"; }
407 };
408
409 template<typename T,
410 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
411 std::ostream& operator<<(std::ostream& out, const Ray3F<T>& v) noexcept {
412 return out << v.toString();
413 }
414
416 static_assert(alignof(float) == alignof(Ray3f));
417 static_assert(sizeof(float)*6 == sizeof(Ray3f));
418
419 /**@}*/
420
421} // namespace jau::math
422
423#endif /* JAU_VEC3F_HPP_ */
2D vector using two value_type components.
Definition: vec2f.hpp:49
3D vector using three value_type components.
Definition: vec3f.hpp:51
constexpr Vector3F(const value_type v) noexcept
Definition: vec3f.hpp:79
constexpr reference operator[](size_t i) noexcept
Returns writeable reference to component
Definition: vec3f.hpp:109
constexpr Vector3F & cross(const Vector3F &a, const Vector3F &b) noexcept
cross product this = a x b, with a, b different from this
Definition: vec3f.hpp:295
value_type * pointer
Definition: vec3f.hpp:54
constexpr Vector3F() noexcept
Definition: vec3f.hpp:76
constexpr_cxx26 Vector3F & rotateZ(const value_type radians) noexcept
Rotates this vector around the Z-axis in place, returns *this.
Definition: vec3f.hpp:202
constexpr Vector3F & set(const Vec2f &o, const value_type z_) noexcept
TODO constexpr bool operator<=>(const vec3f_t& rhs ) const noexcept { return ... }.
Definition: vec3f.hpp:143
const value_type & const_reference
Definition: vec3f.hpp:57
constexpr bool operator==(const Vector3F &rhs) const noexcept
Definition: vec3f.hpp:134
constexpr Vector3F & operator/=(const value_type s) noexcept
Divide this vector with given scale factor.
Definition: vec3f.hpp:196
value_type x
Definition: vec3f.hpp:72
constexpr_cxx26 value_type angle(const Vector3F &o) const noexcept
Return the angle between to vectors in radians.
Definition: vec3f.hpp:316
constexpr Vector3F & operator=(const Vector3F &) noexcept=default
constexpr value_type cos_angle(const Vector3F &o) const noexcept
Return the cosines of the angle between to vectors.
Definition: vec3f.hpp:307
constexpr Vector3F & normalize() noexcept
Normalize this vector in place.
Definition: vec3f.hpp:237
const value_type * const_pointer
Definition: vec3f.hpp:55
constexpr Vector3F & operator=(Vector3F &&) noexcept=default
Vector2F< value_type, std::is_floating_point_v< Value_type > > Vec2
Definition: vec3f.hpp:61
value_type * iterator
Definition: vec3f.hpp:58
constexpr Vector3F(const_iterator v) noexcept
Definition: vec3f.hpp:88
constexpr Vector3F & operator-=(const Vector3F &rhs) noexcept
this = this - rhs, returns this.
Definition: vec3f.hpp:176
constexpr_cxx23 bool intersects(const Vector3F &o) const noexcept
Definition: vec3f.hpp:320
constexpr iterator get(iterator xyz) const noexcept
xyz = this, returns xyz.
Definition: vec3f.hpp:118
constexpr Vector3F & set(const value_type vx, const value_type vy, const value_type vz) noexcept
Definition: vec3f.hpp:150
constexpr value_type length() const noexcept
Return the length of a vector, a.k.a the norm or magnitude
Definition: vec3f.hpp:230
Value_type value_type
Definition: vec3f.hpp:53
constexpr Vector3F & scale(const value_type s) noexcept
this = this * s, returns this.
Definition: vec3f.hpp:166
constexpr value_type dist(const Vector3F &o) const noexcept
Return the distance between this vector and the given one.
Definition: vec3f.hpp:269
constexpr Vector3F & mul(const value_type sx, const value_type sy, const value_type sz) noexcept
this = this * {sx, sy, sz}, returns this.
Definition: vec3f.hpp:162
constexpr Vector3F & rotateZ(const value_type sin, const value_type cos) noexcept
Rotates this vector in place, returns *this.
Definition: vec3f.hpp:207
constexpr Vector3F & operator+=(const Vector3F &rhs) noexcept
this = this + rhs, returns this.
Definition: vec3f.hpp:170
constexpr value_type dist_sq(const Vector3F &o) const noexcept
Return the squared distance between this vector and the given one.
Definition: vec3f.hpp:259
constexpr Vector3F(std::initializer_list< value_type > v) noexcept
Definition: vec3f.hpp:91
constexpr Vector3F(const Vec2 &o2, const value_type z_) noexcept
Definition: vec3f.hpp:85
constexpr Vector3F & add(const value_type dx, const value_type dy, const value_type dz) noexcept
this = this + {dx, dy, dz}, returns this.
Definition: vec3f.hpp:158
constexpr const_iterator cbegin() const noexcept
Definition: vec3f.hpp:106
constexpr bool is_zero() const noexcept
Definition: vec3f.hpp:216
constexpr value_type dot(const Vector3F &o) const noexcept
Return the dot product of this vector and the given one.
Definition: vec3f.hpp:277
constexpr value_type length_sq() const noexcept
Return the squared length of a vector, a.k.a the squared norm or squared magnitude
Definition: vec3f.hpp:223
constexpr Vector3F(const Vector3F &o) noexcept=default
constexpr Vector3F cross(const Vector3F &b) const noexcept
cross product this x b
Definition: vec3f.hpp:285
constexpr Vector3F & set(const_iterator xyz) noexcept
this = xyz, returns this.
Definition: vec3f.hpp:154
const value_type * const_iterator
Definition: vec3f.hpp:59
constexpr Vector3F(const value_type x_, const value_type y_, const value_type z_) noexcept
Definition: vec3f.hpp:82
value_type & reference
Definition: vec3f.hpp:56
constexpr Vector3F & operator*=(const value_type s) noexcept
Scale this vector with given scale factor.
Definition: vec3f.hpp:186
constexpr Vector3F(Vector3F &&o) noexcept=default
value_type y
Definition: vec3f.hpp:73
constexpr iterator begin() noexcept
Definition: vec3f.hpp:115
std::string toString() const noexcept
Definition: vec3f.hpp:214
constexpr bool equals(const Vector3F &o, const value_type epsilon=std::numeric_limits< value_type >::epsilon()) const noexcept
Definition: vec3f.hpp:125
value_type z
Definition: vec3f.hpp:74
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
std::enable_if< std::is_floating_point_v< T >, bool >::type constexpr equals(const T &a, const T &b, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if both values are equal, i.e.
Definition: float_math.hpp:394
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
Ray3F< float > Ray3f
Definition: vec3f.hpp:415
constexpr Matrix4< T > operator*(const Matrix4< T > &lhs, const Matrix4< T > &rhs) noexcept
Definition: mat4f.hpp:1859
Vector3F< float > Vec3f
Definition: vec3f.hpp:371
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
Point3F< float > Point3f
Definition: vec3f.hpp:382
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
Simple compound denoting a ray.
Definition: vec3f.hpp:399
Point3F< T > orig
Origin of Ray.
Definition: vec3f.hpp:401
std::string toString() const noexcept
Definition: vec3f.hpp:406
Vector3F< T > dir
Normalized direction vector of ray.
Definition: vec3f.hpp:404
uint8_t Value_type