Krotos Modules 3
Loading...
Searching...
No Matches
KrotosIntrepolators.cpp
Go to the documentation of this file.
1namespace krotos
2{
3 float ShapePreservingCubicInterpolator::interpolate(const std::vector<float>& xPositions,
4 const std::vector<float>& yPositions, float x)
5 {
6 jassert(xPositions.size() == yPositions.size());
7
8 const int numPoints = static_cast<int>(xPositions.size());
9
10 if (numPoints < 2)
11 {
12 jassertfalse; // Not enough points for interpolation
13 return 0.0f;
14 }
15
16 int index = 0;
17
18 // Find the index of the nearest point to the left of x
19 for (int i = 0; i < numPoints - 1; ++i)
20 {
21 if (xPositions[i + 1] >= x)
22 {
23 index = i;
24 break;
25 }
26 }
27
28 const float x0 = xPositions[index];
29 const float x1 = xPositions[index + 1];
30 const float y0 = yPositions[index];
31 const float y1 = yPositions[index + 1];
32
33 const float dx = x1 - x0;
34 const float dy = y1 - y0;
35 const float h0 = (index > 0) ? x0 - xPositions[index - 1] : dx;
36 const float h1 = (index < numPoints - 2) ? xPositions[index + 2] - x1 : dx;
37
38 const float t = (x - x0) / dx;
39 const float t2 = t * t;
40
41 const float p = (1.0f - t) * y0 + t * y1;
42
43 if (dy * h0 > 0.0f && dy * h1 > 0.0f)
44 {
45 const float a = (2.0f * dy - h0 * (y1 - y0) / dx) / h0;
46 const float b = (2.0f * dy - h1 * (y1 - y0) / dx) / h1;
47
48 return t * (1.0f - t) * (a * h0 + b * h1) + p;
49 }
50 else
51 {
52 return p;
53 }
54 }
55
56 float ShapePreservingCubicInterpolator::interpolateEigen(const Eigen::VectorXf& xPositions,
57 const Eigen::VectorXf& yPositions, float x)
58 {
59 jassert(xPositions.size() == yPositions.size());
60
61 const int numPoints = static_cast<int>(xPositions.size());
62
63 if (numPoints < 2)
64 {
65 jassertfalse; // Not enough points for interpolation
66 return 0.0f;
67 }
68
69 int index = 0;
70
71 // Find the index of the nearest point to the left of x
72 for (int i = 0; i < numPoints - 1; ++i)
73 {
74 if (xPositions[i + 1] >= x)
75 {
76 index = i;
77 break;
78 }
79 }
80
81 const float x0 = xPositions[index];
82 const float x1 = xPositions[index + 1];
83 const float y0 = yPositions[index];
84 const float y1 = yPositions[index + 1];
85
86 const float dx = x1 - x0;
87 const float dy = y1 - y0;
88 const float h0 = (index > 0) ? x0 - xPositions[index - 1] : dx;
89 const float h1 = (index < numPoints - 2) ? xPositions[index + 2] - x1 : dx;
90
91 const float t = (x - x0) / dx;
92 const float t2 = t * t;
93
94 const float p = (1.0f - t) * y0 + t * y1;
95
96 if (dy * h0 > 0.0f && dy * h1 > 0.0f)
97 {
98 const float a = (2.0f * dy - h0 * (y1 - y0) / dx) / h0;
99 const float b = (2.0f * dy - h1 * (y1 - y0) / dx) / h1;
100
101 return t * (1.0f - t) * (a * h0 + b * h1) + p;
102 }
103 else
104 {
105 return p;
106 }
107 }
108
109 std::vector<std::vector<float>> ShapePreservingCubicInterpolator::interpolate2D(
110 const std::vector<float>& xValues, const std::vector<std::vector<float>>& yValues,
111 const std::vector<float>& vals)
112 {
113 // Check if input dimensions are valid
114 if (xValues.size() != yValues[0].size() || yValues[0].size() == 0)
115 {
116 // Invalid input dimensions
117 jassertfalse;
118 }
119
120 std::vector<std::vector<float>> resultMatrix;
121
122 for (int row = 0; row < yValues.size(); ++row)
123 {
124 // Interpolate using Shape Preserving Cubic Interpolation
125 std::vector<float> interpolatedValues = interpolateVector(xValues, yValues[row], vals);
126
127 resultMatrix.push_back(interpolatedValues);
128 }
129
130 return resultMatrix;
131 }
132
133 Eigen::MatrixXf ShapePreservingCubicInterpolator::interpolate2DEigen(const Eigen::VectorXf& xValues,
134 const Eigen::MatrixXf yValues,
135 const Eigen::VectorXf& vals)
136 {
137 // Check if input dimensions are valid
138 if (xValues.size() != yValues.rows() || yValues.rows() == 0)
139 {
140 // Invalid input dimensions
141 jassertfalse;
142 }
143
144 Eigen::MatrixXf resultMatrix(vals.size(), yValues.cols());
145
146 for (int col = 0; col < yValues.cols(); ++col)
147 {
148 // Interpolate using Shape Preserving Cubic Interpolation
149 Eigen::VectorXf interpolatedValues = interpolateVectorEigen(xValues, yValues.col(col), vals);
150
151 resultMatrix.col(col) = interpolatedValues;
152 }
153
154 return resultMatrix;
155 }
156
157 std::vector<float> ShapePreservingCubicInterpolator::interpolateVector(const std::vector<float>& xPositions,
158 const std::vector<float>& yPositions,
159 const std::vector<float>& xValues)
160 {
161 jassert(xPositions.size() == yPositions.size());
162
163 const int numPoints = static_cast<int>(xPositions.size());
164
165 if (numPoints < 2)
166 {
167 jassertfalse; // Not enough points for interpolation
168 return std::vector<float>(xValues.size(), 0.0f);
169 }
170
171 std::vector<float> interpolatedValues;
172 interpolatedValues.reserve(xValues.size());
173
174 for (float x : xValues)
175 {
176 int index = 0;
177
178 // Find the index of the nearest point to the left of x
179 for (int i = 0; i < numPoints - 1; ++i)
180 {
181 if (xPositions[i + 1] >= x)
182 {
183 index = i;
184 break;
185 }
186 }
187
188 const float x0 = xPositions[index];
189 const float x1 = xPositions[index + 1];
190 const float y0 = yPositions[index];
191 const float y1 = yPositions[index + 1];
192
193 const float dx = x1 - x0;
194 const float dy = y1 - y0;
195 const float h0 = (index > 0) ? x0 - xPositions[index - 1] : dx;
196 const float h1 = (index < numPoints - 2) ? xPositions[index + 2] - x1 : dx;
197
198 const float t = (x - x0) / dx;
199 const float t2 = t * t;
200
201 const float p = (1.0f - t) * y0 + t * y1;
202
203 if (dy * h0 > 0.0f && dy * h1 > 0.0f)
204 {
205 const float a = (2.0f * dy - h0 * (y1 - y0) / dx) / h0;
206 const float b = (2.0f * dy - h1 * (y1 - y0) / dx) / h1;
207
208 interpolatedValues.push_back(t * (1.0f - t) * (a * h0 + b * h1) + p);
209 }
210 else
211 {
212 interpolatedValues.push_back(p);
213 }
214 }
215
216 return interpolatedValues;
217 }
218
219 Eigen::VectorXf ShapePreservingCubicInterpolator::interpolateVectorEigen(const Eigen::VectorXf& xPositions,
220 const Eigen::VectorXf& yPositions,
221 const Eigen::VectorXf& xValues)
222 {
223 jassert(xPositions.size() == yPositions.size());
224
225 const int numPoints = static_cast<int>(xPositions.size());
226
227 if (numPoints < 2)
228 {
229 jassert(false); // Not enough points for interpolation
230 return Eigen::VectorXf::Zero(xValues.size());
231 }
232
233 Eigen::VectorXf interpolatedValues(xValues.size());
234
235 for (int k = 0; k < xValues.size(); ++k)
236 {
237 float x = xValues[k];
238 int index = 0;
239
240 // Find the index of the nearest point to the left of x
241 for (int i = 0; i < numPoints - 1; ++i)
242 {
243 if (xPositions[i + 1] >= x)
244 {
245 index = i;
246 break;
247 }
248 }
249
250 const float x0 = xPositions[index];
251 const float x1 = xPositions[index + 1];
252 const float y0 = yPositions[index];
253 const float y1 = yPositions[index + 1];
254
255 const float dx = x1 - x0;
256 const float dy = y1 - y0;
257 const float h0 = (index > 0) ? x0 - xPositions[index - 1] : dx;
258 const float h1 = (index < numPoints - 2) ? xPositions[index + 2] - x1 : dx;
259
260 const float t = (x - x0) / dx;
261 const float t2 = t * t;
262
263 const float p = (1.0f - t) * y0 + t * y1;
264
265 if (dy * h0 > 0.0f && dy * h1 > 0.0f)
266 {
267 const float a = (2.0f * dy - h0 * (y1 - y0) / dx) / h0;
268 const float b = (2.0f * dy - h1 * (y1 - y0) / dx) / h1;
269
270 interpolatedValues[k] = t * (1.0f - t) * (a * h0 + b * h1) + p;
271 }
272 else
273 {
274 interpolatedValues[k] = p;
275 }
276 }
277
278 return interpolatedValues;
279 }
280
281 //============================================================================================================================================
282
283 std::vector<float> LinearInterpolator::interpolate(const std::vector<float>& xValues,
284 const std::vector<float>& yValues,
285 const std::vector<float>& vals)
286 {
287 // check if input vectors are of equal size
288 if (xValues.size() != yValues.size())
289 {
290 // handle error: Vectors must be of equal size
291 return std::vector<float>(); // return an empty vector to indicate the
292 // error
293 }
294
295 std::vector<float> interpolatedValues;
296 int size = static_cast<int>(vals.size());
297
298 for (int i = 0; i < size; ++i)
299 {
300 float valToInterpolateFor = vals[i];
301
302 // find the indices of the two nearest x-values in the input vector
303 int index1 = 0;
304 int index2 = 0;
305 int xSize = static_cast<int>(xValues.size());
306 for (int j = 0; j < xSize; ++j)
307 {
308 if (xValues[j] <= valToInterpolateFor)
309 index1 = j;
310 else
311 {
312 index2 = j;
313 break;
314 }
315 }
316
317 // perform linear interpolation
318 float x1 = xValues[index1];
319 float x2 = xValues[index2];
320 float y1 = yValues[index1];
321 float y2 = yValues[index2];
322
323 // avoid division by zero
324 if (std::isnan(valToInterpolateFor))
325 {
326 interpolatedValues.push_back(std::numeric_limits<float>::quiet_NaN());
327 }
328 else if (std::isnan(x1) || std::isnan(x2) || std::isnan(y1) || std::isnan(y2))
329 {
330 // handle NaN values in xValues or yValues
331 interpolatedValues.push_back(std::numeric_limits<float>::quiet_NaN());
332 }
333 else
334 {
335 if (x2 == x1)
336 {
337 // handle error: Division by zero
338 interpolatedValues.push_back(0.0f); // or push back an appropriate error value
339 }
340 else
341 {
342 float interpolatedValue = y1 + ((valToInterpolateFor - x1) * (y2 - y1)) / (x2 - x1);
343 interpolatedValues.push_back(interpolatedValue);
344 }
345 }
346 }
347
348 return interpolatedValues;
349 }
350
351 Eigen::VectorXf LinearInterpolator::interpolateEigen(const Eigen::VectorXf& xValues, const Eigen::VectorXf& yValues,
352 const Eigen::VectorXf& vals)
353 {
354 // check if input vectors are of equal size
355 if (xValues.size() != yValues.size())
356 {
357 jassertfalse; // Not enough points for interpolation
358 return Eigen::VectorXf::Zero(xValues.size());
359 }
360
361 Eigen::VectorXf interpolatedValues(vals.size());
362
363 for (int i = 0; i < vals.size(); ++i)
364 {
365 float valToInterpolateFor = vals[i];
366
367 // find the indices of the two nearest x-values in the input vector
368 int index1 = 0;
369 int index2 = 0;
370 int xSize = static_cast<int>(xValues.size());
371 for (int j = 0; j < xSize; ++j)
372 {
373 if (xValues[j] <= valToInterpolateFor)
374 index1 = j;
375 else
376 {
377 index2 = j;
378 break;
379 }
380 }
381
382 // perform linear interpolation
383 float x1 = xValues[index1];
384 float x2 = xValues[index2];
385 float y1 = yValues[index1];
386 float y2 = yValues[index2];
387
388 if (valToInterpolateFor < x1 || valToInterpolateFor > x2)
389 {
390 // Extrapolation, return NaN
391 interpolatedValues[i] = std::numeric_limits<float>::quiet_NaN();
392 }
393 else
394 {
395 if (x2 == x1)
396 {
397 // handle error: Division by zero
398 interpolatedValues.conservativeResize(interpolatedValues.size() + 1);
399 interpolatedValues(interpolatedValues.size() - 1) =
400 std::numeric_limits<float>::quiet_NaN(); // or push back an appropriate error value
401 }
402 else
403 {
404 float interpolatedValue = y1 + ((valToInterpolateFor - x1) * (y2 - y1)) / (x2 - x1);
405 interpolatedValues[i] = interpolatedValue;
406 }
407 }
408 }
409
410 return interpolatedValues;
411 }
412
413 Eigen::MatrixXf LinearInterpolator::interpolate2DEigen(const Eigen::VectorXf& xValues,
414 const Eigen::MatrixXf& yValues, const Eigen::VectorXf& vals)
415 {
416 // Check if input dimensions are valid
417 if (xValues.size() != yValues.rows() || yValues.rows() == 0)
418 {
419 // Invalid input dimensions
420 jassertfalse;
421 }
422
423 Eigen::MatrixXf resultMatrix(vals.size(), yValues.cols());
424
425 for (int col = 0; col < yValues.cols(); ++col)
426 {
427 // Interpolate using Shape Preserving Cubic Interpolation
428 Eigen::VectorXf interpolatedValues = LinearInterpolator::interpolateEigen(xValues, yValues.col(col), vals);
429
430 resultMatrix.col(col) = interpolatedValues;
431 }
432
433 return resultMatrix;
434 }
435
436 std::vector<std::vector<float>> LinearInterpolator::interpolate2D(const std::vector<float>& xValues,
437 const std::vector<std::vector<float>>& yValues,
438 const std::vector<float>& vals)
439 {
440 // Check if input dimensions are valid
441 if (xValues.size() != yValues[0].size() || yValues[0].size() == 0)
442 {
443 // Invalid input dimensions
444 jassertfalse;
445 }
446
447 // Convert values in vals to NaN if they are outside the range of xValues
448 std::vector<float> sanitizedVals = vals;
449 std::transform(sanitizedVals.begin(), sanitizedVals.end(), sanitizedVals.begin(), [&](float val) {
450 return (val < xValues.front() || val > xValues.back()) ? std::numeric_limits<float>::quiet_NaN() : val;
451 });
452
453 std::vector<std::vector<float>> resultMatrix;
454
455 for (int row = 0; row < yValues.size(); ++row)
456 {
457 // Interpolate using Linear Interpolation
458 std::vector<float> interpolatedValues =
459 LinearInterpolator::interpolate(xValues, yValues[row], sanitizedVals);
460
461 resultMatrix.push_back(interpolatedValues);
462 }
463
464 return resultMatrix;
465 }
466
467} // namespace krotos
static Eigen::VectorXf interpolateEigen(const Eigen::VectorXf &xValues, const Eigen::VectorXf &yValues, const Eigen::VectorXf &vals)
Definition KrotosIntrepolators.cpp:351
static Eigen::MatrixXf interpolate2DEigen(const Eigen::VectorXf &xValues, const Eigen::MatrixXf &yValues, const Eigen::VectorXf &vals)
Definition KrotosIntrepolators.cpp:413
static std::vector< std::vector< float > > interpolate2D(const std::vector< float > &xValues, const std::vector< std::vector< float > > &yValues, const std::vector< float > &vals)
Definition KrotosIntrepolators.cpp:436
static std::vector< float > interpolate(const std::vector< float > &xValues, const std::vector< float > &yValues, const std::vector< float > &vals)
Definition KrotosIntrepolators.cpp:283
static Eigen::VectorXf interpolateVectorEigen(const Eigen::VectorXf &xPositions, const Eigen::VectorXf &yPositions, const Eigen::VectorXf &xValues)
Definition KrotosIntrepolators.cpp:219
static std::vector< float > interpolateVector(const std::vector< float > &xPositions, const std::vector< float > &yPositions, const std::vector< float > &xValues)
Definition KrotosIntrepolators.cpp:157
static float interpolate(const std::vector< float > &xPositions, const std::vector< float > &yPositions, float x)
Definition KrotosIntrepolators.cpp:3
static float interpolateEigen(const Eigen::VectorXf &xPositions, const Eigen::VectorXf &yPositions, float x)
Definition KrotosIntrepolators.cpp:56
static std::vector< std::vector< float > > interpolate2D(const std::vector< float > &xValues, const std::vector< std::vector< float > > &yValues, const std::vector< float > &vals)
Definition KrotosIntrepolators.cpp:109
static Eigen::MatrixXf interpolate2DEigen(const Eigen::VectorXf &xValues, const Eigen::MatrixXf yValues, const Eigen::VectorXf &vals)
Definition KrotosIntrepolators.cpp:133
Definition AirAbsorptionFilter.cpp:2