LibCarna Version 3.4.0
Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 - 2016 Leonid Kostrykin
3 *
4 * Chair of Medical Engineering (mediTEC)
5 * RWTH Aachen University
6 * Pauwelsstr. 20
7 * 52074 Aachen
8 * Germany
9 *
10 *
11 * Copyright (C) 2021 - 2025 Leonid Kostrykin
12 *
13 */
14
15#ifndef MATH_H_6014714286
16#define MATH_H_6014714286
17
18#include <LibCarna/LibCarna.hpp>
20#include <algorithm>
21#include <type_traits>
22#include <cmath>
23#include <Eigen/Dense>
24
25#ifdef min
26#error MIN macro defined, define NOMINMAX first!
27#endif
28
29#ifdef max
30#error MAX macro defined, define NOMINMAX first!
31#endif
32
35#ifndef NOMINMAX
36#define NOMINMAX
37#endif
50namespace LibCarna
51{
52
53namespace base
54{
55
56namespace math
57{
58
67 template< typename T >
68 T clamp( T val, T my_min, T my_max )
69 {
70 return std::min( std::max( val, my_min ), my_max );
71 }
72
76 template< typename T >
77 T sq( T x )
78 {
79 return x * x;
80 }
81
85 inline float deg2rad( float deg )
86 {
87 return deg * 3.1415926f / 180.f;
88 }
89
93 inline float rad2deg( float rad )
94 {
95 return 180.f * rad / 3.1415926f;
96 }
97
101 template< typename T >
103 {
104 return static_cast< T >( 0 );
105 }
106
111 template< >
112 inline float epsilon< float >()
113 {
114 return 1e-4f;
115 }
116
121 template< >
122 inline double epsilon< double >()
123 {
124 return 1e-6;
125 }
126
131 template< typename T >
133 {
137 typedef T type;
138 };
139
144 template< typename VectorElementType, int rows, int cols >
145 struct element_type_of< Eigen::Matrix< VectorElementType, rows, cols > >
146 {
151
152 };
153
158 template< typename T >
159 T length2( const T& x )
160 {
161 return x * x;
162 }
163
168 template< typename VectorElementType, int dimension >
169 VectorElementType length2( const Eigen::Matrix< VectorElementType, dimension, 1 >& x )
170 {
171 return x.squaredNorm();
172 }
173
177 template< typename InputType >
178 bool isEqual( const InputType& x, const InputType& y )
179 {
181 const InputType difference = x - y;
184 return distance2 <= _epsilon;
185 }
186
191 template< >
192 inline bool isEqual( const bool& x, const bool& y )
193 {
194 return x == y;
195 }
196
197 typedef Eigen::Matrix< float, 4, 4, Eigen::ColMajor > Matrix4f;
198 typedef Eigen::Matrix< float, 3, 3, Eigen::ColMajor > Matrix3f;
199 typedef Eigen::Matrix< float, 4, 1 > Vector4f;
200 typedef Eigen::Matrix< float, 3, 1 > Vector3f;
201 typedef Eigen::Matrix< float, 2, 1 > Vector2f;
202 typedef Eigen::Matrix< signed int, 3, 1 > Vector3i;
203 typedef Eigen::Matrix< unsigned int, 3, 1 > Vector3ui;
204 typedef Eigen::Matrix< unsigned int, 2, 1 > Vector2ui;
205
210 {
211 Matrix4f result;
212 result.setIdentity();
213 return result;
214 }
215
220 {
221 Matrix3f result;
222 result.setIdentity();
223 return result;
224 }
225
229 template< typename MatrixType >
231 {
232 MatrixType result;
233 result.setZero();
234 return result;
235 }
236
246 inline Matrix4f basis4f( const Vector4f& x, const Vector4f& y, const Vector4f& z, const Vector4f& t = Vector4f( 0, 0, 0, 0 ) )
247 {
248 Matrix4f result;
249 result.col( 0 ) = x;
250 result.col( 1 ) = y;
251 result.col( 2 ) = z;
252 result.col( 3 ) = t;
253 for( unsigned int i = 0; i < 3; ++i )
254 {
255 result( 3, i ) = 0;
256 }
257 result( 3, 3 ) = 1;
258 return result;
259 }
260
263 inline Matrix4f basis4f( const Vector3f& x, const Vector3f& y, const Vector3f& z, const Vector3f& t = Vector3f( 0, 0, 0 ) )
264 {
265 const Vector4f x4( x.x(), x.y(), x.z(), 0 );
266 const Vector4f y4( y.x(), y.y(), y.z(), 0 );
267 const Vector4f z4( z.x(), z.y(), z.z(), 0 );
268 const Vector4f t4( t.x(), t.y(), t.z(), 0 );
269 return basis4f( x4, y4, z4, t4 );
270 }
271
275 inline Matrix4f translation4f( float x, float y, float z )
276 {
277 Matrix4f result;
278 result.setIdentity();
279 result( 0, 3 ) = x;
280 result( 1, 3 ) = y;
281 result( 2, 3 ) = z;
282 return result;
283 }
284
287 template< typename Vector >
288 Matrix4f translation4f( const Vector& v )
289 {
290 return translation4f( v.x(), v.y(), v.z() );
291 }
292
296 inline Matrix4f scaling4f( float x, float y, float z )
297 {
298 Matrix4f result;
299 result.setIdentity();
300 result( 0, 0 ) = x;
301 result( 1, 1 ) = y;
302 result( 2, 2 ) = z;
303 return result;
304 }
305
308 template< typename VectorElementType >
309 inline Matrix4f scaling4f( const Eigen::Matrix< VectorElementType, 3, 1 >& v )
310 {
311 return scaling4f( v.x(), v.y(), v.z() );
312 }
313
320
326 inline Matrix4f rotation4f( float x, float y, float z, float radians )
327 {
328 const float c = std::cos( radians );
329 const float s = std::sin( radians );
330
331 Matrix4f result;
332 result.setIdentity();
333
334 result( 0, 0 ) = x * x * ( 1 - c ) + c;
335 result( 1, 0 ) = y * x * ( 1 - c ) + z * s;
336 result( 2, 0 ) = x * z * ( 1 - c ) - y * s;
337
338 result( 0, 1 ) = x * y * ( 1 - c ) - z * s;
339 result( 1, 1 ) = y * y * ( 1 - c ) + c;
340 result( 2, 1 ) = y * z * ( 1 - c ) + x * s;
341
342 result( 0, 2 ) = x * z * ( 1 - c ) + y * s;
343 result( 1, 2 ) = y * z * ( 1 - c ) - x * s;
344 result( 2, 2 ) = z * z * ( 1 - c ) + c;
345
346 return result;
347 }
348
351 template< typename Vector >
352 Matrix4f rotation4f( const Vector& v, float radians )
353 {
354 return rotation4f( v.x(), v.y(), v.z(), radians );
355 }
356
361 inline Matrix3f rotation3f( float x, float y, float z, float radians )
362 {
363 return rotation4f( x, y, z, radians ).block< 3, 3 >( 0, 0 );
364 }
365
371 inline Vector3f orthogonal3f( const Vector3f& in )
372 {
373 Vector3f out;
374 if( std::abs( in.x() - in.y() ) > 1e-4f )
375 {
376 out.x() = in.y();
377 out.y() = in.x();
378 out.z() = 0;
379
380 if( std::abs( out.x() ) > std::abs( out.y() ) )
381 {
382 out.x() = -out.x();
383 }
384 else
385 {
386 out.y() = -out.y();
387 }
388 }
389 else
390 if( std::abs( in.x() - in.z() ) > 1e-4f )
391 {
392 out.x() = in.z();
393 out.y() = 0;
394 out.z() = in.x();
395
396 if( std::abs( out.x() ) > std::abs( out.z() ) )
397 {
398 out.x() = -out.x();
399 }
400 else
401 {
402 out.z() = -out.z();
403 }
404 }
405 else
406 if( std::abs( in.y() - in.z() ) > 1e-4f )
407 {
408 out.x() = 0;
409 out.y() = in.z();
410 out.z() = in.x();
411
412 if( std::abs( out.y() ) > std::abs( out.z() ) )
413 {
414 out.y() = -out.y();
415 }
416 else
417 {
418 out.z() = -out.z();
419 }
420 }
421 else // all components are equal
422 {
423 out = Vector3f( -in.x(), in.y(), 0 );
424 }
425
429 LIBCARNA_ASSERT( isEqual< float >( in.dot( out ), 0 ) );
430 return out;
431 }
432
437 template< typename VectorElementType, int rows, typename WType >
438 Eigen::Matrix< VectorElementType, 4, 1 > vector4( const Eigen::Matrix< VectorElementType, rows, 1 >& v, WType w )
439 {
440 static_assert( rows >= 3, "math::vector4 requires input vector with 3 rows or more." );
441 return Eigen::Matrix< VectorElementType, 4, 1 >( v.x(), v.y(), v.z(), static_cast< VectorElementType >( w ) );
442 }
443
448 template< typename VectorElementType, int rows >
449 Eigen::Matrix< VectorElementType, 3, 1 > vector3( const Eigen::Matrix< VectorElementType, rows, 1 >& v )
450 {
451 static_assert( rows >= 3, "math::vector3 requires input vector with 3 rows or more." );
452 return Eigen::Matrix< VectorElementType, 3, 1 >( v.x(), v.y(), v.z() );
453 }
454
460 inline Matrix4f plane4f( const Vector3f& normal, float distance )
461 {
464 const Vector3f bitangent( normal.cross( tangent ).normalized() );
466 return basis4f
467 ( vector4( bitangent, 0 )
468 , vector4( tangent, 0 )
469 , vector4( normal, 0 )
470 , vector4( translation, 1 ) );
471 }
472
476 {
478 const float distance = normal.dot( support );
479 return plane4f( normal, distance );
480 }
481
486 inline float translationDistance2( const Matrix4f& m )
487 {
488 return m( 0, 3 ) * m( 0, 3 ) + m( 1, 3 ) * m( 1, 3 ) + m( 2, 3 ) * m( 2, 3 );
489 }
490
494 template< typename Matrix >
495 typename Matrix::Scalar maxAbsElement( const Matrix& m )
496 {
497 const std::size_t length = m.rows() * m.cols();
498 typename Matrix::Scalar maxAbs = 0;
499 for( std::size_t i = 0; i < length; ++i )
500 {
501 maxAbs = std::max( maxAbs, std::abs( m.data()[ i ] ) );
502 }
503 return maxAbs;
504 }
505
520 inline Matrix4f frustum4f( float left, float right, float bottom, float top, float zNear, float zFar )
521 {
522 Matrix4f result;
523 result.setZero();
524
525 result( 0, 0 ) = +2 * zNear / ( right - left );
526 result( 1, 1 ) = +2 * zNear / ( top - bottom );
527 result( 0, 2 ) = ( right + left ) / ( right - left );
528 result( 1, 2 ) = ( top + bottom ) / ( top - bottom );
529 result( 2, 2 ) = -( zFar + zNear ) / ( zFar - zNear );
530 result( 3, 2 ) = -1;
531 result( 2, 3 ) = -2 * zFar * zNear / ( zFar - zNear );
532
533 return result;
534 }
535
557
561 inline Matrix4f ortho4f( float left, float right, float bottom, float top, float zNear, float zFar )
562 {
563 Matrix4f result;
564 result.setZero();
565
566 result( 0, 0 ) = 2 / ( right - left );
567 result( 1, 1 ) = 2 / ( top - bottom );
568 result( 2, 2 ) = -2 / ( zFar - zNear );
569 result( 0, 3 ) = -( right + left ) / ( right - left );
570 result( 1, 3 ) = -( top + bottom ) / ( bottom - top );
571 result( 2, 3 ) = -( zFar + zNear ) / ( zFar - zNear );
572 result( 3, 3 ) = +1;
573
574 return result;
575 }
576
580 template< typename Sampler >
582 {
583 const float val_0yz = func( -1, 0, 0 );
584 const float val_1yz = func( +1, 0, 0 );
585 const float val_x0z = func( 0, -1, 0 );
586 const float val_x1z = func( 0, +1, 0 );
587 const float val_xy0 = func( 0, 0, -1 );
588 const float val_xy1 = func( 0, 0, +1 );
589
591 }
592
597 template< typename ScalarType >
598 unsigned int round_ui( ScalarType x )
599 {
600 LIBCARNA_ASSERT( !std::numeric_limits< ScalarType >::is_signed || x >= 0 );
601 return static_cast< unsigned int >( x + static_cast< ScalarType >( 0.5 ) );
602 }
603
608 template< typename MatrixElementType, int cols, int rows >
609 Eigen::Matrix< unsigned int, cols, rows > round_ui( const Eigen::Matrix< MatrixElementType, cols, rows >& m )
610 {
611 Eigen::Matrix< unsigned int, cols, rows > result;
612 for( int i = 0; i < cols; ++i )
613 for( int j = 0; j < rows; ++j )
614 {
615 result( i, j ) = round_ui( m( i, j ) );
616 }
617 return result;
618 }
619
624 template< typename ScalarType >
626 {
627 LIBCARNA_ASSERT( s == +1 || s == -1 );
628 static_assert( std::is_integral< ScalarType >::value, "Only integral data types allowed." );
629 return x + s * ( x % 2 );
630 }
631
637 template< typename MatrixElementType, int cols, int rows >
638 Eigen::Matrix< MatrixElementType, cols, rows > makeEven( const Eigen::Matrix< MatrixElementType, cols, rows >& m, int s )
639 {
640 Eigen::Matrix< unsigned int, cols, rows > result;
641 for( int i = 0; i < cols; ++i )
642 for( int j = 0; j < rows; ++j )
643 {
644 result( i, j ) = makeEven( m( i, j ), s );
645 }
646 return result;
647 }
648
652 template< typename T >
654 {
657
662 {
663 }
664
668 Statistics( std::size_t size, const std::function< T( std::size_t ) > values )
669 {
670 if( size == 0 )
671 {
672 mean = variance = 0;
673 }
674 else
675 {
676 /* Compute mean.
677 */
678 T sum = 0;
679 for( std::size_t idx = 0; idx < size; ++idx )
680 {
681 sum += values( idx );
682 }
683 mean = sum / size;
684
685 /* Compute variance.
686 */
687 sum = 0;
688 for( std::size_t idx = 0; idx < size; ++idx )
689 {
690 sum += sq( mean - values( idx ) );
691 }
692 variance = sum / ( size - 1 );
693 }
694 }
695
700 {
701 mean = other.mean;
702 variance = other.variance;
703 return *this;
704 }
705
710 {
711 return std::sqrt( variance );
712 }
713 };
714
718 template< typename ResultType, typename SupportType >
719 ResultType mix( const SupportType& a, const SupportType& b, float t )
720 {
721 return a * ( 1 - t ) + b * t;
722 }
723
724
725
731#define LIBCARNA_FOR_VECTOR3UI_EX( vecName, vecLimit, vecStart ) \
732 LibCarna::base::math::Vector3ui vecName; \
733 for( vecName.z() = vecStart.x(); vecName.z() < vecLimit.z(); ++vecName.z() ) \
734 for( vecName.y() = vecStart.y(); vecName.y() < vecLimit.y(); ++vecName.y() ) \
735 for( vecName.x() = vecStart.z(); vecName.x() < vecLimit.x(); ++vecName.x() )
736
737
738
745#define LIBCARNA_FOR_VECTOR3UI( vecName, vecLimit ) \
746 LIBCARNA_FOR_VECTOR3UI_EX( vecName, vecLimit, LibCarna::base::math::Vector3ui( 0, 0, 0 ) )
747
748
749
750} // namespace LibCarna :: base :: math
751
752} // namespace LibCarna :: base
753
754} // namespace LibCarna
755
756
757
758#endif // MATH_H_6014714286
Defines LibCarna::base::LibCarnaException and LibCarna::base::AssertionFailure.
#define LIBCARNA_ASSERT(expression)
If the given expression is false, a break point is raised in debug mode and an AssertionFailure throw...
Contains forward-declarations.
Represents an association.
Maintains an OpenGL texture sampler object. This class realizes the RAII-idiom.
Definition Sampler.hpp:48
float translationDistance2(const Matrix4f &m)
Returns the squared length of the translation component of the homogeneous coordinates transformation...
Definition math.hpp:486
bool isEqual(const InputType &x, const InputType &y)
Tells whether two objects are equal respectively to epsilon.
Definition math.hpp:178
base::math::Vector3f computeFastGradient3f(Sampler func)
Computes fast approximation of the gradient at the origin of the scalar field func.
Definition math.hpp:581
Eigen::Matrix< signed int, 3, 1 > Vector3i
Defines vector.
Definition math.hpp:202
T length2(const T &x)
Retrieves the squared length of vector and scalar types. General case assumes scalar type.
Definition math.hpp:159
MatrixType zeros()
Returns matrix with zeros in all components.
Definition math.hpp:230
Eigen::Matrix< float, 3, 3, Eigen::ColMajor > Matrix3f
Defines matrix.
Definition math.hpp:198
Matrix4f frustum4f(float left, float right, float bottom, float top, float zNear, float zFar)
Returns the projection matrix that is described by the specified frustum.
Definition math.hpp:520
Matrix::Scalar maxAbsElement(const Matrix &m)
Returns where $m$ is m.
Definition math.hpp:495
Matrix3f identity3f()
Returns identity matrix.
Definition math.hpp:219
Eigen::Matrix< float, 2, 1 > Vector2f
Defines vector.
Definition math.hpp:201
Matrix4f ortho4f(float left, float right, float bottom, float top, float zNear, float zFar)
Returns the projection matrix that is described by the specified box.
Definition math.hpp:561
Eigen::Matrix< float, 3, 1 > Vector3f
Defines vector.
Definition math.hpp:200
Matrix4f rotation4f(float x, float y, float z, float radians)
Creates rotation matrix for homogeneous coordinates. The rotation is performed around the axis that i...
Definition math.hpp:326
Eigen::Matrix< unsigned int, 2, 1 > Vector2ui
Defines vector.
Definition math.hpp:204
float epsilon< float >()
Defines the maximum difference of two single-precision floating point objects treated as equal.
Definition math.hpp:112
Matrix3f rotation3f(float x, float y, float z, float radians)
Creates rotation matrix for homogeneous coordinates, but returns only the upper left sub-matrix.
Definition math.hpp:361
Eigen::Matrix< float, 4, 4, Eigen::ColMajor > Matrix4f
Defines matrix.
Definition math.hpp:197
Eigen::Matrix< VectorElementType, 4, 1 > vector4(const Eigen::Matrix< VectorElementType, rows, 1 > &v, WType w)
Creates 4-dimensional vector from 3-dimensional (or higher) with same component type,...
Definition math.hpp:438
ScalarType makeEven(ScalarType x, int s)
Returns if is even and if is odd, where . The data type of must be integral.
Definition math.hpp:625
Eigen::Matrix< float, 4, 1 > Vector4f
Defines vector.
Definition math.hpp:199
unsigned int round_ui(ScalarType x)
Rounds x to the closest . Either the data type of must be unsigned or .
Definition math.hpp:598
float rad2deg(float rad)
Converts radians to degrees.
Definition math.hpp:93
Vector3f orthogonal3f(const Vector3f &in)
Constructs vector that is orthogonal to in. The result is undefined if the squared length of in equa...
Definition math.hpp:371
Matrix4f scaling4f(float x, float y, float z)
Creates scaling matrix for homogeneous coordinates.
Definition math.hpp:296
Matrix4f plane4f(const Vector3f &normal, float distance)
Creates matrix that transforms from the tangent space of a plane with particular normal vector and or...
Definition math.hpp:460
T sq(T x)
Computes and returns .
Definition math.hpp:77
float deg2rad(float deg)
Converts degrees to radians.
Definition math.hpp:85
ResultType mix(const SupportType &a, const SupportType &b, float t)
Interpolates between and by t linearly.
Definition math.hpp:719
Eigen::Matrix< VectorElementType, 3, 1 > vector3(const Eigen::Matrix< VectorElementType, rows, 1 > &v)
Creates 3-dimensional vector from 4-dimensional (or higher) with same component type by dropping the ...
Definition math.hpp:449
Matrix4f translation4f(float x, float y, float z)
Returns matrix that translates homogeneous coordinates.
Definition math.hpp:275
T epsilon()
Defines the maximum difference of two objects treated as equal.
Definition math.hpp:102
double epsilon< double >()
Defines the maximum difference of two double-precision floating point objects treated as equal.
Definition math.hpp:122
Matrix4f identity4f()
Returns identity matrix.
Definition math.hpp:209
Eigen::Matrix< unsigned int, 3, 1 > Vector3ui
Defines vector.
Definition math.hpp:203
T clamp(T val, T my_min, T my_max)
Returns val my_min my_max .
Definition math.hpp:68
Matrix4f basis4f(const Vector4f &x, const Vector4f &y, const Vector4f &z, const Vector4f &t=Vector4f(0, 0, 0, 0))
Creates basis embedded into a homogenous coordinates matrix.
Definition math.hpp:246
Holds mean and variance of an characteristic.
Definition math.hpp:654
T standardDeviation() const
Computes the standard deviation.
Definition math.hpp:709
Statistics< T > & operator=(const Statistics< T > &other)
Copies from other.
Definition math.hpp:699
T variance
Holds the variance.
Definition math.hpp:656
Statistics(T mean, T variance)
Initializes with mean and variance.
Definition math.hpp:661
Statistics(std::size_t size, const std::function< T(std::size_t) > values)
Computes statistics from size samples queried from values.
Definition math.hpp:668
VectorElementType type
The vector element type is known implicitly for each vector type.
Definition math.hpp:150
Retrieves element types of vectors and scalars. General case assumes a scalar type.
Definition math.hpp:133
T type
Since T is assumed to be scalar type, it's element type is also T.
Definition math.hpp:137