License conversion from Flora to Apache 2.0
[platform/core/uifw/dali-core.git] / dali / public-api / geometry / spline.h
1 #ifndef __DALI_SPLINE_H__
2 #define __DALI_SPLINE_H__
3
4 /*
5  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21
22 // INTERNAL INCLUDES
23 #include <dali/public-api/common/vector-wrapper.h>
24 #include <dali/public-api/math/vector2.h>
25 #include <dali/public-api/math/matrix.h>
26
27 namespace Dali DALI_IMPORT_API
28 {
29
30 class Matrix;
31 struct Vector3;
32
33 /**
34  * @brief The Spline class is used to interpolate through a series of points
35  * (or knots) which are open (the end points do not connect).
36  *
37  * In Hermite splines, each knot has an in-tangent and an
38  * out-tangent associated with it. In the case of Bezier splines,
39  * there are equivalent control points.
40  *
41  * Once the spline is initialized with AddKnot(), SetInTangent() and
42  * SetOutTangent(), the client can choose to use either parametric
43  * interpolation (using GetPoint()), or calculate a Y value from an X
44  * value (using GetYFromMonotonicX()). The latter requires that the
45  * curve is monotonic along X (i.e. for any given X value there is
46  * exactly 1 Y value). Thus, the initial points and tangents have to
47  * be chosen carefully. (Most useful for animation curves)
48  *
49  */
50 class Spline
51 {
52 public:
53   /**
54    * @brief Constructor.
55    */
56   Spline();
57
58   /**
59    * @brief Destructor.
60    */
61   virtual ~Spline();
62
63   /**
64    * @brief Add a knot to the spline.
65    *
66    * @param[in] knot - the point or knot to add.
67    */
68   void AddKnot(Vector3 knot);
69
70   /**
71    * @brief Get the knot at the given index.
72    *
73    * @param[in] knotIndex the index of the knot
74    * @return the knot vector
75    */
76   Vector3 GetKnot(size_t knotIndex);
77
78   /**
79    * @brief Get the in tangent (or in control point) at the given index.
80    *
81    * @param[in] knotIndex the index of the knot
82    * @return the in tangent (or in control point)
83    */
84   Vector3 GetInTangent(size_t knotIndex);
85
86   /**
87    * @brief Get the out tangent (or out control point) at the given index.
88    *
89    * @param[in] knotIndex the index of the knot
90    * @return the out tangent (or out control point)
91    */
92   Vector3 GetOutTangent(size_t knotIndex);
93
94   /**
95    * @brief Set an in-tangent for the given knot.
96    *
97    * @param[in] knotIndex - the index of the knot
98    * @param[in] inTangent - The in tangent or control point, depending on the spline type
99    */
100   void SetInTangent(size_t knotIndex, Vector3 inTangent);
101
102   /**
103    * @brief Set an out-tangent for the given knot.
104    *
105    * @param[in] knotIndex - the index of the knot
106    * @param[in] outTangent - The out tangent or control point, depending on the spline type
107    */
108   void SetOutTangent(size_t knotIndex, Vector3 outTangent);
109
110   /**
111    * @brief For the given set of knot points, generate control points which result in a smooth join between the splines of each segment.
112    *
113    * The generating algorithm is as follows:
114    * For a given knot point K[N], find the vector that bisects K[N-1],[N] and [N],[N+1].
115    * Calculate the tangent vector by taking the normal of this bisector.
116    * The in control point is the length of the preceding segment back along this bisector multiplied by the curvature
117    * The out control point is the length of the succceding segment forward along this bisector multiplied by the curvature
118    *
119    * @param[in] curvature The curvature of the spline. 0 gives straight lines between the knots,
120    *                      negative values means the spline contains loops, positive values up to
121    *                      0.5 result in a smooth curve, positive values between 0.5 and 1 result
122    *                      in looped curves where the loops are not distinct (i.e. the curve appears
123    *                      to be non-continuous), positive values higher than 1 result in looped curves.
124    */
125   void GenerateControlPoints(float curvature=0.25f);
126
127   /**
128    * @brief Get the number of segments.
129    *
130    * This is the number of points - 1, or zero if there are fewer than 2 points.
131    * @return the number of segments
132    */
133   unsigned int GetNumberOfSegments() const;
134
135   /**
136    * @brief Given an alpha value 0.0-1.0, return the associated point on the entire
137    * spline.
138    *
139    * The alpha value is split into each segment equally, so doesn't give a
140    * constant speed along the spline.  An alpha value of 0.0 returns the first knot
141    * and an alpha value of 1.0 returns the last knot.
142    *
143    * @param[in] alpha - the overall parameter value.
144    * @return point - the interpolated point.
145    */
146   const Vector3 GetPoint(float alpha) const;
147
148   /**
149    * @brief Given a parameter 0.0 - 1.0, return the associated point
150    * on the spline given the relevant segment.
151    *
152    * Note, the parameter does not correspond to an axis, neither is it
153    * necessarily equally spaced along the curve.  If the parameter is
154    * 0.0 or 1.0, then the first or second knot point is returned.
155    *
156    * @param[in] segmentIndex the segment of the spline to interpolation.
157    * @param[in] parameter    the parameter to use in the parametric formula
158    * @return point           the interpolated point.
159    */
160   const Vector3 GetPoint(unsigned int segmentIndex, float parameter) const;
161
162   /**
163    * @brief Given a value X on the spline (between the first and last knot inclusively),
164    * calculate the corresponding Y value. Requires that there is only 1 Y per X.
165    *
166    * @param[in] x The X
167    * @return the Y value
168    */
169   const float GetYFromMonotonicX(float x) const;
170
171   /**
172    * @brief For a 2 dimensional curve (z=0), given a parameter 0.0 - 1.0, return the
173    * associated Y value on the spline given the relevant segment.
174    *
175    * Note, the parameter does not correspond to an axis, neither is it
176    * necessarily equally spaced along the curve.  If the parameter is
177    * 0.0 or 1.0, then the first or second knot point's Y value is
178    * returned.
179    *
180    * @param[in] segmentIndex - the segment of the spline to interpolation.
181    * @param[in] parameter    - the parameter to use in the parametric formula
182    * @return y value    - the interpolated point's Y value
183    */
184   const float GetY(unsigned int segmentIndex, float parameter) const;
185
186
187 private:
188   /**
189    * @brief FindSegment searches through the control points to find the appropriate
190    * segment.
191    *
192    * @param[in]  x            - the X value to search for
193    * @param[out] segmentIndex - the returned segment index
194    * @return True if the segment was found.
195    */
196   const bool FindSegment(float x, int& segmentIndex) const;
197
198   /**
199    * @brief Given two knots and control points, interpolate to find the
200    * parameter that will give the required X value.
201    *
202    * Requires that X is monotonic.
203    *
204    * @param[in] atX  the X value to search for
205    * @param[in] P0_X the starting knot's X
206    * @param[in] C0_X the X of the control point for the first knot
207    * @param[in] C1_X the X of the control point for the second knot
208    * @param[in] P1_X the ending knot's X.
209    * @return         the corresponding parameter.
210    */
211   const float ApproximateCubicBezierParameter (float atX, float P0_X, float C0_X, float C1_X, float P1_X ) const;
212
213 private:
214   std::vector<Vector3>   mKnots;          ///< The set of knot points
215   std::vector<Vector3>   mOutTangents;    ///< The set of out tangents (matching to mKnots)
216   std::vector<Vector3>   mInTangents;     ///< The set of in tangents  (matching to mKnots)
217
218   Matrix                 mBasis;          ///< The basis matrix to use
219
220   static const float     BezierBasisA[];  ///< The basis matrix for Bezier splines
221 };
222
223 } //namespace Dali
224
225 #endif //__DALI_SPLINE_H__