1 #ifndef __DALI_INTERNAL_HISTORY_H__
2 #define __DALI_INTERNAL_HISTORY_H__
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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/dali-common.h>
26 #include <dali/public-api/math/vector2.h>
36 * represents a key-value element in the HistoryContainer
39 struct HistoryPairType
43 HistoryPairType(float firstValue)
48 HistoryPairType(float firstValue, T secondValue)
54 bool operator<(const HistoryPairType& rhs) const
56 return first < rhs.first;
65 * This container is used for keeping a list of element pairs while providing an API that can
66 * generate interpolated values of requested elements that lie between two stored elements.
74 * Requesting value at key 1.5 will use the adjacent stored keys (1.0 and 2.0) to return an
75 * interpolated value of 20.0 (i.e. 0.5 of the way between 10 and 30).
77 * Requesting value at key 2.9 will use the adjacent stored keys (2.0 and 3.0) to return an
78 * interpolated value of 48.0 (i.e. 0.9 of the way between 30 and 50)
82 typedef HistoryPairType<Vector2> HistoryPair;
83 typedef std::set<HistoryPair> HistoryContainer;
84 typedef HistoryContainer::iterator HistoryContainerIter;
92 : mMaxSize(std::numeric_limits<size_t>::max())
104 * Sets the maximum size of the history container in terms of elements stored, default is no limit
105 * @param[in] maxSize The maximum number of elements stored in container
107 void SetMaxSize(size_t maxSize)
111 if(mHistory.size() > mMaxSize)
113 // determine reduction in history size, and remove these elements
114 size_t reduction = mHistory.size() - mMaxSize;
118 mHistory.erase(mHistory.begin() );
129 * Adds an element (y) to the container at position (x)
131 * @param[in] x Key position value to add
132 * @param[in] y Value to add at Key.
134 void Add(float x, const Vector2& y)
136 if(mHistory.size() >= mMaxSize)
141 mHistory.insert(HistoryPair(x,y));
145 * Removes first element in the container
149 mHistory.erase(mHistory.begin());
153 * Retrieves value from the history using key (x).
154 * If the requested key (x) lies between two points, a linearly interpolated value between the two
155 * points is returned.
157 * @param[in] x Key position to retrieve
159 * @return The interpolated Value is returned for this position.
161 Vector2 Get(float x) const
163 HistoryContainerIter i = mHistory.lower_bound(x);
165 if(i == mHistory.end())
170 // For samples based on first point, just return position.
171 if(i == mHistory.begin())
176 // within begin() ... end() range
178 Vector2 y2 = i->second;
182 Vector2 y1 = i->second;
184 // For samples based on first 2 points, just use linear interpolation
185 // TODO: Should really perform quadratic interpolation whenever there are 3+
187 if(i == mHistory.begin())
189 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
192 // For samples based elsewhere, always use quadratic interpolation.
195 Vector2 y0 = i->second;
197 if(i != mHistory.begin())
201 Vector2 yn = i->second;
203 x2 = (x2 + x1) * 0.5f;
204 x1 = (x1 + x0) * 0.5f;
205 x0 = (xn + x0) * 0.5f;
207 y2 = (y2 + y1) * 0.5f;
208 y1 = (y1 + y0) * 0.5f;
209 y0 = (yn + y0) * 0.5f;
211 // Quadratic equation:
214 // by making touches relative to x0, y0 (i.e. x0 = 0, y0 = 0)
215 // we get c = 0, and equation becomes:
217 // 1) Y1 = a . X1^2 + b X1
218 // 2) Y2 = a . X2^2 + b X2
219 // solving simulatenous equations gets:
221 // make time (x) & position (y) relative to x0, y0
229 Vector2 a = ( y1 - (y2 * x1) / x2 ) / (x1 * (x1 - x2) );
230 Vector2 b = ( y1 / x1 ) - (a * x1);
232 return a * x * x + b * x + y0;
236 * Retrieves a value from the history relative to the head.
238 * @note If the Keys (x) in the history decrease in value the further back you go. Then a
239 * negative deltaX value should be supplied to refer to these keys relative to the head key.
241 * @param[in] deltaX Key position to retrieve relative to head key
243 * @return The interpolated Value is returned for this relative position.
245 Vector2 GetRelativeToHead(float deltaX) const
247 HistoryContainerIter i = mHistory.end();
249 return Get(i->first + deltaX);
253 * Retrieves the head time value.
255 * @retrun The head time value.
257 float GetHeadTime() const
259 HistoryContainerIter i = mHistory.end();
260 if(i==mHistory.begin())
269 * Retrieves the head value.
271 * @return The head value.
273 Vector2 GetHead() const
275 HistoryContainerIter i = mHistory.end();
276 if(i==mHistory.begin())
286 HistoryContainer mHistory; ///< History container
287 size_t mMaxSize; ///< Current maximum size of container
291 } // namespace Internal
295 #endif // __DALI_INTERNAL_HISTORY_H__