API Documentation
Loading...
Searching...
No Matches
TimePath.h
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Design
28File: TimePath
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Buffer.h>
34#include <NDEVR/Time.h>
35#include <NDEVR/TimeSpan.h>
36namespace NDEVR
37{
38 class Path
39 {
40 public:
42 {}
43 Path(const Buffer<Time>& time, const Buffer<fltp04>& y, const Buffer<fltp04>& m)
44 : mX(time)
45 , mY(y)
46 , mM(m)
47 {}
48
49 Path(const Path& path)
50 : mX(path.mX)
51 , mY(path.mY)
52 , mM(path.mM)
53 {}
54
55 Path(const Path&& path)
56 : mX(std::move(path.mX))
57 , mY(std::move(path.mY))
58 , mM(std::move(path.mM))
59 {}
60
61 fltp08 interpolateX(const Time& current_time)
62 {
63 // Handle the boundary cases.
64 uint04 n = mX.size();
65 if (isNaN(current_time) || n == 0) {
67 }
68 if (current_time <= mX[0]) {
69 return mY[0];
70 }
71 if (current_time >= mX.last()) {
72 return mY.last();
73 }
74 // Find the index 'i' of the last point with smaller X.
75 // We know this will be within the spline due to the boundary tests.
76 int i = 0;
77 while (current_time >= mX[i + 1])
78 {
79 i += 1;
80 if (current_time == mX[i])
81 return mY[i];
82 }
83 // Perform cubic Hermite spline interpolation.
84 fltp08 h = (mX[i + 1] - mX[i]).elapsedSeconds();
85 fltp08 t = (current_time - mX[i]).elapsedSeconds() / h;
86 return (mY[i] * (1 + 2 * t) + h * mM[i] * t) * (1 - t) * (1 - t)
87 + (mY[i + 1] * (3 - 2 * t) + h * mM[i + 1] * (t - 1)) * t * t;
88 }
89
91 {
92 if (time.size() != y.size() || time.size() < 2)
93 throw Exception("There must be at least two control points and the arrays must be of equal length.");
94 uint04 n = time.size();
95 fltp04 object = 0.0f;
96 Buffer<fltp04> dx(n - 1, object); // could optimize this out
97 Buffer<fltp04> mx(n, object);
98 // Compute slopes of secant lines between successive points.
99 for (uint04 i = 0; i < n - 1; i++)
100 {
101 fltp08 h = (time[i + 1] - time[i]).elapsedSeconds();
102 if (h < 0.0)
103 throw Exception("The control points must all have strictly increasing X values:" + String(time[i]) + " " + String(time[i + 1]));
104 dx[i] = (y[i + 1] - y[i]) / h;
105
106 }
107 // Initialize the tangents as the average of the secants.
108 mx[0] = dx[0];
109 for (uint04 i = 1; i < n - 1; i++)
110 {
111 mx[i] = (dx[i - 1] + dx[i]) * 0.5f;
112 }
113 mx[n - 1] = dx[n - 2];
114
115 // Update the tangents to preserve monotonicity.
116 for (uint04 i = 0; i < n - 1; i++)
117 {
118 if (dx[i] == 0.0f)
119 { // successive Y values are equal
120 mx[i] = 0.0f;
121 mx[i + 1] = 0.0f;
122 }
123 else
124 {
125 float a = mx[i] / dx[i];
126 float b = mx[i + 1] / dx[i];
127 if (a < 0.0f || b < 0.0f) {
128 //throw new IllegalArgumentException("The control points must have "
129 //+ "monotonic Y values.");
130 }
131 float h = (float)hypot(a, b);
132 if (h > 9.0f) {
133 float t = 3.0f / h;
134 mx[i] = t * a * dx[i];
135 mx[i + 1] = t * b * dx[i];
136 }
137 }
138 }
139 return Path(time, y, mx);
140 }
141
143 {
144 if (time.size() != y.size() || time.size() < 2)
145 {
146 throw new Exception("There must be at least two control points and the arrays must be of equal length.");
147 }
148 Buffer<Time> temp_time(y.size() * 2);
149 Buffer<fltp04> temp_y(y.size() * 2);
150 for (int i = 0; i < time.size() - 1; i++)
151 {
152 temp_y.add(y[i].as<DEGREES>());
153 temp_time.add(time[i]);
154 if((y[i].as<DEGREES>() - y[i + 1].as<DEGREES>()) > 180.0)
155 {
156 temp_y.add( 179.99);
157 temp_y.add(-179.99);
158 temp_time.add(time[i] + (time[i + 1] - time[i]) / 2.0);
159 temp_time.add(time[i] + (time[i + 1] - time[i]) / 2.0);
160 }
161 if ((y[i].as<DEGREES>() - y[i + 1].as<DEGREES>()) > 180.0)
162 {
163 temp_y.add(-179.99);
164 temp_y.add( 179.99);
165 temp_time.add(time[i] + (time[i + 1] - time[i]) / 2.0);
166 temp_time.add(time[i] + (time[i + 1] - time[i]) / 2.0);
167 }
168 }
169 return createMonotoneCubicPath(temp_time, temp_y);
170 }
171
173 {
174 Buffer<std::pair<Time, fltp04>> sorted_path(time.size());
175 for (uint04 i = 0; i < time.size(); i++)
176 {
177 sorted_path.add(std::pair<Time, fltp04>(time[i], y[i]));
178 }
179 std::sort(sorted_path.begin(), sorted_path.end(), [](const std::pair<Time, fltp04>& p1, const std::pair<Time, fltp04>& p2)
180 {
181 return p1.first > p2.first;
182 });
183 Buffer<Time> corrected_time(time.size());
184 Buffer<fltp04> corrected_value(time.size());
185 for (uint04 i = 0; i < time.size(); i++)
186 {
187 corrected_value.add(sorted_path[i].second);
188 corrected_time.add(sorted_path[i].first);
189 }
190 return createMonotoneCubicPath(corrected_time, corrected_value);
191 }
193 {
194 Buffer<std::pair<Time, Angle<fltp08>>> sorted_path(time.size());
195 for (uint04 i = 0; i < time.size(); i++)
196 {
197 sorted_path.add(std::pair<Time, Angle<fltp08>>(time[i], y[i]));
198 }
199 std::sort(sorted_path.begin(), sorted_path.end(), [](const std::pair<Time, Angle<fltp08>>& p1, const std::pair<Time, Angle<fltp08>>& p2)
200 {
201 return p1.first > p2.first;
202 });
203 Buffer<Time> corrected_time(time.size());
204 Buffer<Angle<fltp08>> corrected_value(time.size());
205 for (uint04 i = 0; i < time.size(); i++)
206 {
207 corrected_value.add(sorted_path[i].second);
208 corrected_time.add(sorted_path[i].first);
209 }
210 return createMonotoneCubicPathAzimuth(corrected_time, corrected_value);
211 }
212
213 Path& operator=(const Path& path)
214 {
215 mX = path.mX;
216 mY = path.mY;
217 mM = path.mM;
218 return *this;
219 }
220 protected:
224 };
225}
226
227
228
229
Stores an angle in an optimized format.
Definition StringStream.h:352
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:64
void add(t_type &&object)
Definition Buffer.hpp:199
constexpr t_index_type size() const
Definition Buffer.hpp:1461
decltype(auto) last()
Definition Buffer.hpp:977
decltype(auto) end()
Definition Buffer.hpp:746
decltype(auto) begin()
Definition Buffer.hpp:504
Definition Exception.hpp:56
Definition TimePath.h:39
static Path createMonotoneCubicPathSorted(const Buffer< Time > &time, const Buffer< fltp04 > &y)
Definition TimePath.h:172
Path & operator=(const Path &path)
Definition TimePath.h:213
static Path createMonotoneAngleCubicPathSorted(const Buffer< Time > &time, const Buffer< Angle< fltp08 > > &y)
Definition TimePath.h:192
Path(const Path &path)
Definition TimePath.h:49
Buffer< Time > mX
Definition TimePath.h:221
static Path createMonotoneCubicPath(const Buffer< Time > &time, const Buffer< fltp04 > &y)
Definition TimePath.h:90
static Path createMonotoneCubicPathAzimuth(const Buffer< Time > &time, const Buffer< Angle< fltp08 > > &y)
Definition TimePath.h:142
Path(const Buffer< Time > &time, const Buffer< fltp04 > &y, const Buffer< fltp04 > &m)
Definition TimePath.h:43
fltp08 interpolateX(const Time &current_time)
Definition TimePath.h:61
Path()
Definition TimePath.h:41
Buffer< fltp04 > mM
Definition TimePath.h:223
Buffer< fltp04 > mY
Definition TimePath.h:222
Path(const Path &&path)
Definition TimePath.h:55
Definition String.h:40
Represents a timestamp with utilities for manipulation and conversion.
Definition Time.h:54
Definition ACIColor.h:37
float fltp04
Defines an alias representing a 4 byte floating-point number.
Definition BaseValues.hpp:157
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:181
Definition File.h:213
Definition BaseValues.hpp:272