linearspace2.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "vec2.h"
  18. namespace embree
  19. {
  20. ////////////////////////////////////////////////////////////////////////////////
  21. /// 2D Linear Transform (2x2 Matrix)
  22. ////////////////////////////////////////////////////////////////////////////////
  23. template<typename T> struct LinearSpace2
  24. {
  25. typedef T Vector;
  26. typedef typename T::Scalar Scalar;
  27. /*! default matrix constructor */
  28. __forceinline LinearSpace2 ( ) {}
  29. __forceinline LinearSpace2 ( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; }
  30. __forceinline LinearSpace2& operator=( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; return *this; }
  31. template<typename L1> __forceinline LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
  32. /*! matrix construction from column vectors */
  33. __forceinline LinearSpace2(const Vector& vx, const Vector& vy)
  34. : vx(vx), vy(vy) {}
  35. /*! matrix construction from row mayor data */
  36. __forceinline LinearSpace2(const Scalar& m00, const Scalar& m01,
  37. const Scalar& m10, const Scalar& m11)
  38. : vx(m00,m10), vy(m01,m11) {}
  39. /*! compute the determinant of the matrix */
  40. __forceinline const Scalar det() const { return vx.x*vy.y - vx.y*vy.x; }
  41. /*! compute adjoint matrix */
  42. __forceinline const LinearSpace2 adjoint() const { return LinearSpace2(vy.y,-vy.x,-vx.y,vx.x); }
  43. /*! compute inverse matrix */
  44. __forceinline const LinearSpace2 inverse() const { return adjoint()/det(); }
  45. /*! compute transposed matrix */
  46. __forceinline const LinearSpace2 transposed() const { return LinearSpace2(vx.x,vx.y,vy.x,vy.y); }
  47. /*! returns first row of matrix */
  48. __forceinline const Vector row0() const { return Vector(vx.x,vy.x); }
  49. /*! returns second row of matrix */
  50. __forceinline const Vector row1() const { return Vector(vx.y,vy.y); }
  51. ////////////////////////////////////////////////////////////////////////////////
  52. /// Constants
  53. ////////////////////////////////////////////////////////////////////////////////
  54. __forceinline LinearSpace2( ZeroTy ) : vx(zero), vy(zero) {}
  55. __forceinline LinearSpace2( OneTy ) : vx(one, zero), vy(zero, one) {}
  56. /*! return matrix for scaling */
  57. static __forceinline LinearSpace2 scale(const Vector& s) {
  58. return LinearSpace2(s.x, 0,
  59. 0 , s.y);
  60. }
  61. /*! return matrix for rotation */
  62. static __forceinline LinearSpace2 rotate(const Scalar& r) {
  63. Scalar s = sin(r), c = cos(r);
  64. return LinearSpace2(c, -s,
  65. s, c);
  66. }
  67. /*! return closest orthogonal matrix (i.e. a general rotation including reflection) */
  68. LinearSpace2 orthogonal() const
  69. {
  70. LinearSpace2 m = *this;
  71. // mirrored?
  72. Scalar mirror(one);
  73. if (m.det() < Scalar(zero)) {
  74. m.vx = -m.vx;
  75. mirror = -mirror;
  76. }
  77. // rotation
  78. for (int i = 0; i < 99; i++) {
  79. const LinearSpace2 m_next = 0.5 * (m + m.transposed().inverse());
  80. const LinearSpace2 d = m_next - m;
  81. m = m_next;
  82. // norm^2 of difference small enough?
  83. if (max(dot(d.vx, d.vx), dot(d.vy, d.vy)) < 1e-8)
  84. break;
  85. }
  86. // rotation * mirror_x
  87. return LinearSpace2(mirror*m.vx, m.vy);
  88. }
  89. public:
  90. /*! the column vectors of the matrix */
  91. Vector vx,vy;
  92. };
  93. ////////////////////////////////////////////////////////////////////////////////
  94. // Unary Operators
  95. ////////////////////////////////////////////////////////////////////////////////
  96. template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a ) { return LinearSpace2<T>(-a.vx,-a.vy); }
  97. template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a ) { return LinearSpace2<T>(+a.vx,+a.vy); }
  98. template<typename T> __forceinline LinearSpace2<T> rcp ( const LinearSpace2<T>& a ) { return a.inverse(); }
  99. ////////////////////////////////////////////////////////////////////////////////
  100. // Binary Operators
  101. ////////////////////////////////////////////////////////////////////////////////
  102. template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx+b.vx,a.vy+b.vy); }
  103. template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx-b.vx,a.vy-b.vy); }
  104. template<typename T> __forceinline LinearSpace2<T> operator*(const typename T::Scalar & a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
  105. template<typename T> __forceinline T operator*(const LinearSpace2<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy; }
  106. template<typename T> __forceinline LinearSpace2<T> operator*(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
  107. template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const typename T::Scalar & b) { return LinearSpace2<T>(a.vx/b, a.vy/b); }
  108. template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return a * rcp(b); }
  109. template<typename T> __forceinline LinearSpace2<T>& operator *=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a * b; }
  110. template<typename T> __forceinline LinearSpace2<T>& operator /=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a / b; }
  111. ////////////////////////////////////////////////////////////////////////////////
  112. /// Comparison Operators
  113. ////////////////////////////////////////////////////////////////////////////////
  114. template<typename T> __forceinline bool operator ==( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx == b.vx && a.vy == b.vy; }
  115. template<typename T> __forceinline bool operator !=( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx != b.vx || a.vy != b.vy; }
  116. ////////////////////////////////////////////////////////////////////////////////
  117. /// Output Operators
  118. ////////////////////////////////////////////////////////////////////////////////
  119. template<typename T> static std::ostream& operator<<(std::ostream& cout, const LinearSpace2<T>& m) {
  120. return cout << "{ vx = " << m.vx << ", vy = " << m.vy << "}";
  121. }
  122. /*! Shortcuts for common linear spaces. */
  123. typedef LinearSpace2<Vec2f> LinearSpace2f;
  124. }