Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
8.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. AffineTransform::AffineTransform (float m00, float m01, float m02,
  21. float m10, float m11, float m12) noexcept
  22. : mat00 (m00), mat01 (m01), mat02 (m02),
  23. mat10 (m10), mat11 (m11), mat12 (m12)
  24. {
  25. }
  26. bool AffineTransform::operator== (const AffineTransform& other) const noexcept
  27. {
  28. return mat00 == other.mat00
  29. && mat01 == other.mat01
  30. && mat02 == other.mat02
  31. && mat10 == other.mat10
  32. && mat11 == other.mat11
  33. && mat12 == other.mat12;
  34. }
  35. bool AffineTransform::operator!= (const AffineTransform& other) const noexcept
  36. {
  37. return ! operator== (other);
  38. }
  39. //==============================================================================
  40. bool AffineTransform::isIdentity() const noexcept
  41. {
  42. return mat01 == 0.0f
  43. && mat02 == 0.0f
  44. && mat10 == 0.0f
  45. && mat12 == 0.0f
  46. && mat00 == 1.0f
  47. && mat11 == 1.0f;
  48. }
  49. const AffineTransform AffineTransform::identity (1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
  50. //==============================================================================
  51. AffineTransform AffineTransform::followedBy (const AffineTransform& other) const noexcept
  52. {
  53. return { other.mat00 * mat00 + other.mat01 * mat10,
  54. other.mat00 * mat01 + other.mat01 * mat11,
  55. other.mat00 * mat02 + other.mat01 * mat12 + other.mat02,
  56. other.mat10 * mat00 + other.mat11 * mat10,
  57. other.mat10 * mat01 + other.mat11 * mat11,
  58. other.mat10 * mat02 + other.mat11 * mat12 + other.mat12 };
  59. }
  60. AffineTransform AffineTransform::translated (float dx, float dy) const noexcept
  61. {
  62. return { mat00, mat01, mat02 + dx,
  63. mat10, mat11, mat12 + dy };
  64. }
  65. AffineTransform AffineTransform::translation (float dx, float dy) noexcept
  66. {
  67. return { 1.0f, 0.0f, dx,
  68. 0.0f, 1.0f, dy };
  69. }
  70. AffineTransform AffineTransform::withAbsoluteTranslation (float tx, float ty) const noexcept
  71. {
  72. return { mat00, mat01, tx,
  73. mat10, mat11, ty };
  74. }
  75. AffineTransform AffineTransform::rotated (float rad) const noexcept
  76. {
  77. auto cosRad = std::cos (rad);
  78. auto sinRad = std::sin (rad);
  79. return { cosRad * mat00 - sinRad * mat10,
  80. cosRad * mat01 - sinRad * mat11,
  81. cosRad * mat02 - sinRad * mat12,
  82. sinRad * mat00 + cosRad * mat10,
  83. sinRad * mat01 + cosRad * mat11,
  84. sinRad * mat02 + cosRad * mat12 };
  85. }
  86. AffineTransform AffineTransform::rotation (float rad) noexcept
  87. {
  88. auto cosRad = std::cos (rad);
  89. auto sinRad = std::sin (rad);
  90. return { cosRad, -sinRad, 0,
  91. sinRad, cosRad, 0 };
  92. }
  93. AffineTransform AffineTransform::rotation (float rad, float pivotX, float pivotY) noexcept
  94. {
  95. auto cosRad = std::cos (rad);
  96. auto sinRad = std::sin (rad);
  97. return { cosRad, -sinRad, -cosRad * pivotX + sinRad * pivotY + pivotX,
  98. sinRad, cosRad, -sinRad * pivotX + -cosRad * pivotY + pivotY };
  99. }
  100. AffineTransform AffineTransform::rotated (float angle, float pivotX, float pivotY) const noexcept
  101. {
  102. return followedBy (rotation (angle, pivotX, pivotY));
  103. }
  104. AffineTransform AffineTransform::scaled (float factorX, float factorY) const noexcept
  105. {
  106. return { factorX * mat00, factorX * mat01, factorX * mat02,
  107. factorY * mat10, factorY * mat11, factorY * mat12 };
  108. }
  109. AffineTransform AffineTransform::scaled (float factor) const noexcept
  110. {
  111. return { factor * mat00, factor * mat01, factor * mat02,
  112. factor * mat10, factor * mat11, factor * mat12 };
  113. }
  114. AffineTransform AffineTransform::scale (float factorX, float factorY) noexcept
  115. {
  116. return { factorX, 0, 0, 0, factorY, 0 };
  117. }
  118. AffineTransform AffineTransform::scale (float factor) noexcept
  119. {
  120. return { factor, 0, 0, 0, factor, 0 };
  121. }
  122. AffineTransform AffineTransform::scaled (float factorX, float factorY,
  123. float pivotX, float pivotY) const noexcept
  124. {
  125. return { factorX * mat00, factorX * mat01, factorX * mat02 + pivotX * (1.0f - factorX),
  126. factorY * mat10, factorY * mat11, factorY * mat12 + pivotY * (1.0f - factorY) };
  127. }
  128. AffineTransform AffineTransform::scale (float factorX, float factorY,
  129. float pivotX, float pivotY) noexcept
  130. {
  131. return { factorX, 0, pivotX * (1.0f - factorX),
  132. 0, factorY, pivotY * (1.0f - factorY) };
  133. }
  134. AffineTransform AffineTransform::shear (float shearX, float shearY) noexcept
  135. {
  136. return { 1.0f, shearX, 0,
  137. shearY, 1.0f, 0 };
  138. }
  139. AffineTransform AffineTransform::sheared (float shearX, float shearY) const noexcept
  140. {
  141. return { mat00 + shearX * mat10,
  142. mat01 + shearX * mat11,
  143. mat02 + shearX * mat12,
  144. mat10 + shearY * mat00,
  145. mat11 + shearY * mat01,
  146. mat12 + shearY * mat02 };
  147. }
  148. AffineTransform AffineTransform::verticalFlip (float height) noexcept
  149. {
  150. return { 1.0f, 0.0f, 0.0f,
  151. 0.0f, -1.0f, height };
  152. }
  153. AffineTransform AffineTransform::inverted() const noexcept
  154. {
  155. double determinant = getDeterminant();
  156. if (! approximatelyEqual (determinant, 0.0))
  157. {
  158. determinant = 1.0 / determinant;
  159. auto dst00 = (float) ( mat11 * determinant);
  160. auto dst10 = (float) (-mat10 * determinant);
  161. auto dst01 = (float) (-mat01 * determinant);
  162. auto dst11 = (float) ( mat00 * determinant);
  163. return { dst00, dst01, -mat02 * dst00 - mat12 * dst01,
  164. dst10, dst11, -mat02 * dst10 - mat12 * dst11 };
  165. }
  166. // singularity..
  167. return *this;
  168. }
  169. bool AffineTransform::isSingularity() const noexcept
  170. {
  171. return (mat00 * mat11 - mat10 * mat01) == 0.0f;
  172. }
  173. AffineTransform AffineTransform::fromTargetPoints (float x00, float y00,
  174. float x10, float y10,
  175. float x01, float y01) noexcept
  176. {
  177. return { x10 - x00, x01 - x00, x00,
  178. y10 - y00, y01 - y00, y00 };
  179. }
  180. AffineTransform AffineTransform::fromTargetPoints (float sx1, float sy1, float tx1, float ty1,
  181. float sx2, float sy2, float tx2, float ty2,
  182. float sx3, float sy3, float tx3, float ty3) noexcept
  183. {
  184. return fromTargetPoints (sx1, sy1, sx2, sy2, sx3, sy3)
  185. .inverted()
  186. .followedBy (fromTargetPoints (tx1, ty1, tx2, ty2, tx3, ty3));
  187. }
  188. bool AffineTransform::isOnlyTranslation() const noexcept
  189. {
  190. return mat01 == 0.0f
  191. && mat10 == 0.0f
  192. && mat00 == 1.0f
  193. && mat11 == 1.0f;
  194. }
  195. float AffineTransform::getDeterminant() const noexcept
  196. {
  197. return (mat00 * mat11) - (mat01 * mat10);
  198. }
  199. float AffineTransform::getScaleFactor() const noexcept
  200. {
  201. return (std::abs (mat00) + std::abs (mat11)) / 2.0f;
  202. }
  203. //==============================================================================
  204. //==============================================================================
  205. #if JUCE_UNIT_TESTS
  206. class AffineTransformTests : public UnitTest
  207. {
  208. public:
  209. AffineTransformTests()
  210. : UnitTest ("AffineTransform", UnitTestCategories::maths)
  211. {}
  212. void runTest() override
  213. {
  214. beginTest ("Determinant");
  215. {
  216. constexpr float scale1 = 1.5f, scale2 = 1.3f;
  217. auto transform = AffineTransform::scale (scale1)
  218. .followedBy (AffineTransform::rotation (degreesToRadians (72.0f)))
  219. .followedBy (AffineTransform::translation (100.0f, 20.0f))
  220. .followedBy (AffineTransform::scale (scale2));
  221. expect (approximatelyEqual (std::sqrt (std::abs (transform.getDeterminant())), scale1 * scale2));
  222. }
  223. }
  224. };
  225. static AffineTransformTests timeTests;
  226. #endif
  227. } // namespace juce