semf
linearinterpolator.h
Go to the documentation of this file.
1
10#ifndef SEMF_UTILS_PROCESSING_LINEARINTERPOLATOR_H_
11#define SEMF_UTILS_PROCESSING_LINEARINTERPOLATOR_H_
12
13#include <cstddef>
14#include <cstdint>
15#include <cmath>
16
17namespace semf
18{
30template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET = T_IN, typename T_STORAGE = T_TARGET>
32{
33public:
40 explicit LinearInterpolator(bool limitToBoundaryValues = true);
41 virtual ~LinearInterpolator() = default;
42
52 bool init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_TARGET targetData[], uint16_t targetDataSize);
53
65 bool init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_IN dimension2Data[], uint16_t dimension2DataSize, const T_TARGET targetData[],
66 uint16_t targetDataSize);
67
81 bool init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_IN dimension2Data[], uint16_t dimension2DataSize, const T_IN dimension3Data[],
82 uint16_t dimension3DataSize, const T_TARGET targetData[], uint16_t targetDataSize);
83
93 bool setTargetDataInputDimension(const T_TARGET targetData[], uint16_t targetDataSize);
94
106 bool interpolate(T_TARGET& y, T_IN x1 = 0, T_IN x2 = 0, T_IN x3 = 0);
107
108private:
112 void interpolateInOneDimension();
113
117 void interpolateInTwoDimensions();
118
122 void interpolateInThreeDimensions();
123
127 void calculateNeighboringPoints();
128
132 void getPointIndecies();
133
137 void checkDimensionBoundaries();
138
144 T_STORAGE abs(T_STORAGE);
145
147 bool m_limitToBoundaryValues;
149 T_STORAGE m_partition = 0;
151 const T_IN* m_dim[MAX_DIMENSIONS] = {nullptr};
153 const T_TARGET* m_targetData = nullptr;
156 bool m_dimReduction[MAX_DIMENSIONS] = {true};
158 uint8_t m_consideredDimCtr = 0;
160 uint16_t m_dimLen[MAX_DIMENSIONS] = {0};
162 uint16_t m_targetDataSize = 0;
165 int16_t m_iSVec[MAX_DIMENSIONS] = {-1};
167 int16_t m_iBVec[MAX_DIMENSIONS] = {-1};
169 T_IN m_xVal[MAX_DIMENSIONS] = {0};
171 uint8_t m_considDim[MAX_DIMENSIONS] = {0};
173 T_TARGET m_targetDataSel[8 /*2^3*/] = {0};
174 T_TARGET m_yVal = 0;
177 bool m_retValue = false;
178};
179
180template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
182: m_limitToBoundaryValues(limitToBoundaryValues)
183{
184 // Throws an error at compile time if maximal dimension is not in the allowed range (1, 2, or 3).
185 static_assert(MAX_DIMENSIONS == 1 || MAX_DIMENSIONS == 2 || MAX_DIMENSIONS == 3, "MAX_DIMENSIONS has to be 1, 2 or 3");
186}
187
188template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
189bool LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_TARGET targetData[],
190 uint16_t targetDataSize)
191{
192 if (dimension1Data == nullptr || targetData == nullptr || targetDataSize != dimension1DataSize)
193 {
194 m_retValue = false;
195 }
196 else
197 {
198 m_dim[0] = dimension1Data;
199 m_dimLen[0] = dimension1DataSize;
200 m_targetData = targetData;
201 m_targetDataSize = targetDataSize;
202 m_retValue = true;
203 }
204 return m_retValue;
205}
206
207template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
208bool LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_IN dimension2Data[],
209 uint16_t dimension2DataSize, const T_TARGET targetData[], uint16_t targetDataSize)
210{
211 if (dimension1Data == nullptr || dimension2Data == nullptr || targetData == nullptr || targetDataSize != (dimension1DataSize * dimension2DataSize))
212 {
213 m_retValue = false;
214 }
215 else
216 {
217 m_dim[0] = dimension1Data;
218 m_dim[1] = dimension2Data;
219 m_dimLen[0] = dimension1DataSize;
220 m_dimLen[1] = dimension2DataSize;
221 m_targetData = targetData;
222 m_targetDataSize = targetDataSize;
223 m_retValue = true;
224 }
225 return m_retValue;
226}
227
228template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
229bool LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_IN dimension2Data[],
230 uint16_t dimension2DataSize, const T_IN dimension3Data[], uint16_t dimension3DataSize,
231 const T_TARGET targetData[], uint16_t targetDataSize)
232{
233 if (dimension1Data == nullptr || dimension2Data == nullptr || dimension3Data == nullptr || targetData == nullptr ||
234 targetDataSize != (dimension1DataSize * dimension2DataSize * dimension3DataSize))
235 {
236 m_retValue = false;
237 }
238 else
239 {
240 m_dim[0] = dimension1Data;
241 m_dim[1] = dimension2Data;
242 m_dim[2] = dimension3Data;
243 m_dimLen[0] = dimension1DataSize;
244 m_dimLen[1] = dimension2DataSize;
245 m_dimLen[2] = dimension3DataSize;
246 m_targetData = targetData;
247 m_targetDataSize = targetDataSize;
248 m_retValue = true;
249 }
250 return m_retValue;
251}
252
253template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
255{
256 if (targetData == nullptr || targetDataSize != m_targetDataSize)
257 {
258 m_retValue = false;
259 }
260 else
261 {
262 m_targetData = targetData;
263 m_retValue = true;
264 }
265 return m_retValue;
266}
267
268template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
270{
271 m_retValue = true;
272 m_yVal = 0;
273 m_partition = 0;
274 // reinitialize: m_dimReduction, m_iBVec, m_iSVec, m_consideredDimCtr
275 for (uint8_t i = 0; i < MAX_DIMENSIONS; i++)
276 {
277 m_dimReduction[i] = false;
278 m_iBVec[i] = 0;
279 m_iSVec[i] = 0;
280 m_considDim[i] = 0;
281 }
282 m_xVal[0] = x1;
283 m_xVal[1] = x2;
284 m_xVal[2] = x3;
285 m_consideredDimCtr = 0;
286 calculateNeighboringPoints();
287 if (m_retValue)
288 {
289 switch (m_consideredDimCtr)
290 {
291 case 0:
292 m_yVal = m_targetDataSel[0];
293 break;
294 case 1:
295 interpolateInOneDimension();
296 break;
297 case 2:
298 interpolateInTwoDimensions();
299 break;
300 case 3:
301 interpolateInThreeDimensions();
302 break;
303 default:
304 m_retValue = false;
305 break;
306 }
307 y = m_yVal;
308 }
309 return m_retValue;
310}
311
312template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
314{
315 T_STORAGE nB = 0, nS = 0;
316 uint16_t iS = 1, iB = 1;
317
318 for (int i = 0; i <= m_considDim[0]; i++) // 1st considered dimension
319 {
320 iB *= 2;
321 iS = iB / 2;
322 }
323 m_partition += (m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]]);
324 nB += (m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]);
325 nS += (m_xVal[m_considDim[0]] - m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]]);
326 m_yVal = (m_targetDataSel[iS - 1] * nB + m_targetDataSel[iB - 1] * nS) / m_partition;
327}
328
329template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
330void LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::interpolateInTwoDimensions()
331{
332 uint16_t iSS = 1, iBS = 1, iSB = 1, iBB = 1;
333 T_STORAGE nSS, nBS, nSB, nBB; // n(1stDimNotation)(2ndDimNotaion)
334
335 for (int i = 0; i <= m_considDim[0]; i++) // 1st considered dimension
336 {
337 iBS *= 2;
338 iSS = iBS / 2;
339 }
340 for (int i = 0; i <= m_considDim[1]; i++) // 2nd considered dimension
341 {
342 iBB *= 2;
343 }
344 iSB = iBB - iSS;
345
346 m_partition = (m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]]) *
347 (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]]);
348
349 nSS = (m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) * (m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]] - m_xVal[m_considDim[1]]);
350 nBS = (m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) * (m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]] - m_xVal[m_considDim[1]]);
351 nSB = (m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) * (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_xVal[m_considDim[1]]);
352 nBB = (m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) * (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_xVal[m_considDim[1]]);
353 m_yVal = (abs(nSS) * m_targetDataSel[iBB - 1] + abs(nBS) * m_targetDataSel[iSB - 1] + abs(nSB) * m_targetDataSel[iBS - 1] +
354 abs(nBB) * m_targetDataSel[iSS - 1]) /
355 m_partition;
356}
357
358template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
359void LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::interpolateInThreeDimensions()
360{
361 // this part has to be generalized
362 uint16_t iSSS = 1, iBSS = 2, iSBS = 3, iBBS = 4, iSSB = 5, iBSB = 6, iSBB = 7, iBBB = 8;
363 T_STORAGE nSSS, nBSS, nSBS, nBBS, nSSB, nBSB, nSBB, nBBB;
364
365 m_partition = (m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]]) *
366 (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]]) *
367 (m_dim[m_considDim[2]][m_iBVec[m_considDim[2]]] - m_dim[m_considDim[2]][m_iSVec[m_considDim[2]]]);
368
369 nSSS = abs((m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
370 (m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
371 (m_dim[m_considDim[2]][m_iSVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
372 nBSS = abs((m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
373 (m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
374 (m_dim[m_considDim[2]][m_iSVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
375 nSBS = abs((m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
376 (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
377 (m_dim[m_considDim[2]][m_iSVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
378 nBBS = abs((m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
379 (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
380 (m_dim[m_considDim[2]][m_iSVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
381 nSSB = abs((m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
382 (m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
383 (m_dim[m_considDim[2]][m_iBVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
384 nBSB = abs((m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
385 (m_dim[m_considDim[1]][m_iSVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
386 (m_dim[m_considDim[2]][m_iBVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
387 nSBB = abs((m_dim[m_considDim[0]][m_iSVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
388 (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
389 (m_dim[m_considDim[2]][m_iBVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
390 nBBB = abs((m_dim[m_considDim[0]][m_iBVec[m_considDim[0]]] - m_xVal[m_considDim[0]]) *
391 (m_dim[m_considDim[1]][m_iBVec[m_considDim[1]]] - m_xVal[m_considDim[1]]) *
392 (m_dim[m_considDim[2]][m_iBVec[m_considDim[2]]] - m_xVal[m_considDim[2]]));
393
394 m_yVal = (nSSS * m_targetDataSel[iBBB - 1] + nBSS * m_targetDataSel[iSBB - 1] + nSBS * m_targetDataSel[iBSB - 1] + nBBS * m_targetDataSel[iSSB - 1] +
395 nSSB * m_targetDataSel[iBBS - 1] + nBSB * m_targetDataSel[iSBS - 1] + nSBB * m_targetDataSel[iBSS - 1] + nBBB * m_targetDataSel[iSSS - 1]) /
396 m_partition;
397}
398
399template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
400void LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::calculateNeighboringPoints()
401{
402 getPointIndecies();
403 if (m_retValue)
404 {
405 switch (MAX_DIMENSIONS)
406 {
407 case 1:
408 m_targetDataSel[0] = m_targetData[m_iSVec[0]];
409 m_targetDataSel[1] = m_targetData[m_iBVec[0]];
410 break;
411 case 2:
412 m_targetDataSel[0] = m_targetData[m_iSVec[1] + m_dimLen[1] * m_iSVec[0]];
413 m_targetDataSel[1] = m_targetData[m_iSVec[1] + m_dimLen[1] * m_iBVec[0]];
414 m_targetDataSel[2] = m_targetData[m_iBVec[1] + m_dimLen[1] * m_iSVec[0]];
415 m_targetDataSel[3] = m_targetData[m_iBVec[1] + m_dimLen[1] * m_iBVec[0]];
416 break;
417 case 3:
418 m_targetDataSel[0] = m_targetData[m_iSVec[2] + m_dimLen[2] * m_iSVec[1] + m_dimLen[1] * m_dimLen[2] * m_iSVec[0]];
419 m_targetDataSel[1] = m_targetData[m_iSVec[2] + m_dimLen[2] * m_iSVec[1] + m_dimLen[1] * m_dimLen[2] * m_iBVec[0]];
420 m_targetDataSel[2] = m_targetData[m_iSVec[2] + m_dimLen[2] * m_iBVec[1] + m_dimLen[1] * m_dimLen[2] * m_iSVec[0]];
421 m_targetDataSel[3] = m_targetData[m_iSVec[2] + m_dimLen[2] * m_iBVec[1] + m_dimLen[1] * m_dimLen[2] * m_iBVec[0]];
422 m_targetDataSel[4] = m_targetData[m_iBVec[2] + m_dimLen[2] * m_iSVec[1] + m_dimLen[1] * m_dimLen[2] * m_iSVec[0]];
423 m_targetDataSel[5] = m_targetData[m_iBVec[2] + m_dimLen[2] * m_iSVec[1] + m_dimLen[1] * m_dimLen[2] * m_iBVec[0]];
424 m_targetDataSel[6] = m_targetData[m_iBVec[2] + m_dimLen[2] * m_iBVec[1] + m_dimLen[1] * m_dimLen[2] * m_iSVec[0]];
425 m_targetDataSel[7] = m_targetData[m_iBVec[2] + m_dimLen[2] * m_iBVec[1] + m_dimLen[1] * m_dimLen[2] * m_iBVec[0]];
426 break;
427 default:
428 m_retValue = false;
429 break;
430 }
431 }
432}
433
434template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
435void LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::getPointIndecies()
436{
437 for (uint8_t i = 0; i < MAX_DIMENSIONS; i++)
438 {
439 if (m_limitToBoundaryValues)
440 {
441 if (m_xVal[i] > m_dim[i][m_dimLen[i] - 1])
442 {
443 m_xVal[i] = m_dim[i][m_dimLen[i] - 1];
444 }
445 else if (m_xVal[i] < m_dim[i][0])
446 {
447 m_xVal[i] = m_dim[i][0];
448 }
449 }
450
451 // finding targetData the index of the bigger index for each dimension.
452 while ((m_dim[i][m_iBVec[i]] < m_xVal[i]) && (m_iBVec[i] < m_dimLen[i]))
453 {
454 m_iBVec[i]++;
455 }
456 // checks whether the chosen index is the same as the given
457 // point for each dimension, and counts the active dimensions.
458 if (m_dim[i][m_iBVec[i]] == m_xVal[i])
459 {
460 m_iSVec[i] = m_iBVec[i];
461 m_dimReduction[i] = true;
462 }
463 else
464 {
465 m_iSVec[i] = m_iBVec[i] - 1;
466 m_considDim[m_consideredDimCtr] = i;
467 m_consideredDimCtr++;
468 }
469 }
470 checkDimensionBoundaries();
471}
472
473template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
474void LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::checkDimensionBoundaries()
475{
476 for (uint8_t i = 0; i < MAX_DIMENSIONS; i++)
477 {
478 if ((m_iSVec[i] < 0) || (m_iBVec[i] >= m_dimLen[i]))
479 {
480 m_retValue = false;
481 }
482 }
483}
484
485template <uint8_t MAX_DIMENSIONS, typename T_IN, typename T_TARGET, typename T_STORAGE>
486T_STORAGE LinearInterpolator<MAX_DIMENSIONS, T_IN, T_TARGET, T_STORAGE>::abs(T_STORAGE input)
487{
488 if (input < 0)
489 input *= -1;
490 return input;
491}
492} /* namespace semf */
493#endif /* SEMF_UTILS_PROCESSING_LINEARINTERPOLATOR_H_ */
Class for calculating the linear interpolation. It interpolates till 3-dimensional data.
bool interpolate(T_TARGET &y, T_IN x1=0, T_IN x2=0, T_IN x3=0)
Calculates the interpolation of a given data point.
virtual ~LinearInterpolator()=default
LinearInterpolator(bool limitToBoundaryValues=true)
bool setTargetDataInputDimension(const T_TARGET targetData[], uint16_t targetDataSize)
It updates/changes the m_targetDataSource array.
bool init(const T_IN dimension1Data[], uint16_t dimension1DataSize, const T_TARGET targetData[], uint16_t targetDataSize)
Initializes the class members with 1 dimensional data points.