1 #ifndef __DALI_SPLINE_H__
2 #define __DALI_SPLINE_H__
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
27 namespace Dali DALI_IMPORT_API
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).
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.
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)
64 * @brief Add a knot to the spline.
66 * @param[in] knot - the point or knot to add.
68 void AddKnot(Vector3 knot);
71 * @brief Get the knot at the given index.
73 * @param[in] knotIndex the index of the knot
74 * @return the knot vector
76 Vector3 GetKnot(size_t knotIndex);
79 * @brief Get the in tangent (or in control point) at the given index.
81 * @param[in] knotIndex the index of the knot
82 * @return the in tangent (or in control point)
84 Vector3 GetInTangent(size_t knotIndex);
87 * @brief Get the out tangent (or out control point) at the given index.
89 * @param[in] knotIndex the index of the knot
90 * @return the out tangent (or out control point)
92 Vector3 GetOutTangent(size_t knotIndex);
95 * @brief Set an in-tangent for the given knot.
97 * @param[in] knotIndex - the index of the knot
98 * @param[in] inTangent - The in tangent or control point, depending on the spline type
100 void SetInTangent(size_t knotIndex, Vector3 inTangent);
103 * @brief Set an out-tangent for the given knot.
105 * @param[in] knotIndex - the index of the knot
106 * @param[in] outTangent - The out tangent or control point, depending on the spline type
108 void SetOutTangent(size_t knotIndex, Vector3 outTangent);
111 * @brief For the given set of knot points, generate control points which result in a smooth join between the splines of each segment.
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
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.
125 void GenerateControlPoints(float curvature=0.25f);
128 * @brief Get the number of segments.
130 * This is the number of points - 1, or zero if there are fewer than 2 points.
131 * @return the number of segments
133 unsigned int GetNumberOfSegments() const;
136 * @brief Given an alpha value 0.0-1.0, return the associated point on the entire
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.
143 * @param[in] alpha - the overall parameter value.
144 * @return point - the interpolated point.
146 const Vector3 GetPoint(float alpha) const;
149 * @brief Given a parameter 0.0 - 1.0, return the associated point
150 * on the spline given the relevant segment.
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.
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.
160 const Vector3 GetPoint(unsigned int segmentIndex, float parameter) const;
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.
167 * @return the Y value
169 const float GetYFromMonotonicX(float x) const;
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.
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
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
184 const float GetY(unsigned int segmentIndex, float parameter) const;
189 * @brief FindSegment searches through the control points to find the appropriate
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.
196 const bool FindSegment(float x, int& segmentIndex) const;
199 * @brief Given two knots and control points, interpolate to find the
200 * parameter that will give the required X value.
202 * Requires that X is monotonic.
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.
211 const float ApproximateCubicBezierParameter (float atX, float P0_X, float C0_X, float C1_X, float P1_X ) const;
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)
218 Matrix mBasis; ///< The basis matrix to use
220 static const float BezierBasisA[]; ///< The basis matrix for Bezier splines
225 #endif //__DALI_SPLINE_H__