BezierCurve.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <Mathematics/Array2.h>
  10. #include <Mathematics/ParametricCurve.h>
  11. namespace WwiseGTE
  12. {
  13. template <int N, typename Real>
  14. class BezierCurve : public ParametricCurve<N, Real>
  15. {
  16. public:
  17. // Construction and destruction. The number of control points must be
  18. // degree + 1. This object copies the input array. The domain is t
  19. // in [0,1]. To validate construction, create an object as shown:
  20. // BezierCurve<N, Real> curve(parameters);
  21. // if (!curve) { <constructor failed, handle accordingly>; }
  22. BezierCurve(int degree, Vector<N, Real> const* controls)
  23. :
  24. ParametricCurve<N, Real>((Real)0, (Real)1),
  25. mDegree(degree),
  26. mNumControls(degree + 1),
  27. mChoose(mNumControls, mNumControls)
  28. {
  29. LogAssert(degree >= 2 && controls != nullptr, "Invalid input.");
  30. // Copy the controls.
  31. mControls[0].resize(mNumControls);
  32. std::copy(controls, controls + mNumControls, mControls[0].begin());
  33. // Compute first-order differences.
  34. mControls[1].resize(mNumControls - 1);
  35. for (int i = 0; i < mNumControls - 1; ++i)
  36. {
  37. mControls[1][i] = mControls[0][i + 1] - mControls[0][i];
  38. }
  39. // Compute second-order differences.
  40. mControls[2].resize(mNumControls - 2);
  41. for (int i = 0; i < mNumControls - 2; ++i)
  42. {
  43. mControls[2][i] = mControls[1][i + 1] - mControls[1][i];
  44. }
  45. // Compute third-order differences.
  46. if (degree >= 3)
  47. {
  48. mControls[3].resize(mNumControls - 3);
  49. for (int i = 0; i < mNumControls - 3; ++i)
  50. {
  51. mControls[3][i] = mControls[2][i + 1] - mControls[2][i];
  52. }
  53. }
  54. // Compute combinatorial values Choose(n,k) and store in mChoose[n][k].
  55. // The values mChoose[r][c] are invalid for r < c; that is, we use only
  56. // the entries for r >= c.
  57. mChoose[0][0] = (Real)1;
  58. mChoose[1][0] = (Real)1;
  59. mChoose[1][1] = (Real)1;
  60. for (int i = 2; i <= mDegree; ++i)
  61. {
  62. mChoose[i][0] = (Real)1;
  63. mChoose[i][i] = (Real)1;
  64. for (int j = 1; j < i; ++j)
  65. {
  66. mChoose[i][j] = mChoose[i - 1][j - 1] + mChoose[i - 1][j];
  67. }
  68. }
  69. this->mConstructed = true;
  70. }
  71. virtual ~BezierCurve()
  72. {
  73. }
  74. // Member access.
  75. inline int GetDegree() const
  76. {
  77. return mDegree;
  78. }
  79. inline int GetNumControls() const
  80. {
  81. return mNumControls;
  82. }
  83. inline Vector<N, Real> const* GetControls() const
  84. {
  85. return &mControls[0][0];
  86. }
  87. // Evaluation of the curve. The function supports derivative
  88. // calculation through order 3; that is, order <= 3 is required. If
  89. // you want/ only the position, pass in order of 0. If you want the
  90. // position and first derivative, pass in order of 1, and so on. The
  91. // output array 'jet' must have enough storage to support the maximum
  92. // order. The values are ordered as: position, first derivative,
  93. // second derivative, third derivative.
  94. virtual void Evaluate(Real t, unsigned int order, Vector<N, Real>* jet) const override
  95. {
  96. unsigned int const supOrder = ParametricCurve<N, Real>::SUP_ORDER;
  97. if (!this->mConstructed || order >= supOrder)
  98. {
  99. // Return a zero-valued jet for invalid state.
  100. for (unsigned int i = 0; i < supOrder; ++i)
  101. {
  102. jet[i].MakeZero();
  103. }
  104. return;
  105. }
  106. // Compute position.
  107. Real omt = (Real)1 - t;
  108. jet[0] = Compute(t, omt, 0);
  109. if (order >= 1)
  110. {
  111. // Compute first derivative.
  112. jet[1] = Compute(t, omt, 1);
  113. if (order >= 2)
  114. {
  115. // Compute second derivative.
  116. jet[2] = Compute(t, omt, 2);
  117. if (order >= 3)
  118. {
  119. // Compute third derivative.
  120. if (mDegree >= 3)
  121. {
  122. jet[3] = Compute(t, omt, 3);
  123. }
  124. else
  125. {
  126. jet[3].MakeZero();
  127. }
  128. }
  129. }
  130. }
  131. }
  132. protected:
  133. // Support for Evaluate(...).
  134. Vector<N, Real> Compute(Real t, Real omt, int order) const
  135. {
  136. Vector<N, Real> result = omt * mControls[order][0];
  137. Real tpow = t;
  138. int isup = mDegree - order;
  139. for (int i = 1; i < isup; ++i)
  140. {
  141. Real c = mChoose[isup][i] * tpow;
  142. result = (result + c * mControls[order][i]) * omt;
  143. tpow *= t;
  144. }
  145. result = (result + tpow * mControls[order][isup]);
  146. int multiplier = 1;
  147. for (int i = 0; i < order; ++i)
  148. {
  149. multiplier *= mDegree - i;
  150. }
  151. result *= (Real)multiplier;
  152. return result;
  153. }
  154. int mDegree, mNumControls;
  155. std::array<std::vector<Vector<N, Real>>, ParametricCurve<N, Real>::SUP_ORDER> mControls;
  156. Array2<Real> mChoose;
  157. };
  158. }