Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1452 chris 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
 
11
using System;
12
using System.Collections.Generic;
13
using System.Text;
14
 
15
namespace OpenTK
16
{
17
    /// <summary>
18
    /// Represents a cubic bezier curve with two anchor and two control points.
19
    /// </summary>
20
    [Serializable]
21
    public struct BezierCurveCubic
22
    {
23
        #region Fields
24
 
25
        /// <summary>
26
        /// Start anchor point.
27
        /// </summary>
28
        public Vector2 StartAnchor;
29
 
30
        /// <summary>
31
        /// End anchor point.
32
        /// </summary>
33
        public Vector2 EndAnchor;
34
 
35
        /// <summary>
36
        /// First control point, controls the direction of the curve start.
37
        /// </summary>
38
        public Vector2 FirstControlPoint;
39
 
40
        /// <summary>
41
        /// Second control point, controls the direction of the curve end.
42
        /// </summary>
43
        public Vector2 SecondControlPoint;
44
 
45
        /// <summary>
46
        /// Gets or sets the parallel value.
47
        /// </summary>
48
        /// <remarks>This value defines whether the curve should be calculated as a
49
        /// parallel curve to the original bezier curve. A value of 0.0f represents
50
        /// the original curve, 5.0f i.e. stands for a curve that has always a distance
51
        /// of 5.f to the orignal curve at any point.</remarks>
52
        public float Parallel;
53
 
54
        #endregion
55
 
56
        #region Constructors
57
 
58
        /// <summary>
59
        /// Constructs a new <see cref="BezierCurveCubic"/>.
60
        /// </summary>
61
        /// <param name="startAnchor">The start anchor point.</param>
62
        /// <param name="endAnchor">The end anchor point.</param>
63
        /// <param name="firstControlPoint">The first control point.</param>
64
        /// <param name="secondControlPoint">The second control point.</param>
65
        public BezierCurveCubic(Vector2 startAnchor, Vector2 endAnchor, Vector2 firstControlPoint, Vector2 secondControlPoint)
66
        {
67
            this.StartAnchor = startAnchor;
68
            this.EndAnchor = endAnchor;
69
            this.FirstControlPoint = firstControlPoint;
70
            this.SecondControlPoint = secondControlPoint;
71
            this.Parallel = 0.0f;
72
        }
73
 
74
        /// <summary>
75
        /// Constructs a new <see cref="BezierCurveCubic"/>.
76
        /// </summary>
77
        /// <param name="parallel">The parallel value.</param>
78
        /// <param name="startAnchor">The start anchor point.</param>
79
        /// <param name="endAnchor">The end anchor point.</param>
80
        /// <param name="firstControlPoint">The first control point.</param>
81
        /// <param name="secondControlPoint">The second control point.</param>
82
        public BezierCurveCubic(float parallel, Vector2 startAnchor, Vector2 endAnchor, Vector2 firstControlPoint, Vector2 secondControlPoint)
83
        {
84
            this.Parallel = parallel;
85
            this.StartAnchor = startAnchor;
86
            this.EndAnchor = endAnchor;
87
            this.FirstControlPoint = firstControlPoint;
88
            this.SecondControlPoint = secondControlPoint;
89
        }
90
 
91
        #endregion
92
 
93
        #region Functions
94
 
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
            Vector2 r = new Vector2();
103
            float c = 1.0f - t;
104
 
105
            r.X = (StartAnchor.X * c * c * c) + (FirstControlPoint.X * 3 * t * c * c) + (SecondControlPoint.X * 3 * t * t * c)
106
                + EndAnchor.X * t * t * t;
107
            r.Y = (StartAnchor.Y * c * c * c) + (FirstControlPoint.Y * 3 * t * c * c) + (SecondControlPoint.Y * 3 * t * t * c)
108
                + EndAnchor.Y * t * t * t;
109
 
110
            if (Parallel == 0.0f)
111
                return r;
112
 
113
            Vector2 perpendicular = new Vector2();
114
 
115
            if (t == 0.0f)
116
                perpendicular = FirstControlPoint - StartAnchor;
117
            else
118
                perpendicular = r - CalculatePointOfDerivative(t);
119
 
120
            return r + Vector2.Normalize(perpendicular).PerpendicularRight * Parallel;
121
        }
122
 
123
        /// <summary>
124
        /// Calculates the point with the specified t of the derivative of this function.
125
        /// </summary>
126
        /// <param name="t">The t, value between 0.0f and 1.0f.</param>
127
        /// <returns>Resulting point.</returns>
128
        private Vector2 CalculatePointOfDerivative(float t)
129
        {
130
            Vector2 r = new Vector2();
131
            float c = 1.0f - t;
132
 
133
            r.X = (c * c * StartAnchor.X) + (2 * t * c * FirstControlPoint.X) + (t * t * SecondControlPoint.X);
134
            r.Y = (c * c * StartAnchor.Y) + (2 * t * c * FirstControlPoint.Y) + (t * t * SecondControlPoint.Y);
135
 
136
            return r;
137
        }
138
 
139
        /// <summary>
140
        /// Calculates the length of this bezier curve.
141
        /// </summary>
142
        /// <param name="precision">The precision.</param>
143
        /// <returns>Length of the curve.</returns>
144
        /// <remarks>The precision gets better when the <paramref name="precision"/>
145
        /// value gets smaller.</remarks>
146
        public float CalculateLength(float precision)
147
        {
148
            float length = 0.0f;
149
            Vector2 old = CalculatePoint(0.0f);
150
 
151
            for (float i = precision; i < (1.0f + precision); i += precision)
152
            {
153
                Vector2 n = CalculatePoint(i);
154
                length += (n - old).Length;
155
                old = n;
156
            }
157
 
158
            return length;
159
        }
160
 
161
        #endregion
162
    }
163
}