Carna  Version 3.0.1
math.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 - 2015 Leonid Kostrykin
3  *
4  * Chair of Medical Engineering (mediTEC)
5  * RWTH Aachen University
6  * Pauwelsstr. 20
7  * 52074 Aachen
8  * Germany
9  *
10  */
11 
12 #ifndef MATH_H_6014714286
13 #define MATH_H_6014714286
14 
15 #include <Carna/Carna.h>
17 #include <algorithm>
18 #include <type_traits>
19 #include <cmath>
20 #include <Eigen/Dense>
21 
22 #ifdef min
23 #error MIN macro defined, define NOMINMAX first!
24 #endif
25 
26 #ifdef max
27 #error MAX macro defined, define NOMINMAX first!
28 #endif
29 
32 #ifndef NOMINMAX
33 #define NOMINMAX
34 #endif
35 
46 namespace Carna
47 {
48 
49 namespace base
50 {
51 
52 namespace math
53 {
54 
63  template< typename T >
64  T clamp( T val, T my_min, T my_max )
65  {
66  return std::min( std::max( val, my_min ), my_max );
67  }
68 
72  template< typename T >
73  T sq( T x )
74  {
75  return x * x;
76  }
77 
81  inline float deg2rad( float deg )
82  {
83  return deg * 3.1415926f / 180.f;
84  }
85 
89  inline float rad2deg( float rad )
90  {
91  return 180.f * rad / 3.1415926f;
92  }
93 
97  template< typename T >
98  T epsilon()
99  {
100  return static_cast< T >( 0 );
101  }
102 
107  template< >
108  inline float epsilon< float >()
109  {
110  return 1e-4f;
111  }
112 
117  template< >
118  inline double epsilon< double >()
119  {
120  return 1e-6;
121  }
122 
127  template< typename T >
129  {
133  typedef T type;
134  };
135 
140  template< typename VectorElementType, int rows, int cols >
141  struct element_type_of< Eigen::Matrix< VectorElementType, rows, cols > >
142  {
146  typedef VectorElementType type;
147 
148  };
149 
154  template< typename T >
155  T length2( const T& x )
156  {
157  return x * x;
158  }
159 
164  template< typename VectorElementType, int dimension >
165  VectorElementType length2( const Eigen::Matrix< VectorElementType, dimension, 1 >& x )
166  {
167  return x.squaredNorm();
168  }
169 
173  template< typename InputType >
174  bool isEqual( const InputType& x, const InputType& y )
175  {
176  typedef typename element_type_of< InputType >::type ScalarType;
177  const InputType difference = x - y;
178  const ScalarType distance2 = length2( InputType( difference ) );
179  const ScalarType _epsilon = epsilon< ScalarType >();
180  return distance2 <= _epsilon;
181  }
182 
187  template< >
188  inline bool isEqual( const bool& x, const bool& y )
189  {
190  return x == y;
191  }
192 
193  typedef Eigen::Matrix< float, 4, 4, Eigen::ColMajor > Matrix4f;
194  typedef Eigen::Matrix< float, 3, 3, Eigen::ColMajor > Matrix3f;
195  typedef Eigen::Matrix< float, 4, 1 > Vector4f;
196  typedef Eigen::Matrix< float, 3, 1 > Vector3f;
197  typedef Eigen::Matrix< float, 2, 1 > Vector2f;
198  typedef Eigen::Matrix< signed int, 3, 1 > Vector3i;
199  typedef Eigen::Matrix< unsigned int, 3, 1 > Vector3ui;
200  typedef Eigen::Matrix< unsigned int, 2, 1 > Vector2ui;
201 
205  inline Matrix4f identity4f()
206  {
207  Matrix4f result;
208  result.setIdentity();
209  return result;
210  }
211 
215  inline Matrix3f identity3f()
216  {
217  Matrix3f result;
218  result.setIdentity();
219  return result;
220  }
221 
225  template< typename MatrixType >
226  MatrixType zeros()
227  {
228  MatrixType result;
229  result.setZero();
230  return result;
231  }
232 
242  inline Matrix4f basis4f( const Vector4f& x, const Vector4f& y, const Vector4f& z, const Vector4f& t = Vector4f( 0, 0, 0, 0 ) )
243  {
244  Matrix4f result;
245  result.col( 0 ) = x;
246  result.col( 1 ) = y;
247  result.col( 2 ) = z;
248  result.col( 3 ) = t;
249  for( unsigned int i = 0; i < 3; ++i )
250  {
251  result( 3, i ) = 0;
252  }
253  result( 3, 3 ) = 1;
254  return result;
255  }
256 
259  inline Matrix4f basis4f( const Vector3f& x, const Vector3f& y, const Vector3f& z, const Vector3f& t = Vector3f( 0, 0, 0 ) )
260  {
261  const Vector4f x4( x.x(), x.y(), x.z(), 0 );
262  const Vector4f y4( y.x(), y.y(), y.z(), 0 );
263  const Vector4f z4( z.x(), z.y(), z.z(), 0 );
264  const Vector4f t4( t.x(), t.y(), t.z(), 0 );
265  return basis4f( x4, y4, z4, t4 );
266  }
267 
271  inline Matrix4f translation4f( float x, float y, float z )
272  {
273  Matrix4f result;
274  result.setIdentity();
275  result( 0, 3 ) = x;
276  result( 1, 3 ) = y;
277  result( 2, 3 ) = z;
278  return result;
279  }
280 
283  template< typename Vector >
284  Matrix4f translation4f( const Vector& v )
285  {
286  return translation4f( v.x(), v.y(), v.z() );
287  }
288 
292  inline Matrix4f scaling4f( float x, float y, float z )
293  {
294  Matrix4f result;
295  result.setIdentity();
296  result( 0, 0 ) = x;
297  result( 1, 1 ) = y;
298  result( 2, 2 ) = z;
299  return result;
300  }
301 
304  template< typename VectorElementType >
305  inline Matrix4f scaling4f( const Eigen::Matrix< VectorElementType, 3, 1 >& v )
306  {
307  return scaling4f( v.x(), v.y(), v.z() );
308  }
309 
312  inline Matrix4f scaling4f( float uniformScaleFactor )
313  {
314  return scaling4f( uniformScaleFactor, uniformScaleFactor, uniformScaleFactor );
315  }
316 
322  inline Matrix4f rotation4f( float x, float y, float z, float radians )
323  {
324  const float c = std::cos( radians );
325  const float s = std::sin( radians );
326 
327  Matrix4f result;
328  result.setIdentity();
329 
330  result( 0, 0 ) = x * x * ( 1 - c ) + c;
331  result( 1, 0 ) = y * x * ( 1 - c ) + z * s;
332  result( 2, 0 ) = x * z * ( 1 - c ) - y * s;
333 
334  result( 0, 1 ) = x * y * ( 1 - c ) - z * s;
335  result( 1, 1 ) = y * y * ( 1 - c ) + c;
336  result( 2, 1 ) = y * z * ( 1 - c ) + x * s;
337 
338  result( 0, 2 ) = x * z * ( 1 - c ) + y * s;
339  result( 1, 2 ) = y * z * ( 1 - c ) - x * s;
340  result( 2, 2 ) = z * z * ( 1 - c ) + c;
341 
342  return result;
343  }
344 
347  template< typename Vector >
348  Matrix4f rotation4f( const Vector& v, float radians )
349  {
350  return rotation4f( v.x(), v.y(), v.z(), radians );
351  }
352 
357  inline Matrix3f rotation3f( float x, float y, float z, float radians )
358  {
359  return rotation4f( x, y, z, radians ).block< 3, 3 >( 0, 0 );
360  }
361 
367  inline Vector3f orthogonal3f( const Vector3f& in )
368  {
369  Vector3f out;
370  if( std::abs( in.x() - in.y() ) > 1e-4f )
371  {
372  out.x() = in.y();
373  out.y() = in.x();
374  out.z() = 0;
375 
376  if( std::abs( out.x() ) > std::abs( out.y() ) )
377  {
378  out.x() = -out.x();
379  }
380  else
381  {
382  out.y() = -out.y();
383  }
384  }
385  else
386  if( std::abs( in.x() - in.z() ) > 1e-4f )
387  {
388  out.x() = in.z();
389  out.y() = 0;
390  out.z() = in.x();
391 
392  if( std::abs( out.x() ) > std::abs( out.z() ) )
393  {
394  out.x() = -out.x();
395  }
396  else
397  {
398  out.z() = -out.z();
399  }
400  }
401  else
402  if( std::abs( in.y() - in.z() ) > 1e-4f )
403  {
404  out.x() = 0;
405  out.y() = in.z();
406  out.z() = in.x();
407 
408  if( std::abs( out.y() ) > std::abs( out.z() ) )
409  {
410  out.y() = -out.y();
411  }
412  else
413  {
414  out.z() = -out.z();
415  }
416  }
417  else // all components are equal
418  {
419  out = Vector3f( -in.x(), in.y(), 0 );
420  }
421 
425  CARNA_ASSERT( isEqual< float >( in.dot( out ), 0 ) );
426  return out;
427  }
428 
433  template< typename VectorElementType, int rows, typename WType >
434  Eigen::Matrix< VectorElementType, 4, 1 > vector4( const Eigen::Matrix< VectorElementType, rows, 1 >& v, WType w )
435  {
436  static_assert( rows >= 3, "math::vector4 requires input vector with 3 rows or more." );
437  return Eigen::Matrix< VectorElementType, 4, 1 >( v.x(), v.y(), v.z(), static_cast< VectorElementType >( w ) );
438  }
439 
444  template< typename VectorElementType, int rows >
445  Eigen::Matrix< VectorElementType, 3, 1 > vector3( const Eigen::Matrix< VectorElementType, rows, 1 >& v )
446  {
447  static_assert( rows >= 3, "math::vector3 requires input vector with 3 rows or more." );
448  return Eigen::Matrix< VectorElementType, 3, 1 >( v.x(), v.y(), v.z() );
449  }
450 
456  inline Matrix4f plane4f( const Vector3f& normal, float distance )
457  {
458  CARNA_ASSERT( isEqual< float >( normal.norm(), 1 ) );
459  const Vector3f tangent ( orthogonal3f( normal ).normalized() );
460  const Vector3f bitangent( normal.cross( tangent ).normalized() );
461  const Vector3f translation( normal * distance );
462  return basis4f
463  ( vector4( bitangent, 0 )
464  , vector4( tangent, 0 )
465  , vector4( normal, 0 )
466  , vector4( translation, 1 ) );
467  }
468 
471  inline Matrix4f plane4f( const Vector3f& normal, const Vector3f& support )
472  {
473  CARNA_ASSERT( isEqual< float >( normal.norm(), 1 ) );
474  const float distance = normal.dot( support );
475  return plane4f( normal, distance );
476  }
477 
482  inline float translationDistance2( const Matrix4f& m )
483  {
484  return m( 0, 3 ) * m( 0, 3 ) + m( 1, 3 ) * m( 1, 3 ) + m( 2, 3 ) * m( 2, 3 );
485  }
486 
490  template< typename Matrix >
491  typename Matrix::Scalar maxAbsElement( const Matrix& m )
492  {
493  const std::size_t length = m.rows() * m.cols();
494  typename Matrix::Scalar maxAbs = 0;
495  for( std::size_t i = 0; i < length; ++i )
496  {
497  maxAbs = std::max( maxAbs, std::abs( m.data()[ i ] ) );
498  }
499  return maxAbs;
500  }
501 
516  inline Matrix4f frustum4f( float left, float right, float bottom, float top, float zNear, float zFar )
517  {
518  Matrix4f result;
519  result.setZero();
520 
521  result( 0, 0 ) = +2 * zNear / ( right - left );
522  result( 1, 1 ) = +2 * zNear / ( top - bottom );
523  result( 0, 2 ) = ( right + left ) / ( right - left );
524  result( 1, 2 ) = ( top + bottom ) / ( top - bottom );
525  result( 2, 2 ) = -( zFar + zNear ) / ( zFar - zNear );
526  result( 3, 2 ) = -1;
527  result( 2, 3 ) = -2 * zFar * zNear / ( zFar - zNear );
528 
529  return result;
530  }
531 
547  inline Matrix4f frustum4f( float fovRadiansHorizontal, float heightOverWidth, float zNear, float zFar )
548  {
549  const float halfProjPlaneWidth = zNear * std::tan( fovRadiansHorizontal );
550  const float halfProjPlaneHeight = halfProjPlaneWidth * heightOverWidth;
551  return frustum4f( -halfProjPlaneWidth, +halfProjPlaneWidth, -halfProjPlaneHeight, +halfProjPlaneHeight, zNear, zFar );
552  }
553 
557  inline Matrix4f ortho4f( float left, float right, float bottom, float top, float zNear, float zFar )
558  {
559  Matrix4f result;
560  result.setZero();
561 
562  result( 0, 0 ) = 2 / ( right - left );
563  result( 1, 1 ) = 2 / ( top - bottom );
564  result( 2, 2 ) = -2 / ( zFar - zNear );
565  result( 0, 3 ) = -( right + left ) / ( right - left );
566  result( 1, 3 ) = -( top + bottom ) / ( bottom - top );
567  result( 2, 3 ) = -( zFar + zNear ) / ( zFar - zNear );
568  result( 3, 3 ) = +1;
569 
570  return result;
571  }
572 
577  template< typename ScalarType >
578  unsigned int round_ui( ScalarType x )
579  {
580  CARNA_ASSERT( !std::numeric_limits< ScalarType >::is_signed || x >= 0 );
581  return static_cast< unsigned int >( x + static_cast< ScalarType >( 0.5 ) );
582  }
583 
589  template< typename MatrixElementType, int cols, int rows >
590  Eigen::Matrix< unsigned int, cols, rows > round_ui( const Eigen::Matrix< MatrixElementType, cols, rows >& m )
591  {
592  Eigen::Matrix< unsigned int, cols, rows > result;
593  for( int i = 0; i < cols; ++i )
594  for( int j = 0; j < rows; ++j )
595  {
596  result( i, j ) = round_ui( m( i, j ) );
597  }
598  return result;
599  }
600 
605  template< typename ScalarType >
606  ScalarType makeEven( ScalarType x, int s )
607  {
608  CARNA_ASSERT( s == +1 || s == -1 );
609  static_assert( std::is_integral< ScalarType >::value, "Only integral data types allowed." );
610  return x + s * ( x % 2 );
611  }
612 
620  template< typename MatrixElementType, int cols, int rows >
621  Eigen::Matrix< MatrixElementType, cols, rows > makeEven( const Eigen::Matrix< MatrixElementType, cols, rows >& m, int s )
622  {
623  Eigen::Matrix< unsigned int, cols, rows > result;
624  for( int i = 0; i < cols; ++i )
625  for( int j = 0; j < rows; ++j )
626  {
627  result( i, j ) = makeEven( m( i, j ), s );
628  }
629  return result;
630  }
631 
635  template< typename T >
636  struct Statistics
637  {
638  T mean;
640 
644  Statistics( T mean, T variance ) : mean( mean ), variance( variance )
645  {
646  }
647 
651  Statistics( std::size_t size, const std::function< T( std::size_t ) > values )
652  {
653  if( size == 0 )
654  {
655  mean = variance = 0;
656  }
657  else
658  {
659  /* Compute mean.
660  */
661  T sum = 0;
662  for( std::size_t idx = 0; idx < size; ++idx )
663  {
664  sum += values( idx );
665  }
666  mean = sum / size;
667 
668  /* Compute variance.
669  */
670  sum = 0;
671  for( std::size_t idx = 0; idx < size; ++idx )
672  {
673  sum += sq( mean - values( idx ) );
674  }
675  variance = sum / ( size - 1 );
676  }
677  }
678 
683  {
684  mean = other.mean;
685  variance = other.variance;
686  return *this;
687  }
688 
693  {
694  return std::sqrt( variance );
695  }
696  };
697 
701  template< typename ResultType, typename SupportType >
702  ResultType mix( const SupportType& a, const SupportType& b, float t )
703  {
704  return a * ( 1 - t ) + b * t;
705  }
706 
707 
708 
714 #define CARNA_FOR_VECTOR3UI_EX( vecName, vecLimit, vecStart ) \
715  Carna::base::math::Vector3ui vecName; \
716  for( vecName.z() = vecStart.x(); vecName.z() < vecLimit.z(); ++vecName.z() ) \
717  for( vecName.y() = vecStart.y(); vecName.y() < vecLimit.y(); ++vecName.y() ) \
718  for( vecName.x() = vecStart.z(); vecName.x() < vecLimit.x(); ++vecName.x() )
719 
720 
721 
728 #define CARNA_FOR_VECTOR3UI( vecName, vecLimit ) \
729  CARNA_FOR_VECTOR3UI_EX( vecName, vecLimit, Carna::base::math::Vector3ui( 0, 0, 0 ) )
730 
731 
732 
733 } // namespace Carna :: base :: math
734 
735 } // namespace Carna :: base
736 
737 } // namespace Carna
738 
739 
740 
741 #endif // MATH_H_6014714286
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.h:445
Holds mean and variance of an characteristic.
Definition: math.h:636
Eigen::Matrix< float, 2, 1 > Vector2f
Defines vector.
Definition: math.h:197
unsigned int round_ui(ScalarType x)
Rounds x to the closest . Either the data type of must be unsigned or .
Definition: math.h:578
ScalarType makeEven(ScalarType x, int s)
Returns if is even and if is odd, where . The data type of must be integral. ...
Definition: math.h:606
T length2(const T &x)
Retrieves the squared length of vector and scalar types. General case assumes scalar type...
Definition: math.h:155
float epsilon< float >()
Defines the maximum difference of two single-precision floating point objects treated as equal...
Definition: math.h:108
Matrix4f scaling4f(float x, float y, float z)
Creates scaling matrix for homogeneous coordinates.
Definition: math.h:292
Eigen::Matrix< float, 4, 1 > Vector4f
Defines vector.
Definition: math.h:195
Eigen::Matrix< unsigned int, 3, 1 > Vector3ui
Defines vector.
Definition: math.h:199
ResultType mix(const SupportType &a, const SupportType &b, float t)
Interpolates between and by t linearly.
Definition: math.h:702
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.h:242
T mean
Holds the mean.
Definition: math.h:638
Eigen::Matrix< float, 3, 1 > Vector3f
Defines vector.
Definition: math.h:196
Matrix4f translation4f(float x, float y, float z)
Returns matrix that translates homogeneous coordinates.
Definition: math.h:271
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.h:322
Statistics(T mean, T variance)
Initializes with mean and variance.
Definition: math.h:644
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.h:516
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.h:357
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.h:367
T epsilon()
Defines the maximum difference of two objects treated as equal.
Definition: math.h:98
Eigen::Matrix< float, 4, 4, Eigen::ColMajor > Matrix4f
Defines matrix.
Definition: math.h:193
double epsilon< double >()
Defines the maximum difference of two double-precision floating point objects treated as equal...
Definition: math.h:118
float rad2deg(float rad)
Converts radians to degrees.
Definition: math.h:89
Matrix4f identity4f()
Returns identity matrix.
Definition: math.h:205
T variance
Holds the variance.
Definition: math.h:639
T sq(T x)
Computes and returns .
Definition: math.h:73
Statistics(std::size_t size, const std::function< T(std::size_t) > values)
Computes statistics from size samples queried from values.
Definition: math.h:651
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.h:557
T type
Since T is assumed to be scalar type, it's element type is also T.
Definition: math.h:133
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.h:456
Statistics< T > & operator=(const Statistics< T > &other)
Copies from other.
Definition: math.h:682
MatrixType zeros()
Returns matrix with zeros in all components.
Definition: math.h:226
Defines Carna::base::CarnaException, Carna::base::AssertionFailure.
bool isEqual(const InputType &x, const InputType &y)
Tells whether two objects are equal respectively to epsilon.
Definition: math.h:174
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, and a scalar that is appended as the fourth component.
Definition: math.h:434
Eigen::Matrix< unsigned int, 2, 1 > Vector2ui
Defines vector.
Definition: math.h:200
#define CARNA_ASSERT(expression)
If the given expression is false, a break point is raised in debug mode and an AssertionFailure throw...
Matrix3f identity3f()
Returns identity matrix.
Definition: math.h:215
VectorElementType type
The vector element type is known implicitly for each vector type.
Definition: math.h:146
T clamp(T val, T my_min, T my_max)
Returns val my_min my_max .
Definition: math.h:64
float deg2rad(float deg)
Converts degrees to radians.
Definition: math.h:81
Retrieves element types of vectors and scalars. General case assumes a scalar type.
Definition: math.h:128
T standardDeviation() const
Computes the standard deviation.
Definition: math.h:692
Matrix::Scalar maxAbsElement(const Matrix &m)
Returns where $m$ is m.
Definition: math.h:491
Eigen::Matrix< signed int, 3, 1 > Vector3i
Defines vector.
Definition: math.h:198
float translationDistance2(const Matrix4f &m)
Returns the squared length of the translation component of the homogeneous coordinates transformation...
Definition: math.h:482
Eigen::Matrix< float, 3, 3, Eigen::ColMajor > Matrix3f
Defines matrix.
Definition: math.h:194