00001 #region --- License ---
00002
00003
00004
00005
00006
00007
00008
00009 #endregion
00010
00011 using System;
00012 using System.Collections.Generic;
00013 using System.Text;
00014
00015 namespace OpenTK
00016 {
00020 [Serializable]
00021 public struct BezierCurve
00022 {
00023 #region Fields
00024
00025 private List<Vector2> points;
00026
00034 public float Parallel;
00035
00036 #endregion
00037
00038 #region Properties
00039
00044 public IList<Vector2> Points
00045 {
00046 get
00047 {
00048 return points;
00049 }
00050 }
00051
00052 #endregion
00053
00054 #region Constructors
00055
00060 public BezierCurve(IEnumerable<Vector2> points)
00061 {
00062 if (points == null)
00063 throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
00064
00065 this.points = new List<Vector2>(points);
00066 this.Parallel = 0.0f;
00067 }
00068
00073 public BezierCurve(params Vector2[] points)
00074 {
00075 if (points == null)
00076 throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
00077
00078 this.points = new List<Vector2>(points);
00079 this.Parallel = 0.0f;
00080 }
00081
00087 public BezierCurve(float parallel, params Vector2[] points)
00088 {
00089 if (points == null)
00090 throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
00091
00092 this.Parallel = parallel;
00093 this.points = new List<Vector2>(points);
00094 }
00095
00101 public BezierCurve(float parallel, IEnumerable<Vector2> points)
00102 {
00103 if (points == null)
00104 throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
00105
00106 this.Parallel = parallel;
00107 this.points = new List<Vector2>(points);
00108 }
00109
00110 #endregion
00111
00112 #region Functions
00113
00114
00120 public Vector2 CalculatePoint(float t)
00121 {
00122 return BezierCurve.CalculatePoint(points, t, Parallel);
00123 }
00124
00132 public float CalculateLength(float precision)
00133 {
00134 return BezierCurve.CalculateLength(points, precision, Parallel);
00135 }
00136
00137 #region Static methods
00138
00146 public static float CalculateLength(IList<Vector2> points, float precision)
00147 {
00148 return BezierCurve.CalculateLength(points, precision, 0.0f);
00149 }
00150
00164 public static float CalculateLength(IList<Vector2> points, float precision, float parallel)
00165 {
00166 float length = 0.0f;
00167 Vector2 old = BezierCurve.CalculatePoint(points, 0.0f, parallel);
00168
00169 for (float i = precision; i < (1.0f + precision); i += precision)
00170 {
00171 Vector2 n = CalculatePoint(points, i, parallel);
00172 length += (n - old).Length;
00173 old = n;
00174 }
00175
00176 return length;
00177 }
00178
00185 public static Vector2 CalculatePoint(IList<Vector2> points, float t)
00186 {
00187 return BezierCurve.CalculatePoint(points, t, 0.0f);
00188 }
00189
00201 public static Vector2 CalculatePoint(IList<Vector2> points, float t, float parallel)
00202 {
00203 Vector2 r = new Vector2();
00204 double c = 1.0d - (double)t;
00205 float temp;
00206 int i = 0;
00207
00208 foreach (Vector2 pt in points)
00209 {
00210 temp = (float)MathHelper.BinomialCoefficient(points.Count - 1, i) * (float)(System.Math.Pow(t, i) *
00211 System.Math.Pow(c, (points.Count - 1) - i));
00212
00213 r.X += temp * pt.X;
00214 r.Y += temp * pt.Y;
00215 i++;
00216 }
00217
00218 if (parallel == 0.0f)
00219 return r;
00220
00221 Vector2 perpendicular = new Vector2();
00222
00223 if (t != 0.0f)
00224 perpendicular = r - BezierCurve.CalculatePointOfDerivative(points, t);
00225 else
00226 perpendicular = points[1] - points[0];
00227
00228 return r + Vector2.Normalize(perpendicular).PerpendicularRight * parallel;
00229 }
00230
00237 private static Vector2 CalculatePointOfDerivative(IList<Vector2> points, float t)
00238 {
00239 Vector2 r = new Vector2();
00240 double c = 1.0d - (double)t;
00241 float temp;
00242 int i = 0;
00243
00244 foreach (Vector2 pt in points)
00245 {
00246 temp = (float)MathHelper.BinomialCoefficient(points.Count - 2, i) * (float)(System.Math.Pow(t, i) *
00247 System.Math.Pow(c, (points.Count - 2) - i));
00248
00249 r.X += temp * pt.X;
00250 r.Y += temp * pt.Y;
00251 i++;
00252 }
00253
00254 return r;
00255 }
00256
00257 #endregion
00258
00259 #endregion
00260 }
00261 }