PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/GoliatEditor/OpenTK/1.1/Source/Compatibility/Math/BezierCurve.cs

https://gitlab.com/gonzague.defraiteur/GoliatEditor
C# | 262 lines | 127 code | 41 blank | 94 comment | 13 complexity | 6df3a4618f76d10f4f10fa542f17b374 MD5 | raw file
  1. #region --- License ---
  2. /* Licensed under the MIT/X11 license.
  3. * Copyright (c) 2006-2008 the OpenTK Team.
  4. * This notice may not be removed from any source distribution.
  5. * See license.txt for licensing detailed licensing details.
  6. *
  7. * Contributions by Georg W�chter.
  8. */
  9. #endregion
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. namespace OpenTK.Math
  14. {
  15. /// <summary>
  16. /// Represents a bezier curve with as many points as you want.
  17. /// </summary>
  18. [Obsolete("OpenTK.Math functions have been moved to the root OpenTK namespace (reason: XNA compatibility")]
  19. [Serializable]
  20. public struct BezierCurve
  21. {
  22. #region Fields
  23. private List<Vector2> points;
  24. /// <summary>
  25. /// The parallel value.
  26. /// </summary>
  27. /// <remarks>This value defines whether the curve should be calculated as a
  28. /// parallel curve to the original bezier curve. A value of 0.0f represents
  29. /// the original curve, 5.0f i.e. stands for a curve that has always a distance
  30. /// of 5.0f to the orignal curve at any point.</remarks>
  31. public float Parallel;
  32. #endregion
  33. #region Properties
  34. /// <summary>
  35. /// Gets the points of this curve.
  36. /// </summary>
  37. /// <remarks>The first point and the last points represent the anchor points.</remarks>
  38. public IList<Vector2> Points
  39. {
  40. get
  41. {
  42. return points;
  43. }
  44. }
  45. #endregion
  46. #region Constructors
  47. /// <summary>
  48. /// Constructs a new <see cref="BezierCurve"/>.
  49. /// </summary>
  50. /// <param name="points">The points.</param>
  51. public BezierCurve(IEnumerable<Vector2> points)
  52. {
  53. if (points == null)
  54. throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
  55. this.points = new List<Vector2>(points);
  56. this.Parallel = 0.0f;
  57. }
  58. /// <summary>
  59. /// Constructs a new <see cref="BezierCurve"/>.
  60. /// </summary>
  61. /// <param name="points">The points.</param>
  62. public BezierCurve(params Vector2[] points)
  63. {
  64. if (points == null)
  65. throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
  66. this.points = new List<Vector2>(points);
  67. this.Parallel = 0.0f;
  68. }
  69. /// <summary>
  70. /// Constructs a new <see cref="BezierCurve"/>.
  71. /// </summary>
  72. /// <param name="parallel">The parallel value.</param>
  73. /// <param name="points">The points.</param>
  74. public BezierCurve(float parallel, params Vector2[] points)
  75. {
  76. if (points == null)
  77. throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
  78. this.Parallel = parallel;
  79. this.points = new List<Vector2>(points);
  80. }
  81. /// <summary>
  82. /// Constructs a new <see cref="BezierCurve"/>.
  83. /// </summary>
  84. /// <param name="parallel">The parallel value.</param>
  85. /// <param name="points">The points.</param>
  86. public BezierCurve(float parallel, IEnumerable<Vector2> points)
  87. {
  88. if (points == null)
  89. throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
  90. this.Parallel = parallel;
  91. this.points = new List<Vector2>(points);
  92. }
  93. #endregion
  94. #region Functions
  95. /// <summary>
  96. /// Calculates the point with the specified t.
  97. /// </summary>
  98. /// <param name="t">The t value, between 0.0f and 1.0f.</param>
  99. /// <returns>Resulting point.</returns>
  100. public Vector2 CalculatePoint(float t)
  101. {
  102. return BezierCurve.CalculatePoint(points, t, Parallel);
  103. }
  104. /// <summary>
  105. /// Calculates the length of this bezier curve.
  106. /// </summary>
  107. /// <param name="precision">The precision.</param>
  108. /// <returns>Length of curve.</returns>
  109. /// <remarks>The precision gets better as the <paramref name="precision"/>
  110. /// value gets smaller.</remarks>
  111. public float CalculateLength(float precision)
  112. {
  113. return BezierCurve.CalculateLength(points, precision, Parallel);
  114. }
  115. #region Static methods
  116. /// <summary>
  117. /// Calculates the length of the specified bezier curve.
  118. /// </summary>
  119. /// <param name="points">The points.</param>
  120. /// <param name="precision">The precision value.</param>
  121. /// <returns>The precision gets better as the <paramref name="precision"/>
  122. /// value gets smaller.</returns>
  123. public static float CalculateLength(IList<Vector2> points, float precision)
  124. {
  125. return BezierCurve.CalculateLength(points, precision, 0.0f);
  126. }
  127. /// <summary>
  128. /// Calculates the length of the specified bezier curve.
  129. /// </summary>
  130. /// <param name="points">The points.</param>
  131. /// <param name="precision">The precision value.</param>
  132. /// <param name="parallel">The parallel value.</param>
  133. /// <returns>Length of curve.</returns>
  134. /// <remarks><para>The precision gets better as the <paramref name="precision"/>
  135. /// value gets smaller.</para>
  136. /// <para>The <paramref name="parallel"/> parameter defines whether the curve should be calculated as a
  137. /// parallel curve to the original bezier curve. A value of 0.0f represents
  138. /// the original curve, 5.0f represents a curve that has always a distance
  139. /// of 5.0f to the orignal curve.</para></remarks>
  140. public static float CalculateLength(IList<Vector2> points, float precision, float parallel)
  141. {
  142. float length = 0.0f;
  143. Vector2 old = BezierCurve.CalculatePoint(points, 0.0f, parallel);
  144. for (float i = precision; i < (1.0f + precision); i += precision)
  145. {
  146. Vector2 n = CalculatePoint(points, i, parallel);
  147. length += (n - old).Length;
  148. old = n;
  149. }
  150. return length;
  151. }
  152. /// <summary>
  153. /// Calculates the point on the given bezier curve with the specified t parameter.
  154. /// </summary>
  155. /// <param name="points">The points.</param>
  156. /// <param name="t">The t parameter, a value between 0.0f and 1.0f.</param>
  157. /// <returns>Resulting point.</returns>
  158. public static Vector2 CalculatePoint(IList<Vector2> points, float t)
  159. {
  160. return BezierCurve.CalculatePoint(points, t, 0.0f);
  161. }
  162. /// <summary>
  163. /// Calculates the point on the given bezier curve with the specified t parameter.
  164. /// </summary>
  165. /// <param name="points">The points.</param>
  166. /// <param name="t">The t parameter, a value between 0.0f and 1.0f.</param>
  167. /// <param name="parallel">The parallel value.</param>
  168. /// <returns>Resulting point.</returns>
  169. /// <remarks>The <paramref name="parallel"/> parameter defines whether the curve should be calculated as a
  170. /// parallel curve to the original bezier curve. A value of 0.0f represents
  171. /// the original curve, 5.0f represents a curve that has always a distance
  172. /// of 5.0f to the orignal curve.</remarks>
  173. public static Vector2 CalculatePoint(IList<Vector2> points, float t, float parallel)
  174. {
  175. Vector2 r = new Vector2();
  176. double c = 1.0d - (double)t;
  177. float temp;
  178. int i = 0;
  179. foreach (Vector2 pt in points)
  180. {
  181. temp = (float)Functions.BinomialCoefficient(points.Count - 1, i) * (float)(System.Math.Pow(t, i) *
  182. System.Math.Pow(c, (points.Count - 1) - i));
  183. r.X += temp * pt.X;
  184. r.Y += temp * pt.Y;
  185. i++;
  186. }
  187. if (parallel == 0.0f)
  188. return r;
  189. Vector2 perpendicular = new Vector2();
  190. if (t != 0.0f)
  191. perpendicular = r - BezierCurve.CalculatePointOfDerivative(points, t);
  192. else
  193. perpendicular = points[1] - points[0];
  194. return r + Vector2.Normalize(perpendicular).PerpendicularRight * parallel;
  195. }
  196. /// <summary>
  197. /// Calculates the point with the specified t of the derivative of the given bezier function.
  198. /// </summary>
  199. /// <param name="points">The points.</param>
  200. /// <param name="t">The t parameter, value between 0.0f and 1.0f.</param>
  201. /// <returns>Resulting point.</returns>
  202. private static Vector2 CalculatePointOfDerivative(IList<Vector2> points, float t)
  203. {
  204. Vector2 r = new Vector2();
  205. double c = 1.0d - (double)t;
  206. float temp;
  207. int i = 0;
  208. foreach (Vector2 pt in points)
  209. {
  210. temp = (float)Functions.BinomialCoefficient(points.Count - 2, i) * (float)(System.Math.Pow(t, i) *
  211. System.Math.Pow(c, (points.Count - 2) - i));
  212. r.X += temp * pt.X;
  213. r.Y += temp * pt.Y;
  214. i++;
  215. }
  216. return r;
  217. }
  218. #endregion
  219. #endregion
  220. }
  221. }