#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
* Contributions by Georg W�chter.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Math
{
///
/// Represents a cubic bezier curve with two anchor and two control points.
///
[Serializable]
public struct BezierCurveCubic
{
#region Fields
///
/// Start anchor point.
///
public Vector2 StartAnchor;
///
/// End anchor point.
///
public Vector2 EndAnchor;
///
/// First control point, controls the direction of the curve start.
///
public Vector2 FirstControlPoint;
///
/// Second control point, controls the direction of the curve end.
///
public Vector2 SecondControlPoint;
///
/// Gets or sets the parallel value.
///
/// This value defines whether the curve should be calculated as a
/// parallel curve to the original bezier curve. A value of 0.0f represents
/// the original curve, 5.0f i.e. stands for a curve that has always a distance
/// of 5.f to the orignal curve at any point.
public float Parallel;
#endregion
#region Constructors
///
/// Constructs a new .
///
/// The start anchor point.
/// The end anchor point.
/// The first control point.
/// The second control point.
public BezierCurveCubic(Vector2 startAnchor, Vector2 endAnchor, Vector2 firstControlPoint, Vector2 secondControlPoint)
{
this.StartAnchor = startAnchor;
this.EndAnchor = endAnchor;
this.FirstControlPoint = firstControlPoint;
this.SecondControlPoint = secondControlPoint;
this.Parallel = 0.0f;
}
///
/// Constructs a new .
///
/// The parallel value.
/// The start anchor point.
/// The end anchor point.
/// The first control point.
/// The second control point.
public BezierCurveCubic(float parallel, Vector2 startAnchor, Vector2 endAnchor, Vector2 firstControlPoint, Vector2 secondControlPoint)
{
this.Parallel = parallel;
this.StartAnchor = startAnchor;
this.EndAnchor = endAnchor;
this.FirstControlPoint = firstControlPoint;
this.SecondControlPoint = secondControlPoint;
}
#endregion
#region Functions
///
/// Calculates the point with the specified t.
///
/// The t value, between 0.0f and 1.0f.
/// Resulting point.
public Vector2 CalculatePoint(float t)
{
Vector2 r = new Vector2();
float c = 1.0f - t;
r.X = (StartAnchor.X * c * c * c) + (FirstControlPoint.X * 3 * t * c * c) + (SecondControlPoint.X * 3 * t * t * c)
+ EndAnchor.X * t * t * t;
r.Y = (StartAnchor.Y * c * c * c) + (FirstControlPoint.Y * 3 * t * c * c) + (SecondControlPoint.Y * 3 * t * t * c)
+ EndAnchor.Y * t * t * t;
if (Parallel == 0.0f)
return r;
Vector2 perpendicular = new Vector2();
if (t == 0.0f)
perpendicular = FirstControlPoint - StartAnchor;
else
perpendicular = r - CalculatePointOfDerivative(t);
return r + Vector2.Normalize(perpendicular).PerpendicularRight * Parallel;
}
///
/// Calculates the point with the specified t of the derivative of this function.
///
/// The t, value between 0.0f and 1.0f.
/// Resulting point.
private Vector2 CalculatePointOfDerivative(float t)
{
Vector2 r = new Vector2();
float c = 1.0f - t;
r.X = (c * c * StartAnchor.X) + (2 * t * c * FirstControlPoint.X) + (t * t * SecondControlPoint.X);
r.Y = (c * c * StartAnchor.Y) + (2 * t * c * FirstControlPoint.Y) + (t * t * SecondControlPoint.Y);
return r;
}
///
/// Calculates the length of this bezier curve.
///
/// The precision.
/// Length of the curve.
/// The precision gets better when the
/// value gets smaller.
public float CalculateLength(float precision)
{
float length = 0.0f;
Vector2 old = CalculatePoint(0.0f);
for (float i = precision; i < (1.0f + precision); i += precision)
{
Vector2 n = CalculatePoint(i);
length += (n - old).Length;
old = n;
}
return length;
}
#endregion
}
}