1 #ifndef __DALI_INTERNAL_HISTORY_H__
2 #define __DALI_INTERNAL_HISTORY_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.
25 #include <dali/public-api/common/set-wrapper.h>
26 #include <dali/public-api/common/dali-common.h>
27 #include <dali/public-api/math/vector2.h>
37 * represents a key-value element in the HistoryContainer
40 struct HistoryPairType
44 HistoryPairType(float firstValue)
49 HistoryPairType(float firstValue, T secondValue)
55 bool operator<(const HistoryPairType& rhs) const
57 return first < rhs.first;
66 * This container is used for keeping a list of element pairs while providing an API that can
67 * generate interpolated values of requested elements that lie between two stored elements.
75 * Requesting value at key 1.5 will use the adjacent stored keys (1.0 and 2.0) to return an
76 * interpolated value of 20.0 (i.e. 0.5 of the way between 10 and 30).
78 * Requesting value at key 2.9 will use the adjacent stored keys (2.0 and 3.0) to return an
79 * interpolated value of 48.0 (i.e. 0.9 of the way between 30 and 50)
83 typedef HistoryPairType<Vector2> HistoryPair;
84 typedef std::set<HistoryPair> HistoryContainer;
85 typedef HistoryContainer::iterator HistoryContainerIter;
93 : mMaxSize(std::numeric_limits<size_t>::max())
105 * Sets the maximum size of the history container in terms of elements stored, default is no limit
106 * @param[in] maxSize The maximum number of elements stored in container
108 void SetMaxSize(size_t maxSize)
112 if(mHistory.size() > mMaxSize)
114 // determine reduction in history size, and remove these elements
115 size_t reduction = mHistory.size() - mMaxSize;
119 mHistory.erase(mHistory.begin() );
130 * Adds an element (y) to the container at position (x)
132 * @param[in] x Key position value to add
133 * @param[in] y Value to add at Key.
135 void Add(float x, const Vector2& y)
137 if(mHistory.size() >= mMaxSize)
142 mHistory.insert(HistoryPair(x,y));
146 * Removes first element in the container
150 mHistory.erase(mHistory.begin());
154 * Retrieves value from the history using key (x).
155 * If the requested key (x) lies between two points, a linearly interpolated value between the two
156 * points is returned.
158 * @param[in] x Key position to retrieve
160 * @return The interpolated Value is returned for this position.
162 Vector2 Get(float x) const
164 HistoryContainerIter i = mHistory.lower_bound(x);
166 if(i == mHistory.end())
171 // For samples based on first point, just return position.
172 if(i == mHistory.begin())
177 // within begin() ... end() range
179 Vector2 y2 = i->second;
183 Vector2 y1 = i->second;
185 // For samples based on first 2 points, just use linear interpolation
186 // TODO: Should really perform quadratic interpolation whenever there are 3+
188 if(i == mHistory.begin())
190 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
193 // For samples based elsewhere, always use quadratic interpolation.
196 Vector2 y0 = i->second;
198 if(i != mHistory.begin())
202 Vector2 yn = i->second;
204 x2 = (x2 + x1) * 0.5f;
205 x1 = (x1 + x0) * 0.5f;
206 x0 = (xn + x0) * 0.5f;
208 y2 = (y2 + y1) * 0.5f;
209 y1 = (y1 + y0) * 0.5f;
210 y0 = (yn + y0) * 0.5f;
212 // Quadratic equation:
215 // by making touches relative to x0, y0 (i.e. x0 = 0, y0 = 0)
216 // we get c = 0, and equation becomes:
218 // 1) Y1 = a . X1^2 + b X1
219 // 2) Y2 = a . X2^2 + b X2
220 // solving simulatenous equations gets:
222 // make time (x) & position (y) relative to x0, y0
230 Vector2 a = ( y1 - (y2 * x1) / x2 ) / (x1 * (x1 - x2) );
231 Vector2 b = ( y1 / x1 ) - (a * x1);
233 return a * x * x + b * x + y0;
237 * Retrieves a value from the history relative to the head.
239 * @note If the Keys (x) in the history decrease in value the further back you go. Then a
240 * negative deltaX value should be supplied to refer to these keys relative to the head key.
242 * @param[in] deltaX Key position to retrieve relative to head key
244 * @return The interpolated Value is returned for this relative position.
246 Vector2 GetRelativeToHead(float deltaX) const
248 HistoryContainerIter i = mHistory.end();
250 return Get(i->first + deltaX);
254 * Retrieves the head time value.
256 * @retrun The head time value.
258 float GetHeadTime() const
260 HistoryContainerIter i = mHistory.end();
261 if(i==mHistory.begin())
270 * Retrieves the head value.
272 * @return The head value.
274 Vector2 GetHead() const
276 HistoryContainerIter i = mHistory.end();
277 if(i==mHistory.begin())
287 HistoryContainer mHistory; ///< History container
288 size_t mMaxSize; ///< Current maximum size of container
292 } // namespace Internal
296 #endif // __DALI_INTERNAL_HISTORY_H__