Ocean
Lookup2.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_MATH_LOOKUP2_H
9 #define META_OCEAN_MATH_LOOKUP2_H
10 
11 #include "ocean/math/Math.h"
13 #include "ocean/math/Vector2.h"
14 
15 #include <vector>
16 
17 namespace Ocean
18 {
19 
20 /**
21  * This class implements a 2D lookup object allowing to separate a two dimensional lookup area into individual bins.
22  * The entire lookup area covers an integer two-dimensional space starting at the origin.<br>
23  * Lookup values are generated by interpolating lookup values between neighboring bins.
24  * @tparam T The data type of the stored lookup values
25  * @tparam TScalar The data type of the scalar values, either 'float' or 'double'
26  * @ingroup math
27  */
28 template <typename T, typename TScalar = Scalar>
29 class Lookup2
30 {
31  public:
32 
33  /**
34  * Definition of the lookup data type.
35  */
36  typedef T Type;
37 
38  protected:
39 
40  /**
41  * Definition of a vector holding lookup values.
42  */
43  typedef std::vector<T> Values;
44 
45  public:
46 
47  /**
48  * Returns a pointer to the constant bin data (row aligned).
49  * @return Bin data
50  */
51  inline const T* data() const;
52 
53  /**
54  * Returns a pointer to the bin data (row aligned).
55  * @return Bin data
56  */
57  inline T* data();
58 
59  /**
60  * Returns the horizontal dimension of this lookup object.
61  * @return Horizontal dimension
62  */
63  inline size_t sizeX() const;
64 
65  /**
66  * Returns the vertical dimension of this lookup object.
67  * @return Vertical dimension
68  */
69  inline size_t sizeY() const;
70 
71  /**
72  * Returns the number of horizontal bins of this lookup object.
73  * @return Number of horizontal bins
74  */
75  inline size_t binsX() const;
76 
77  /**
78  * Returns the number of vertical bins of this lookup object.
79  * @return Number of vertical bins
80  */
81  inline size_t binsY() const;
82 
83  /**
84  * Returns whether this lookup object does not hold any lookup bin.
85  * @return True, if so
86  */
87  inline bool isEmpty() const;
88 
89  /**
90  * Returns whether this lookup object holds at least one lookup bin.
91  * @return True, if so
92  */
93  explicit inline operator bool() const;
94 
95  /**
96  * Returns whether two lookup objects are identical.
97  * @param lookup Second lookup object
98  * @return True, if so
99  */
100  bool operator==(const Lookup2<T, TScalar>& lookup) const;
101 
102  /**
103  * Returns whether two lookup objects are not identical.
104  * @param lookup Second lookup object
105  * @return True, if so
106  */
107  inline bool operator!=(const Lookup2<T, TScalar>& lookup) const;
108 
109  protected:
110 
111  /**
112  * Creates a new empty lookup object.
113  */
114  Lookup2() = default;
115 
116  /**
117  * Copy constructor.
118  * @param lookup The lookup object to be moved
119  */
120  inline Lookup2(const Lookup2<T, TScalar>& lookup);
121 
122  /**
123  * Move constructor.
124  * @param lookup The lookup object to be moved
125  */
126  inline Lookup2(Lookup2<T, TScalar>&& lookup) noexcept;
127 
128  /**
129  * Assign operator.
130  * @param lookup The lookup object that will be moved
131  * @return Reference to this object
132  */
134 
135  /**
136  * Move operator.
137  * @param lookup The lookup object that will be moved
138  * @return Reference to this object
139  */
141 
142  protected:
143 
144  /// Horizontal dimension of this lookup object.
145  size_t sizeX_ = 0;
146 
147  /// Vertical dimension of this lookup object.
148  size_t sizeY_ = 0;
149 
150  /// Number of horizontal bins.
151  size_t binsX_ = 0;
152 
153  /// Number of vertical bins.
154  size_t binsY_ = 0;
155 
156  /// Inverse horizontal dimension of this lookup object.
157  TScalar invSizeX_ = 0;
158 
159  /// Inverse vertical dimension of this lookup object.
160  TScalar invSizeY_ = 0;
161 
162  /// Inverse number of horizontal bins.
163  TScalar invBinsX_ = 0;
164 
165  /// Inverse number of vertical bins.
166  TScalar invBinsY_ = 0;
167 
168  /// The values of the lookup bins.
170 };
171 
172 /**
173  * This class implements a 2D lookup object with values at the bins' center positions defining the individual lookup values.
174  * This area is separated into individual neighboring bins (with almost same size) each covering an integer-sized area.<br>
175  * The sizes of the bins may vary due to rounding issues if the number of bins is not dividable without remainder in relation to the size of the lookup object.<br>
176  * Each bin covers a whole-numbered number of elements (e.g., pixels) and the left, top, right and bottom position of each bin is also an integer number.<br>
177  * However, the center position of the bins may have a non-integer position.
178  *
179  * The lookup table with 4x2 bins has the following layout:
180  * <pre>
181  * --- --- --- ---
182  * | + | + | + | + |
183  * --- --- --- ---
184  * | + | + | + | + |
185  * --- --- --- ---
186  * </pre>
187  * With '+' showing the center positions of the lookup values.<br>
188  * Thus, the lookup table has 4 horizontal bins and 4 horizontal lookup values.<br>
189  * All lookup values are located inside the specified size of the lookup object.<br>
190  * The vertical positions are accordingly.
191  * @tparam T The data type of the stored lookup values
192  * @tparam TScalar The data type of the scalar values, either 'float' or 'double'
193  * @see LookupCorner2
194  * @ingroup math
195  */
196 template <typename T, typename TScalar = Scalar>
197 class LookupCenter2 : public Lookup2<T, TScalar>
198 {
199  public:
200 
201  /**
202  * Creates a new empty lookup object.
203  */
204  LookupCenter2() = default;
205 
206  /**
207  * Copy constructor.
208  * @param lookup The lookup object to be copied
209  */
211 
212  /**
213  * Move constructor.
214  * @param lookup The lookup object to be moved
215  */
216  inline LookupCenter2(LookupCenter2<T, TScalar>&& lookup) noexcept;
217 
218  /**
219  * Creates a new lookup object by definition of the dimensions and bin numbers.
220  * Beware: The bin values will be initialized with the default constructor of the template class.
221  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
222  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
223  * @param binsX Number of horizontal bins, with range [1, sizeX]
224  * @param binsY Number of vertical bins, with range [1, sizeY]
225  */
226  LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY);
227 
228  /**
229  * Creates a new lookup object by definition of the dimensions and bin numbers.
230  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
231  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
232  * @param binsX Number of horizontal bins, with range [1, sizeX]
233  * @param binsY Number of vertical bins, with range [1, sizeY]
234  * @param binValues The bin values of the lookup object (row aligned), binsX * binsY values must be provided
235  */
236  LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binValues);
237 
238  /**
239  * Creates a new lookup object by definition of the dimensions and a given lookup object.
240  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
241  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
242  * @param lookup The lookup object specifying the lookup values and the number of lookup bins
243  */
244  LookupCenter2(const size_t sizeX, const size_t sizeY, const LookupCenter2<T, TScalar>& lookup);
245 
246  /**
247  * Returns whether a given position lies inside this lookup object and therefore whether this position can be applied for the interpolation functions.
248  * @param x Precise horizontal position for the resulting lookup value, with range (-infinity, infinity)
249  * @param y Precise vertical position for the resulting lookup value, with range (-infinity, infinity)
250  * @return True, if x and y is in the range [0, sizeX() - 1]x[0, sizeY() - 1]
251  */
252  inline bool isInside(const TScalar x, const TScalar y) const;
253 
254  /**
255  * Returns the horizontal bin that corresponds to a precise horizontal lookup position.
256  * @param x Precise horizontal position in relation to the dimension of this lookup object, with range [0, sizeX() - 1]
257  * @return Resulting horizontal bin index
258  */
259  inline size_t binX(const TScalar x) const;
260 
261  /**
262  * Returns the vertical bin that corresponds to a precise vertical lookup position.
263  * @param y Precise vertical position in relation to the dimension of this lookup object, with range [0, sizeY() - 1]
264  * @return Resulting vertical bin index
265  */
266  inline size_t binY(const TScalar y) const;
267 
268  /**
269  * Returns the horizontal top left position of a specified bin with pixel accuracy.
270  * @param binX The horizontal bin position, with range [0, binsX())
271  * @return The horizontal position within the dimension of the lookup table, with range [0, sizeX())
272  */
273  inline size_t binTopLeftX(const size_t binX) const;
274 
275  /**
276  * Returns the vertical top left position of a specified bin with pixel accuracy.
277  * @param binY The vertical bin position, with range [0, binsY())
278  * @return The vertical position within the dimension of the lookup table, with range [0, sizeY())
279  */
280  inline size_t binTopLeftY(const size_t binY) const;
281 
282  /**
283  * Returns the horizontal bottom right position (including) of a specified bin with pixel accuracy.
284  * @param binX The horizontal bin position, with range [0, binsX())
285  * @return The horizontal position within the dimension of the lookup table, with range [0, sizeX())
286  */
287  inline size_t binBottomRightX(const size_t binX) const;
288 
289  /**
290  * Returns the vertical bottom right position of a specified bin with pixel accuracy.
291  * @param binY The vertical bin position, with range [0, binsY())
292  * @return The vertical position within the dimension of the lookup table, with range [0, sizeY())
293  */
294  inline size_t binBottomRightY(const size_t binY) const;
295 
296  /**
297  * Returns the horizontal center position of a specific bin in relation to the dimension of this lookup object.
298  * @param binX Horizontal bin position, with range [0, binsX())
299  * @return Precise horizontal position of the specified bin in relation to the lookup object's dimension, with range [0, sizeX())
300  */
301  inline TScalar binCenterPositionX(const size_t binX) const;
302 
303  /**
304  * Returns the vertical center position of a specific bin in relation to the dimension of this lookup object.
305  * @param binY Vertical bin position, with range [0, binsY())
306  * @return Precise vertical position of the specified bin in relation to the lookup object's dimension, with range [0, sizeY())
307  */
308  inline TScalar binCenterPositionY(const size_t binY) const;
309 
310  /**
311  * Returns the center position of a specific bin in relation to the dimension of this lookup object.
312  * @param binX Horizontal bin position, with range [0, binsX())
313  * @param binY Vertical bin position, with range [0, binsY())
314  * @return Precise position of the specified bin in relation to the lookup object's dimension, with range [0, sizeX())x[0, sizeY())
315  */
316  inline Vector2 binCenterPosition(const size_t binX, const size_t binY) const;
317 
318  /**
319  * Returns the lookup value of a specific bin's center of this lookup object.
320  * @param binX Horizontal bin position, with range [0, binsX())
321  * @param binY Vertical bin position, with range [0, binsY())
322  * @return Bin lookup value
323  */
324  inline const T& binCenterValue(const size_t binX, const size_t binY) const;
325 
326  /**
327  * Returns the lookup value of a specific bin's center of this lookup object.
328  * @param binX Horizontal bin position, with range [0, binsX())
329  * @param binY Vertical bin position, with range [0, binsY())
330  * @return Bin lookup value
331  */
332  inline T& binCenterValue(const size_t binX, const size_t binY);
333 
334  /**
335  * Applies a lookup for a specific position in this lookup object.
336  * The resulting value is specified by the nearest bin (determined by the bin's center position).<br>
337  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX() - 1]
338  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY() - 1]
339  */
340  T nearestValue(const TScalar x, const TScalar y) const;
341 
342  /**
343  * Applies a lookup for a specific position in this lookup object.
344  * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.<br>
345  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX() - 1]
346  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY() - 1]
347  */
348  T bilinearValue(const TScalar x, const TScalar y) const;
349 
350  /**
351  * Applies a lookup for a specific position in this lookup object.
352  * The resulting value is cubic interpolated within the 16-neighborhood of the lookup bins.<br>
353  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX() - 1]
354  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY() - 1]
355  */
356  T bicubicValue(const TScalar x, const TScalar y) const;
357 
358  /**
359  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
360  * The resulting value is specified by the nearest bin (determined by the bin's corner positions).<br>
361  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
362  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
363  * @see clampedBilinearValue(), clampedBicubicValue(), nearestValue().
364  */
365  T clampedNearestValue(const TScalar x, const TScalar y) const;
366 
367  /**
368  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
369  * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.<br>
370  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
371  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
372  * @see clampedNearestValue(), clampedBicubicValue(), bilinearValue().
373  */
374  T clampedBilinearValue(const TScalar x, const TScalar y) const;
375 
376  /**
377  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
378  * The resulting value is cubic interpolated within the 16-neighborhood of the lookup bins.<br>
379  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
380  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
381  * @see clampedNearestValue(), clampedBilinearValue(), bicubicValue().
382  */
383  T clampedBicubicValue(const TScalar x, const TScalar y) const;
384 
385  /**
386  * Sets the value of one specific lookup bin's center.
387  * @param binX Horizontal bin position, with range [0, binsX())
388  * @param binY Vertical bin position, with range [0, binsY())
389  * @param value The value to be set
390  */
391  inline void setBinCenterValue(const size_t binX, const size_t binY, const T& value);
392 
393  /**
394  * Move operator.
395  * @param lookup The lookup object that will be moved
396  * @return Reference to this object
397  */
399 };
400 
401 /**
402  * This class implements an advanced 2D lookup object with values at the bins' center positions defining the individual lookup values.
403  * Further, this lookup object allows to define valid and invalid bins.<br>
404  * Invalid bins are not used for value interpolation.<br>
405  * The lookup table with e.g., 4x2 bins may have the following layout:
406  * <pre>
407  * --- --- --- ---
408  * | x | ? | x | x |
409  * --- --- --- ---
410  * | ? | x | ? | x |
411  * --- --- --- ---
412  * </pre>
413  * With 'x' showing valid center values and '?' showing invalid/undefined center values.<br>
414  * Thus, the lookup table has 4 horizontal bins and 4 horizontal lookup values.<br>
415  * All lookup values are located inside the specified size of the lookup object.<br>
416  * The vertical positions are accordingly.
417  * @tparam T The data type of the stored lookup values
418  * @tparam TScalar The data type of the scalar values, either 'float' or 'double'
419  * @see LookupCorner2
420  * @ingroup math
421  */
422 template <typename T, typename TScalar = Scalar>
423 class AdvancedLookupCenter2 : public LookupCenter2<T, TScalar>
424 {
425  protected:
426 
427  /**
428  * Definition of a vector holding 1 byte values.
429  */
430  typedef std::vector<unsigned char> ValidBins;
431 
432  public:
433 
434  /**
435  * Creates a new empty lookup object.
436  */
438 
439  /**
440  * Copy constructor.
441  * @param lookup The lookup object to be copied
442  */
444 
445  /**
446  * Move constructor.
447  * @param lookup The lookup object to be moved
448  */
450 
451  /**
452  * Creates a new lookup object by definition of the dimensions and bin numbers.
453  * All bins will be set as valid.<br>
454  * Beware: The bin values will be initialized with the default constructor of the template class.
455  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
456  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
457  * @param binsX Number of horizontal bins, with range [1, sizeX]
458  * @param binsY Number of vertical bins, with range [1, sizeY]
459  */
460  AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY);
461 
462  /**
463  * Creates a new lookup object by definition of the dimensions and bin numbers.
464  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
465  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
466  * @param binsX Number of horizontal bins, with range [1, sizeX]
467  * @param binsY Number of vertical bins, with range [1, sizeY]
468  * @param binsValid True, if all bins are valid; False, if all bins are invalid
469  */
470  AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const bool binsValid);
471 
472  /**
473  * Creates a new lookup object by definition of the dimensions and bin numbers.
474  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
475  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
476  * @param binsX Number of horizontal bins, with range [1, sizeX]
477  * @param binsY Number of vertical bins, with range [1, sizeY]
478  * @param binValues The bin values of the lookup object (row aligned), binsX * binsY values must be provided
479  * @param validBins The specification whether a bin is valid or not, a zero value specifies an invalid bin, a non-zero value specifies a valid bin
480  */
481  AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binValues, const unsigned char* validBins);
482 
483  /**
484  * Creates a new lookup object by definition of the dimensions and a given lookup object.
485  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
486  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
487  * @param lookup The lookup object specifying the lookup values and the number of lookup bins
488  */
489  AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const AdvancedLookupCenter2<T, TScalar>& lookup);
490 
491  /**
492  * Returns whether a specific bin of this lookup object is valid.
493  * @param binX Horizontal bin position, with range [0, binsX() - 1]
494  * @param binY Vertical bin position, with range [0, binsY() - 1]
495  * @return True, if so
496  */
497  inline bool binCenterValid(const size_t binX, const size_t binY) const;
498 
499  /**
500  * Applies a lookup for a specific position in this lookup object.
501  * The resulting value is specified by the nearest bin (determined by the bin's center position).
502  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX() - 1]
503  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY() - 1]
504  * @param value The resulting value, if the corresponding bin is valid
505  * @return True, if the corresponding bin is valid
506  */
507  bool nearestValue(const TScalar x, const TScalar y, T& value) const;
508 
509  /**
510  * Applies a lookup for a specific position in this lookup object.
511  * The resulting value is bilinear interpolated within the 4-neighborhood of valid lookup bins.<br>
512  * The interpolation result is based on valid bins only.
513  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX() - 1]
514  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY() - 1]
515  * @param value The resulting interpolated value, if at least one corresponding bin is valid
516  * @return True, if at least one corresponding bin is valid
517  */
518  bool bilinearValue(const TScalar x, const TScalar y, T& value) const;
519 
520  /**
521  * Applies a lookup for a specific position in this lookup object.
522  * The resulting value is bilinear interpolated within the 4-neighborhood of valid lookup bins.<br>
523  * The interpolation result is based on valid bins only.
524  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX() - 1]
525  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY() - 1]
526  * @param minimalValidBins The number of minimal valid neighboring/corresponding bins the specified position must have so that interpolation is done, with range [1, 4]
527  * @param value The resulting interpolated value, if at least one corresponding bin is valid
528  * @return True, if at least 'minimalValidBins' corresponding bin are valid
529  */
530  bool bilinearValue(const TScalar x, const TScalar y, const unsigned int minimalValidBins, T& value) const;
531 
532  /**
533  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
534  * The resulting value is specified by the nearest bin (determined by the bin's corner positions).
535  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
536  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
537  * @param value The resulting value, if the corresponding bin is valid
538  * @return True, if the corresponding bin is valid
539  * @see clampedBilinearValue(), clampedBicubicValue(), nearestValue().
540  */
541  bool clampedNearestValue(const TScalar x, const TScalar y, T& value) const;
542 
543  /**
544  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
545  * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.
546  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
547  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
548  * @param value The resulting interpolated value, if at least one corresponding bin is valid
549  * @return True, if at least one corresponding bin is valid
550  * @see clampedNearestValue(), clampedBicubicValue(), bilinearValue().
551  */
552  bool clampedBilinearValue(const TScalar x, const TScalar y, T& value) const;
553 
554  /**
555  * Sets the value of one specific lookup bin's center and defines whether this bin is valid.
556  * @param binX Horizontal bin position, with range [0, binsX())
557  * @param binY Vertical bin position, with range [0, binsY())
558  * @param value The value to be set
559  * @param isValid True, if the bin is valid; False, if the bin is invalid
560  */
561  inline void setBinCenterValue(const size_t binX, const size_t binY, const T& value, const bool isValid);
562 
563  /**
564  * Sets whether a specific lookup bin is valid.
565  * @param binX Horizontal bin position, with range [0, binsX())
566  * @param binY Vertical bin position, with range [0, binsY())
567  * @param isValid True, if the bin is valid; False, if the bin is invalid
568  */
569  inline void setBinCenterValid(const size_t binX, const size_t binY, const bool isValid);
570 
571  /**
572  * Move operator.
573  * @param lookup The lookup object that will be moved
574  * @return Reference to this object
575  */
577 
578  /**
579  * Returns whether two lookup objects are identical.
580  * @param lookup Second lookup object
581  * @return True, if so
582  */
583  bool operator==(const AdvancedLookupCenter2<T, TScalar>& lookup) const;
584 
585  /**
586  * Returns whether two lookup objects are not identical.
587  * @param lookup Second lookup object
588  * @return True, if so
589  */
590  inline bool operator!=(const AdvancedLookupCenter2<T, TScalar>& lookup) const;
591 
592  protected:
593 
594  /// The vector individually storing whether a bin is valid or not.
596 };
597 
598 /**
599  * This class implements a 2D lookup object with values at the bins' corners defining the individual lookup values.
600  * This area is separated into individual neighboring bins (with absolute identical sizes) as each bin may cover a non-integer sized area of elements (e.g, pixels).<br>
601  * Thus, the positions and sizes of a bin do not match with physical elements (e.g., pixels).
602  *
603  * The lookup table with 4x2 bins has the following layout:
604  * <pre>
605  * + --- + --- + --- + --- +
606  * | | | | |
607  * + --- + --- + --- + --- +
608  * | | | | |
609  * + --- + --- + --- + --- +
610  * </pre>
611  * With '+' showing the corner positions of the lookup values.<br>
612  * Thus, the lookup table has 4 horizontal bins and 5 horizontal lookup values.<br>
613  * The first lookup value is located at the horizontal position 0 and the last lookup value is located at the horizontal position sizeX (and not sizeX - 1).<br>
614  * The vertical positions are accordingly.
615  *
616  * If this lookup table is applied to visual content like e.g. an image, the layout of a 4x2 bins object can be interpreted as follows:
617  * <pre>
618  * -----------------------
619  * |+ + + + |+
620  * | |
621  * |+ + + + |+
622  * | |
623  * -----------------------
624  * + + + + +
625  * </pre>
626  * With '-' and '|' showing the border of the image (not covering one pixel).<br>
627  * Thus, the first column of lookup values is located in the image column with index '0' while the last column of lookup values is located in the image column with index 'width' (not width - 1).<br>
628  * And the first row of lookup values is located in the image row with index '0' while the last row of lookup values it located in the image row with index 'height' (not height - 1).
629  * @tparam T The data type of the stored lookup values
630  * @tparam TScalar The data type of the scalar values, either 'float' or 'double'
631  * @see LookupCenter2
632  * @ingroup math
633  */
634 template <typename T, typename TScalar = Scalar>
635 class LookupCorner2 : public Lookup2<T, TScalar>
636 {
637  public:
638 
639  /**
640  * Creates a new empty lookup object.
641  */
642  LookupCorner2() = default;
643 
644  /**
645  * Copy constructor.
646  * @param lookup The lookup object to be copied
647  */
649 
650  /**
651  * Move constructor.
652  * @param lookup The lookup object to be moved
653  */
654  inline LookupCorner2(LookupCorner2<T, TScalar>&& lookup) noexcept;
655 
656  /**
657  * Creates a new lookup object by definition of the dimensions and bin numbers.
658  * Beware: The bin values will be initialized with the default constructor of the template class.
659  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
660  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
661  * @param binsX Number of horizontal bins, with range [1, sizeX]
662  * @param binsY Number of vertical bins, with range [1, sizeY]
663  */
664  LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY);
665 
666  /**
667  * Creates a new lookup object by definition of the dimensions and bin numbers.
668  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
669  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
670  * @param binsX Number of horizontal bins, with range [1, sizeX]
671  * @param binsY Number of vertical bins, with range [1, sizeY]
672  * @param binCornerValues The bins' corner values of the lookup object (row aligned), (binsX + 1) * (binsY + 1) values must be provided
673  */
674  LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binCornerValues);
675 
676  /**
677  * Creates a new lookup object by definition of the dimensions and a given lookup object.
678  * @param sizeX Horizontal dimension of the lookup table, with range [1, infinity)
679  * @param sizeY Vertical dimension of the lookup table, with range [1, infinity)
680  * @param lookup The lookup object specifying the lookup values and the number of lookup bins
681  */
682  LookupCorner2(const size_t sizeX, const size_t sizeY, const LookupCorner2<T, TScalar>& lookup);
683 
684  /**
685  * Returns whether a given position lies inside this lookup object and therefore whether this position can be applied for the interpolation functions.
686  * @param x Precise horizontal position for the resulting lookup value, with range (-infinity, infinity)
687  * @param y Precise vertical position for the resulting lookup value, with range (-infinity, infinity)
688  * @return True, if x and y is in the range [0, sizeX()]x[0, sizeY()]
689  */
690  inline bool isInside(const TScalar x, const TScalar y) const;
691 
692  /**
693  * Returns the horizontal bin that corresponds to a precise horizontal lookup position.
694  * @param x Precise horizontal position in relation to the dimension of this lookup object, with range [0, sizeX()]
695  * @return Resulting horizontal bin index
696  */
697  inline size_t binX(const TScalar x) const;
698 
699  /**
700  * Returns the vertical bin that corresponds to a precise vertical lookup position.
701  * @param y Precise vertical position in relation to the dimension of this lookup object, with range [0, sizeY()]
702  * @return Resulting vertical bin index
703  */
704  inline size_t binY(const TScalar y) const;
705 
706  /**
707  * Returns the horizontal corner position of a specific bin corner (the top left corner) in relation to the dimension of this lookup object.
708  * @param binX Horizontal bin position, with range [0, binsX()]
709  * @return Precise horizontal position of the specified bin in relation to the lookup object's dimension, with range [0, sizeX()]
710  */
711  inline TScalar binTopLeftCornerPositionX(const size_t binX) const;
712 
713  /**
714  * Returns the vertical corner position of a specific bin corner (the top left corner) in relation to the dimension of this lookup object.
715  * @param binY Vertical bin position, with range [0, binsY()]
716  * @return Precise vertical position of the specified bin in relation to the lookup object's dimension, with range [0, sizeY()]
717  */
718  inline TScalar binTopLeftCornerPositionY(const size_t binY) const;
719 
720  /**
721  * Returns the corner position (the top left corner) of a specific bin in relation to the dimension of this lookup object.
722  * @param binX Horizontal bin position, with range [0, binsX()]
723  * @param binY Vertical bin position, with range [0, binsY()]
724  * @return Precise position of the specified bin in relation to the lookup object's dimension, with range [0, sizeX()]x[0, sizeY()]
725  */
726  inline Vector2 binTopLeftCornerPosition(const size_t binX, const size_t binY) const;
727 
728  /**
729  * Returns the lookup value of a specific bin corner (the top left corner value) of this lookup object.
730  * @param binX Horizontal bin position, with range [0, binsX()]
731  * @param binY Vertical bin position, with range [0, binsY()]
732  * @return Bin lookup value
733  */
734  inline const T& binTopLeftCornerValue(const size_t binX, const size_t binY) const;
735 
736  /**
737  * Applies a lookup for a specific position in this lookup object.
738  * The resulting value is specified by the nearest bin (determined by the bin's corner positions).
739  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX()]
740  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY()]
741  * @return The nearest lookup value
742  * @see bilinearValue(), bicubicValue(), clampedNearestValue().
743  */
744  T nearestValue(const TScalar x, const TScalar y) const;
745 
746  /**
747  * Applies a lookup for a specific position in this lookup object.
748  * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.
749  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX()]
750  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY()]
751  * @return The bilinear interpolated lookup value
752  * @see nearestValue(), bicubicValue(), clampedBilinearValue(), bilinearValues().
753  */
754  T bilinearValue(const TScalar x, const TScalar y) const;
755 
756  /**
757  * Applies a lookup for an entire row in this lookup object.
758  * The resulting values are bilinear interpolated within the individual 4-neighborhood of the lookup bins.
759  * This function provides the same results as bilinearValue(), but for an entire row to speed up the computation.
760  * @param y The vertical position of the row for which the lookup values will be determined, with range [0, sizeY())
761  * @param values The resulting `sizeX()` lookup values
762  * @tparam TTarget The data type of the interpolated target values, e.g., T == VectorD2, TTarget == VectorF2
763  * @see bilinearValue().
764  */
765  template <typename TTarget = T>
766  void bilinearValues(const size_t y, TTarget* values) const;
767 
768  /**
769  * Applies a lookup for a subset of a row in this lookup object.
770  * The resulting values are bilinear interpolated within the individual 4-neighborhood of the lookup bins.
771  * This function provides the same results as bilinearValue(), but for a subset of the row to speed up the computation.
772  * @param x The horizontal start position for which the lookup values will be determined, with range [0, sizeX() - 1]
773  * @param y The vertical position of the row for which the lookup values will be determined, with range [0, sizeY() - 1]
774  * @param size The number of subsequent lookup values which will be created, with range [1, sizeX() - xStart]
775  * @param values The resulting `size` lookup values
776  * @tparam TTarget The data type of the interpolated target values, e.g., T == VectorD2, TTarget == VectorF2
777  * @see bilinearValue().
778  */
779  template <typename TTarget = T>
780  void bilinearValues(const size_t x, const size_t y, const size_t size, TTarget* values) const;
781 
782  /**
783  * Applies a lookup for a specific position in this lookup object but does not apply the bilinear interpolation, instead all necessary parameters will be returned.
784  * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.<br>
785  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX()]
786  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY()]
787  * @param topLeft The lookup value of the top left bin (in relation to the lookup position)
788  * @param topRight The lookup value of the top right bin (in relation to the lookup position)
789  * @param bottomLeft The lookup value of the bottom left bin (in relation to the lookup position)
790  * @param bottomRight The lookup value of the bottom right bin (in relation to the lookup position)
791  * @param factorTopLeft The interpolation value for value of the top left bin, with range [0, 1]
792  * @param factorTopRight The interpolation value for value of the top right bin, with range [0, 1]
793  * @param factorBottomLeft The interpolation value for value of the bottom left bin, with range [0, 1]
794  * @param factorBottomRight The interpolation value for value of the bottom right bin, with range [0, 1]
795  * @see nearestValue(), bicubicValue(), clampedBilinearValue().
796  */
797  void bilinearValue(const TScalar x, const TScalar y, T& topLeft, T& topRight, T& bottomLeft, T& bottomRight, TScalar& factorTopLeft, TScalar& factorTopRight, TScalar& factorBottomLeft, TScalar& factorBottomRight) const;
798 
799  /**
800  * Applies a lookup for a specific position in this lookup object.
801  * The resulting value is cubic interpolated within the 16-neighborhood of the lookup bins.<br>
802  * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX()]
803  * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY()]
804  * @return The bi-cubic interpolated lookup value
805  * @see nearestValue(), bilinearValue(), clampedBicubicValue().
806  */
807  T bicubicValue(const TScalar x, const TScalar y) const;
808 
809  /**
810  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
811  * The resulting value is specified by the nearest bin (determined by the bin's corner positions).<br>
812  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
813  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
814  * @return The nearest lookup value
815  * @see clampedBilinearValue(), clampedBicubicValue(), nearestValue().
816  */
817  T clampedNearestValue(const TScalar x, const TScalar y) const;
818 
819  /**
820  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
821  * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.<br>
822  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
823  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
824  * @return The bilinear interpolated lookup value
825  * @see clampedNearestValue(), clampedBicubicValue(), bilinearValue().
826  */
827  T clampedBilinearValue(const TScalar x, const TScalar y) const;
828 
829  /**
830  * Applies a lookup for a specific position in this lookup object while the position is clamped to match into the domain of the lookup table.
831  * The resulting value is cubic interpolated within the 16-neighborhood of the lookup bins.<br>
832  * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
833  * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
834  * @return The bi-cubic interpolated lookup value
835  * @see clampedNearestValue(), clampedBilinearValue(), bicubicValue().
836  */
837  T clampedBicubicValue(const TScalar x, const TScalar y) const;
838 
839  /**
840  * Sets the value of one specific lookup bin's top left corner.
841  * @param binX Horizontal bin position, with range [0, binsX()]
842  * @param binY Vertical bin position, with range [0, binsY()]
843  * @param value The value to be set
844  */
845  inline void setBinTopLeftCornerValue(const size_t binX, const size_t binY, const T& value);
846 
847  /**
848  * Adds an offset value to each lookup value.
849  * @param offset The offset to be added
850  * @return The new lookup object with shifted lookup values.
851  */
852  LookupCorner2<T, TScalar> operator+(const T& offset) const;
853 
854  /**
855  * Adds an offset value to each lookup value.
856  * @param offset The offset to be added
857  * @return The reference to this shifted lookup object
858  */
860 
861  /**
862  * Subtracts an offset value from each lookup value.
863  * @param offset The offset to be subtracted
864  * @return The new lookup object with shifted lookup values.
865  */
866  LookupCorner2<T, TScalar> operator-(const T& offset) const;
867 
868  /**
869  * Subtracts an offset value from each lookup value.
870  * @param offset The offset to be subtracted
871  * @return The reference to this shifted lookup object
872  */
874 
875  /**
876  * Copy operator.
877  * @param lookup The lookup object to be copied
878  * @return Reference to this object
879  */
881 
882  /**
883  * Move operator.
884  * @param lookup The lookup object to be moved
885  * @return Reference to this object
886  */
888 };
889 
890 template <typename T, typename TScalar>
892  sizeX_(lookup.sizeX_),
893  sizeY_(lookup.sizeY_),
894  binsX_(lookup.binsX_),
895  binsY_(lookup.binsY_),
896  invSizeX_(lookup.invSizeX_),
897  invSizeY_(lookup.invSizeY_),
898  invBinsX_(lookup.invBinsX_),
899  invBinsY_(lookup.invBinsY_),
900  values_(lookup.values_)
901 {
902  // nothing to do here
903 }
904 
905 template <typename T, typename TScalar>
907  sizeX_(lookup.sizeX_),
908  sizeY_(lookup.sizeY_),
909  binsX_(lookup.binsX_),
910  binsY_(lookup.binsY_),
911  invSizeX_(lookup.invSizeX_),
912  invSizeY_(lookup.invSizeY_),
913  invBinsX_(lookup.invBinsX_),
914  invBinsY_(lookup.invBinsY_),
915  values_(std::move(lookup.values_))
916 {
917  lookup.sizeX_ = 0;
918  lookup.sizeY_ = 0;
919  lookup.binsX_ = 0;
920  lookup.binsY_ = 0;
921 
922  lookup.invSizeX_ = 0;
923  lookup.invSizeY_ = 0;
924  lookup.invBinsX_ = 0;
925  lookup.invBinsY_ = 0;
926 }
927 
928 template <typename T, typename TScalar>
929 inline const T* Lookup2<T, TScalar>::data() const
930 {
931  return values_.data();
932 }
933 
934 template <typename T, typename TScalar>
936 {
937  return values_.data();
938 }
939 
940 template <typename T, typename TScalar>
941 inline size_t Lookup2<T, TScalar>::sizeX() const
942 {
943  return sizeX_;
944 }
945 
946 template <typename T, typename TScalar>
947 inline size_t Lookup2<T, TScalar>::sizeY() const
948 {
949  return sizeY_;
950 }
951 
952 template <typename T, typename TScalar>
953 inline size_t Lookup2<T, TScalar>::binsX() const
954 {
955  return binsX_;
956 }
957 
958 template <typename T, typename TScalar>
959 inline size_t Lookup2<T, TScalar>::binsY() const
960 {
961  return binsY_;
962 }
963 
964 template <typename T, typename TScalar>
966 {
967  sizeX_ = lookup.sizeX_;
968  sizeY_ = lookup.sizeY_;
969  binsX_ = lookup.binsX_;
970  binsY_ = lookup.binsY_;
971  invSizeX_ = lookup.invSizeX_;
972  invSizeY_ = lookup.invSizeY_;
973  invBinsX_ = lookup.invBinsX_;
974  invBinsY_ = lookup.invBinsY_;
975  values_ = lookup.values_;
976 
977  return *this;
978 }
979 
980 template <typename T, typename TScalar>
982 {
983  if (this != &lookup)
984  {
985  sizeX_ = lookup.sizeX_;
986  sizeY_ = lookup.sizeY_;
987  binsX_ = lookup.binsX_;
988  binsY_ = lookup.binsY_;
989  invSizeX_ = lookup.invSizeX_;
990  invSizeY_ = lookup.invSizeY_;
991  invBinsX_ = lookup.invBinsX_;
992  invBinsY_ = lookup.invBinsY_;
993  values_ = std::move(lookup.values_);
994 
995  lookup.sizeX_ = 0;
996  lookup.sizeY_ = 0;
997  lookup.binsX_ = 0;
998  lookup.binsY_ = 0;
999  lookup.invSizeX_ = 0;
1000  lookup.invSizeY_ = 0;
1001  lookup.invBinsX_ = 0;
1002  lookup.invBinsY_ = 0;
1003  }
1004 
1005  return *this;
1006 }
1007 
1008 template <typename T, typename TScalar>
1009 inline bool Lookup2<T, TScalar>::isEmpty() const
1010 {
1011  return values_.empty();
1012 }
1013 
1014 template <typename T, typename TScalar>
1016 {
1017  return !values_.empty();
1018 }
1019 
1020 template <typename T, typename TScalar>
1022 {
1023  return sizeX_ == lookup.sizeX_ && sizeY_ == lookup.sizeY_ && binsX_ == lookup.binsX_ && binsY_ == lookup.binsY_ && values_ == lookup.values_;
1024 }
1025 
1026 template <typename T, typename TScalar>
1028 {
1029  return !(*this == lookup);
1030 }
1031 
1032 template <typename T, typename TScalar>
1034  Lookup2<T, TScalar>(lookup)
1035 {
1036  // nothing to do here
1037 }
1038 
1039 template <typename T, typename TScalar>
1041  Lookup2<T, TScalar>(std::move(lookup))
1042 {
1043  // nothing to do here
1044 }
1045 
1046 template <typename T, typename TScalar>
1047 LookupCenter2<T, TScalar>::LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY) :
1048  Lookup2<T, TScalar>()
1049 {
1050  this->sizeX_ = sizeX;
1051  this->sizeY_ = sizeY;
1052  this->binsX_ = min(binsX, sizeX);
1053  this->binsY_ = min(binsY, sizeY);
1054  this->values_.resize(this->binsX_ * this->binsY_);
1055 
1056  ocean_assert(binsX <= sizeX);
1057  ocean_assert(binsY <= sizeY);
1058 
1059  ocean_assert(sizeX > 0);
1060  ocean_assert(sizeY > 0);
1061  this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1062  this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1063 
1064  ocean_assert(binsX > 0);
1065  ocean_assert(binsY > 0);
1066  this->invBinsX_ = TScalar(1) / TScalar(binsX);
1067  this->invBinsY_ = TScalar(1) / TScalar(binsY);
1068 }
1069 
1070 template <typename T, typename TScalar>
1071 LookupCenter2<T, TScalar>::LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binValues) :
1072  Lookup2<T, TScalar>()
1073 {
1074  ocean_assert(binValues);
1075 
1076  this->sizeX_ = sizeX;
1077  this->sizeY_ = sizeY;
1078  this->binsX_ = min(binsX, sizeX);
1079  this->binsY_ = min(binsY, sizeY);
1080  this->values_.resize(this->binsX_ * this->binsY_);
1081 
1082  ocean_assert(binsX <= sizeX);
1083  ocean_assert(binsY <= sizeY);
1084 
1085  ocean_assert(sizeX > 0);
1086  ocean_assert(sizeY > 0);
1087  this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1088  this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1089 
1090  ocean_assert(binsX > 0);
1091  ocean_assert(binsY > 0);
1092  this->invBinsX_ = TScalar(1) / TScalar(binsX);
1093  this->invBinsY_ = TScalar(1) / TScalar(binsY);
1094 
1095  for (size_t n = 0; n < this->values_.size(); ++n)
1096  {
1097  this->values_[n] = binValues[n];
1098  }
1099 }
1100 
1101 template <typename T, typename TScalar>
1102 LookupCenter2<T, TScalar>::LookupCenter2(const size_t sizeX, const size_t sizeY, const LookupCenter2<T, TScalar>& lookup) :
1103  Lookup2<T, TScalar>()
1104 {
1105  this->sizeX_ = sizeX;
1106  this->sizeY_ = sizeY;
1107  this->binsX_ = lookup.binsX_;
1108  this->binsY_ = lookup.binsY_;
1109  this->values_ = lookup.values_;
1110 
1111  ocean_assert(this->binsX_ <= sizeX);
1112  ocean_assert(this->binsY_ <= sizeY);
1113 
1114  ocean_assert(sizeX > 0);
1115  ocean_assert(sizeY > 0);
1116  this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1117  this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1118 
1119  ocean_assert(this->binsX_ > 0);
1120  ocean_assert(this->binsY_ > 0);
1121  this->invBinsX_ = TScalar(1) / TScalar(this->binsX_);
1122  this->invBinsY_ = TScalar(1) / TScalar(this->binsY_);
1123 }
1124 
1125 template <typename T, typename TScalar>
1126 inline bool LookupCenter2<T, TScalar>::isInside(const TScalar x, const TScalar y) const
1127 {
1128  ocean_assert(!this->isEmpty());
1129  return x >= TScalar(0) && y >= TScalar(0) && x <= TScalar(this->sizeX_ - 1) && y <= TScalar(this->sizeY_ - 1);
1130 }
1131 
1132 template <typename T, typename TScalar>
1133 inline size_t LookupCenter2<T, TScalar>::binX(const TScalar x) const
1134 {
1135  ocean_assert(this->sizeX_ > 0);
1136  ocean_assert(x >= 0 && x <= TScalar(this->sizeX_ - 1));
1137 
1138  const size_t result = size_t(x * TScalar(this->binsX_) * this->invSizeX_ + (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps()));
1139  ocean_assert(result < this->binsX_);
1140 
1141  return result;
1142 }
1143 
1144 template <typename T, typename TScalar>
1145 inline size_t LookupCenter2<T, TScalar>::binY(const TScalar y) const
1146 {
1147  ocean_assert(this->sizeY_ > 0);
1148  ocean_assert(y >= 0 && y <= TScalar(this->sizeY_ - 1));
1149 
1150  const size_t result = size_t(y * TScalar(this->binsY_) * this->invSizeY_ + (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps()));
1151  ocean_assert(result < this->binsY_);
1152 
1153  return result;
1154 }
1155 
1156 template <typename T, typename TScalar>
1157 inline size_t LookupCenter2<T, TScalar>::binTopLeftX(const size_t binX) const
1158 {
1159  ocean_assert(binX < this->binsX_);
1160 
1161  const size_t x = size_t(NumericT<TScalar>::ceil(TScalar(binX * this->sizeX_) * this->invBinsX_ - (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps())));
1162  ocean_assert(binX == this->binX(TScalar(x)));
1163 
1164  return x;
1165 }
1166 
1167 template <typename T, typename TScalar>
1168 inline size_t LookupCenter2<T, TScalar>::binTopLeftY(const size_t binY) const
1169 {
1170  ocean_assert(binY < this->binsY_);
1171 
1172  const size_t y = size_t(NumericT<TScalar>::ceil(TScalar(binY * this->sizeY_) * this->invBinsY_ - (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps())));
1173  ocean_assert(binY == this->binY(TScalar(y)));
1174 
1175  return y;
1176 }
1177 
1178 template <typename T, typename TScalar>
1179 inline size_t LookupCenter2<T, TScalar>::binBottomRightX(const size_t binX) const
1180 {
1181  ocean_assert(binX < this->binsX_);
1182 
1183  const size_t x = size_t(NumericT<TScalar>::ceil(TScalar((binX + 1) * this->sizeX_) * this->invBinsX_ - (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps())));
1184 
1185  ocean_assert(x >= 1);
1186  ocean_assert(binX == this->binX(TScalar(x - 1)));
1187 
1188  return x - 1;
1189 }
1190 
1191 template <typename T, typename TScalar>
1192 inline size_t LookupCenter2<T, TScalar>::binBottomRightY(const size_t binY) const
1193 {
1194  ocean_assert(binY < this->binsY_);
1195 
1196  const size_t y = size_t(NumericT<TScalar>::ceil(TScalar((binY + 1) * this->sizeY_) * this->invBinsY_ - (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps())));
1197 
1198  ocean_assert(y >= 1);
1199  ocean_assert(binY == this->binY(TScalar(y - 1)));
1200 
1201  return y - 1;
1202 }
1203 
1204 template <typename T, typename TScalar>
1205 inline TScalar LookupCenter2<T, TScalar>::binCenterPositionX(const size_t binX) const
1206 {
1207  ocean_assert(binX < this->binsX_);
1208 
1209  const TScalar result = TScalar(binTopLeftX(binX) + binBottomRightX(binX)) * TScalar(0.5);
1210  ocean_assert(result >= 0 && result < TScalar(this->sizeX_));
1211 
1212  return result;
1213 }
1214 
1215 template <typename T, typename TScalar>
1216 inline TScalar LookupCenter2<T, TScalar>::binCenterPositionY(const size_t binY) const
1217 {
1218  ocean_assert(binY < this->binsY_);
1219 
1220  const TScalar result = TScalar(binTopLeftY(binY) + binBottomRightY(binY)) * TScalar(0.5);
1221  ocean_assert(result >= 0 && result < TScalar(this->sizeY_));
1222 
1223  return result;
1224 }
1225 
1226 template <typename T, typename TScalar>
1227 inline Vector2 LookupCenter2<T, TScalar>::binCenterPosition(const size_t binX, const size_t binY) const
1228 {
1229  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1230 
1231  return Vector2(binCenterPositionX(binX), binCenterPositionY(binY));
1232 }
1233 
1234 template <typename T, typename TScalar>
1235 inline const T& LookupCenter2<T, TScalar>::binCenterValue(const size_t binX, const size_t binY) const
1236 {
1237  ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1238  return this->values_[binY * this->binsX_ + binX];
1239 }
1240 
1241 template <typename T, typename TScalar>
1242 inline T& LookupCenter2<T, TScalar>::binCenterValue(const size_t binX, const size_t binY)
1243 {
1244  ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1245  return this->values_[binY * this->binsX_ + binX];
1246 }
1247 
1248 template <typename T, typename TScalar>
1249 T LookupCenter2<T, TScalar>::nearestValue(const TScalar x, const TScalar y) const
1250 {
1251  ocean_assert(this->isInside(x, y));
1252 
1253  const size_t bx = this->binX(x);
1254  const size_t by = this->binY(y);
1255 
1256  return this->values_[by * this->binsX_ + bx];
1257 }
1258 
1259 template <typename T, typename TScalar>
1260 T LookupCenter2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y) const
1261 {
1262  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1263  ocean_assert(this->isInside(x, y));
1264 
1265  const size_t bX = this->binX(x);
1266  const size_t bY = this->binY(y);
1267 
1268  const TScalar bCenterX = this->binCenterPositionX(bX);
1269  const TScalar bCenterY = this->binCenterPositionY(bY);
1270 
1271  const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1272  const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1273  const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1274  const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1275  ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1276  ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1277 
1278  const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1279  const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1280  const TScalar topCenter = this->binCenterPositionY(yLowBin);
1281  const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1282  ocean_assert(leftCenter <= rightCenter);
1283  ocean_assert(topCenter <= bottomCenter);
1284 
1285  ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1286  ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1287 
1288  const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1289  const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1290 
1291  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1292  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1293 
1294  const TScalar factorTopLeft = (TScalar(1) - xFactor) * (TScalar(1) - yFactor);
1295  const TScalar factorTopRight = xFactor * (TScalar(1) - yFactor);
1296  const TScalar factorBottomLeft = (TScalar(1) - xFactor) * yFactor;
1297  const TScalar factorBottomRight = xFactor * yFactor;
1298 
1299  const T& topLeft = binCenterValue(xLowBin, yLowBin);
1300  const T& topRight = binCenterValue(xHighBin, yLowBin);
1301  const T& bottomLeft = binCenterValue(xLowBin, yHighBin);
1302  const T& bottomRight = binCenterValue(xHighBin, yHighBin);
1303 
1304  return topLeft * factorTopLeft + topRight * factorTopRight
1305  + bottomLeft * factorBottomLeft + bottomRight * factorBottomRight;
1306 }
1307 
1308 template <typename T, typename TScalar>
1309 T LookupCenter2<T, TScalar>::bicubicValue(const TScalar x, const TScalar y) const
1310 {
1311  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1312  ocean_assert(this->isInside(x, y));
1313 
1314  const size_t bX = this->binX(x);
1315  const size_t bY = this->binY(y);
1316 
1317  const TScalar bCenterX = this->binCenterPositionX(bX);
1318  const TScalar bCenterY = this->binCenterPositionY(bY);
1319 
1320  const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1321  const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1322  const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1323  const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1324  ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1325  ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1326 
1327  // determine the supporting positions
1328  const size_t xMinusBin = max(0, int(xLowBin) - 1);
1329  const size_t xPlusBin = min(xHighBin + 1, this->binsX_ - 1);
1330  const size_t yMinusBin = max(0, int(yLowBin) - 1);
1331  const size_t yPlusBin = min(yHighBin + 1, this->binsY_ - 1);
1332 
1333  const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1334  const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1335  const TScalar topCenter = this->binCenterPositionY(yLowBin);
1336  const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1337  ocean_assert(leftCenter <= rightCenter);
1338  ocean_assert(topCenter <= bottomCenter);
1339 
1340  ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1341  ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1342 
1343  const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1344  const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1345 
1346  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1347  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1348 
1349  return Interpolation::cubic(Interpolation::cubic(binCenterValue(xMinusBin, yMinusBin), binCenterValue(xLowBin, yMinusBin), binCenterValue(xHighBin, yMinusBin), binCenterValue(xPlusBin, yMinusBin), xFactor),
1350  Interpolation::cubic(binCenterValue(xMinusBin, yLowBin), binCenterValue(xLowBin, yLowBin), binCenterValue(xHighBin, yLowBin), binCenterValue(xPlusBin, yLowBin), xFactor),
1351  Interpolation::cubic(binCenterValue(xMinusBin, yHighBin), binCenterValue(xLowBin, yHighBin), binCenterValue(xHighBin, yHighBin), binCenterValue(xPlusBin, yHighBin), xFactor),
1352  Interpolation::cubic(binCenterValue(xMinusBin, yPlusBin), binCenterValue(xLowBin, yPlusBin), binCenterValue(xHighBin, yPlusBin), binCenterValue(xPlusBin, yPlusBin), xFactor), yFactor);
1353 }
1354 
1355 template <typename T, typename TScalar>
1356 T LookupCenter2<T, TScalar>::clampedNearestValue(const TScalar x, const TScalar y) const
1357 {
1358  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1359 
1360  return nearestValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)));
1361 }
1362 
1363 template <typename T, typename TScalar>
1364 T LookupCenter2<T, TScalar>::clampedBilinearValue(const TScalar x, const TScalar y) const
1365 {
1366  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1367 
1368  return bilinearValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)));
1369 }
1370 
1371 template <typename T, typename TScalar>
1372 T LookupCenter2<T, TScalar>::clampedBicubicValue(const TScalar x, const TScalar y) const
1373 {
1374  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1375 
1376  return bicubicValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)));
1377 }
1378 
1379 template <typename T, typename TScalar>
1380 inline void LookupCenter2<T, TScalar>::setBinCenterValue(const size_t binX, const size_t binY, const T& value)
1381 {
1382  ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1383  this->values_[binY * this->binsX_ + binX] = value;
1384 }
1385 
1386 template <typename T, typename TScalar>
1388 {
1389  Lookup2<T, TScalar>::operator=(std::move(lookup));
1390  return *this;
1391 }
1392 
1393 template <typename T, typename TScalar>
1395  LookupCenter2<T, TScalar>(lookup),
1396  validBins_(lookup.validBins_)
1397 {
1398  // nothing to do here
1399 }
1400 
1401 template <typename T, typename TScalar>
1403  LookupCenter2<T, TScalar>(lookup),
1404  validBins_(std::move(lookup.validBins_))
1405 {
1406  // nothing to do here
1407 }
1408 
1409 template <typename T, typename TScalar>
1410 AdvancedLookupCenter2<T, TScalar>::AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY) :
1411  LookupCenter2<T, TScalar>(sizeX, sizeY, binsX, binsY),
1412  validBins_(binsX * binsY, 1u)
1413 {
1414  // nothing to do here
1415 }
1416 
1417 template <typename T, typename TScalar>
1418 AdvancedLookupCenter2<T, TScalar>::AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const bool binsValid) :
1419  LookupCenter2<T, TScalar>(sizeX, sizeY, binsX, binsY),
1420  validBins_(binsX * binsY, binsValid ? 1u : 0u)
1421 {
1422  // nothing to do here
1423 }
1424 
1425 template <typename T, typename TScalar>
1426 AdvancedLookupCenter2<T, TScalar>::AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binValues, const unsigned char* validBins) :
1427  LookupCenter2<T, TScalar>(sizeX, sizeY, binsX, binsY, binValues),
1428  validBins_(binsX * binsY)
1429 {
1430  memcpy(validBins_.data(), validBins, binsX * binsY * sizeof(unsigned char));
1431 }
1432 
1433 template <typename T, typename TScalar>
1435  LookupCenter2<T, TScalar>(sizeX, sizeY, lookup),
1436  validBins_(lookup.validBins_)
1437 {
1438  // nothing to do here
1439 }
1440 
1441 template <typename T, typename TScalar>
1442 inline bool AdvancedLookupCenter2<T, TScalar>::binCenterValid(const size_t binX, const size_t binY) const
1443 {
1444  ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1445  return validBins_[binY * this->binsX_ + binX] != 0u;
1446 }
1447 
1448 template <typename T, typename TScalar>
1449 bool AdvancedLookupCenter2<T, TScalar>::nearestValue(const TScalar x, const TScalar y, T& value) const
1450 {
1451  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1452  ocean_assert(this->values_.size() == validBins_.size());
1453  ocean_assert(this->isInside(x, y));
1454 
1455  const size_t bx = this->binX(x);
1456  const size_t by = this->binY(y);
1457 
1458  if (validBins_[by * this->binsX_ + bx] == 0u)
1459  {
1460  return false;
1461  }
1462 
1463  value = this->values_[by * this->binsX_ + bx];
1464  return true;
1465 }
1466 
1467 template <typename T, typename TScalar>
1468 bool AdvancedLookupCenter2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y, T& value) const
1469 {
1470  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1471  ocean_assert(this->values_.size() == validBins_.size());
1472  ocean_assert(this->isInside(x, y));
1473 
1474  const size_t bX = this->binX(x);
1475  const size_t bY = this->binY(y);
1476 
1477  const TScalar bCenterX = this->binCenterPositionX(bX);
1478  const TScalar bCenterY = this->binCenterPositionY(bY);
1479 
1480  const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1481  const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1482  const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1483  const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1484  ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1485  ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1486 
1487  const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1488  const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1489  const TScalar topCenter = this->binCenterPositionY(yLowBin);
1490  const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1491  ocean_assert(leftCenter <= rightCenter);
1492  ocean_assert(topCenter <= bottomCenter);
1493 
1494  ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1495  ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1496 
1497  const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1498  const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1499 
1500  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1501  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1502 
1503  const T& topLeft = this->binCenterValue(xLowBin, yLowBin);
1504  const T& topRight = this->binCenterValue(xHighBin, yLowBin);
1505  const T& bottomLeft = this->binCenterValue(xLowBin, yHighBin);
1506  const T& bottomRight = this->binCenterValue(xHighBin, yHighBin);
1507 
1508  const bool validTopLeft = validBins_[yLowBin * this->binsX_ + xLowBin] != 0u;
1509  const bool validTopRight = validBins_[yLowBin * this->binsX_ + xHighBin] != 0u;
1510  const bool validBottomLeft = validBins_[yHighBin * this->binsX_ + xLowBin] != 0u;
1511  const bool validBottomRight = validBins_[yHighBin * this->binsX_ + xHighBin] != 0u;
1512 
1513  if (validTopLeft || validTopRight || validBottomLeft || validBottomRight)
1514  {
1515  value = Interpolation::bilinear(topLeft, topRight, bottomLeft, bottomRight, validTopLeft, validTopRight, validBottomLeft, validBottomRight, xFactor, yFactor);
1516  return true;
1517  }
1518 
1519  return false;
1520 }
1521 
1522 template <typename T, typename TScalar>
1523 bool AdvancedLookupCenter2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y, const unsigned int minimalValidBins, T& value) const
1524 {
1525  ocean_assert(minimalValidBins >= 1u && minimalValidBins <= 4u);
1526  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1527  ocean_assert(this->values_.size() == validBins_.size());
1528  ocean_assert(this->isInside(x, y));
1529 
1530  const size_t bX = this->binX(x);
1531  const size_t bY = this->binY(y);
1532 
1533  const TScalar bCenterX = this->binCenterPositionX(bX);
1534  const TScalar bCenterY = this->binCenterPositionY(bY);
1535 
1536  const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1537  const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1538  const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1539  const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1540  ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1541  ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1542 
1543  const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1544  const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1545  const TScalar topCenter = this->binCenterPositionY(yLowBin);
1546  const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1547  ocean_assert(leftCenter <= rightCenter);
1548  ocean_assert(topCenter <= bottomCenter);
1549 
1550  ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1551  ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1552 
1553  const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1554  const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1555 
1556  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1557  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1558 
1559  const T& topLeft = this->binCenterValue(xLowBin, yLowBin);
1560  const T& topRight = this->binCenterValue(xHighBin, yLowBin);
1561  const T& bottomLeft = this->binCenterValue(xLowBin, yHighBin);
1562  const T& bottomRight = this->binCenterValue(xHighBin, yHighBin);
1563 
1564  const bool validTopLeft = validBins_[yLowBin * this->binsX_ + xLowBin] != 0u;
1565  const bool validTopRight = validBins_[yLowBin * this->binsX_ + xHighBin] != 0u;
1566  const bool validBottomLeft = validBins_[yHighBin * this->binsX_ + xLowBin] != 0u;
1567  const bool validBottomRight = validBins_[yHighBin * this->binsX_ + xHighBin] != 0u;
1568 
1569  ocean_assert(validTopLeft == 0 || validTopLeft == 1);
1570  ocean_assert(validTopRight == 0 || validTopRight == 1);
1571  ocean_assert(validBottomLeft == 0 || validBottomLeft == 1);
1572  ocean_assert(validBottomRight == 0 || validBottomRight == 1);
1573 
1574  if ((unsigned int)(validTopLeft + validTopRight + validBottomLeft + validBottomRight) >= minimalValidBins)
1575  {
1576  value = Interpolation::bilinear(topLeft, topRight, bottomLeft, bottomRight, validTopLeft, validTopRight, validBottomLeft, validBottomRight, xFactor, yFactor);
1577  return true;
1578  }
1579 
1580  return false;
1581 }
1582 
1583 template <typename T, typename TScalar>
1584 bool AdvancedLookupCenter2<T, TScalar>::clampedNearestValue(const TScalar x, const TScalar y, T& value) const
1585 {
1586  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1587 
1588  return nearestValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)), value);
1589 }
1590 
1591 template <typename T, typename TScalar>
1592 bool AdvancedLookupCenter2<T, TScalar>::clampedBilinearValue(const TScalar x, const TScalar y, T& value) const
1593 {
1594  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1595 
1596  return bilinearValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)), value);
1597 }
1598 
1599 template <typename T, typename TScalar>
1600 inline void AdvancedLookupCenter2<T, TScalar>::setBinCenterValue(const size_t binX, const size_t binY, const T& value, const bool isValid)
1601 {
1602  ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1603 
1604  this->values_[binY * this->binsX_ + binX] = value;
1605  validBins_[binY * this->binsX_ + binX] = isValid ? 1u : 0u;
1606 }
1607 
1608 template <typename T, typename TScalar>
1609 inline void AdvancedLookupCenter2<T, TScalar>::setBinCenterValid(const size_t binX, const size_t binY, const bool isValid)
1610 {
1611  ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1612  validBins_[binY * this->binsX_ + binX] = isValid ? 1u: 0u;
1613 }
1614 
1615 template <typename T, typename TScalar>
1617 {
1618  if (this != &lookup)
1619  {
1620  LookupCenter2<T, TScalar>::operator=(std::move(lookup));
1621  validBins_ = std::move(lookup.validBins_);
1622  }
1623 
1624  return *this;
1625 }
1626 
1627 template <typename T, typename TScalar>
1629 {
1630  return validBins_ == lookup.validBins_ && (LookupCenter2<T, TScalar>&)*this == (LookupCenter2<T, TScalar>&)lookup;
1631 }
1632 
1633 template <typename T, typename TScalar>
1635 {
1636  return !(*this == lookup);
1637 }
1638 
1639 template <typename T, typename TScalar>
1641  Lookup2<T, TScalar>(std::move(lookup))
1642 {
1643  // nothing to do here
1644 }
1645 
1646 template <typename T, typename TScalar>
1648  Lookup2<T, TScalar>(std::move(lookup))
1649 {
1650  // nothing to do here
1651 }
1652 
1653 template <typename T, typename TScalar>
1654 LookupCorner2<T, TScalar>::LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY) :
1655  Lookup2<T, TScalar>()
1656 {
1657  this->sizeX_ = sizeX;
1658  this->sizeY_ = sizeY;
1659  this->binsX_ = min(binsX, sizeX);
1660  this->binsY_ = min(binsY, sizeY);
1661  this->values_.resize((this->binsX_ + 1) * (this->binsY_ + 1));
1662 
1663  ocean_assert(binsX <= sizeX);
1664  ocean_assert(binsY <= sizeY);
1665 
1666  ocean_assert(sizeX >= 1);
1667  ocean_assert(sizeY >= 1);
1668  this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1669  this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1670 
1671  ocean_assert(binsX > 0);
1672  ocean_assert(binsY > 0);
1673  this->invBinsX_ = TScalar(1) / TScalar(binsX);
1674  this->invBinsY_ = TScalar(1) / TScalar(binsY);
1675 }
1676 
1677 template <typename T, typename TScalar>
1678 LookupCorner2<T, TScalar>::LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binCornerValues) :
1679  Lookup2<T, TScalar>()
1680 {
1681  ocean_assert(binCornerValues);
1682 
1683  this->sizeX_ = sizeX;
1684  this->sizeY_ = sizeY;
1685  this->binsX_ = min(binsX, sizeX);
1686  this->binsY_ = min(binsY, sizeY);
1687  this->values_.resize((this->binsX_ + 1) * (this->binsY_ + 1));
1688 
1689  ocean_assert(binsX <= sizeX);
1690  ocean_assert(binsY <= sizeY);
1691 
1692  ocean_assert(sizeX > 1);
1693  ocean_assert(sizeY > 1);
1694  this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1695  this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1696 
1697  ocean_assert(binsX > 0);
1698  ocean_assert(binsY > 0);
1699  this->invBinsX_ = TScalar(1) / TScalar(binsX);
1700  this->invBinsY_ = TScalar(1) / TScalar(binsY);
1701 
1702  for (size_t n = 0; n < this->values_.size(); ++n)
1703  {
1704  this->values_[n] = binCornerValues[n];
1705  }
1706 }
1707 
1708 template <typename T, typename TScalar>
1709 LookupCorner2<T, TScalar>::LookupCorner2(const size_t sizeX, const size_t sizeY, const LookupCorner2<T, TScalar>& lookup) :
1710  Lookup2<T, TScalar>()
1711 {
1712  this->sizeX_ = sizeX;
1713  this->sizeY_ = sizeY;
1714  this->binsX_ = lookup.binsX_;
1715  this->binsY_ = lookup.binsY_;
1716  this->values_ = lookup.values_;
1717 
1718  ocean_assert(this->binsX_ <= sizeX);
1719  ocean_assert(this->binsY_ <= sizeY);
1720 
1721  ocean_assert(sizeX > 1);
1722  ocean_assert(sizeY > 1);
1723  this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1724  this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1725 
1726  ocean_assert(this->binsX_ > 0);
1727  ocean_assert(this->binsY_ > 0);
1728  this->invBinsX_ = TScalar(1) / TScalar(this->binsX_);
1729  this->invBinsY_ = TScalar(1) / TScalar(this->binsY_);
1730 }
1731 
1732 template <typename T, typename TScalar>
1733 inline bool LookupCorner2<T, TScalar>::isInside(const TScalar x, const TScalar y) const
1734 {
1735  ocean_assert(!this->isEmpty());
1736  return x >= TScalar(0) && y >= TScalar(0) && x <= TScalar(this->sizeX_) && y <= TScalar(this->sizeY_);
1737 }
1738 
1739 template <typename T, typename TScalar>
1740 inline size_t LookupCorner2<T, TScalar>::binX(const TScalar x) const
1741 {
1742  ocean_assert(this->sizeX_ > 0);
1743  ocean_assert(x >= 0 && x <= TScalar(this->sizeX_));
1744 
1745  const size_t result = size_t(x * TScalar(this->binsX_) * this->invSizeX_);
1746  ocean_assert(result <= this->binsX_);
1747 
1748  return result;
1749 }
1750 
1751 template <typename T, typename TScalar>
1752 inline size_t LookupCorner2<T, TScalar>::binY(const TScalar y) const
1753 {
1754  ocean_assert(this->sizeY_ > 0);
1755  ocean_assert(y >= 0 && y <= TScalar(this->sizeY_));
1756 
1757  const size_t result = size_t(y * TScalar(this->binsY_) * this->invSizeY_);
1758  ocean_assert(result <= this->binsY_);
1759 
1760  return result;
1761 }
1762 
1763 template <typename T, typename TScalar>
1764 inline TScalar LookupCorner2<T, TScalar>::binTopLeftCornerPositionX(const size_t binX) const
1765 {
1766  ocean_assert(binX <= this->binsX_ && this->sizeX_ >= 1);
1767 
1768  const TScalar result = TScalar(binX * this->sizeX_) * this->invBinsX_;
1769 
1770  // the clamping is necessary due to tiny rounding issues
1771  return minmax<TScalar>(0, result, TScalar(this->sizeX_));
1772 }
1773 
1774 template <typename T, typename TScalar>
1775 inline TScalar LookupCorner2<T, TScalar>::binTopLeftCornerPositionY(const size_t binY) const
1776 {
1777  ocean_assert(binY <= this->binsY_ && this->sizeY_ >= 1);
1778 
1779  const TScalar result = TScalar(binY * this->sizeY_) * this->invBinsY_;
1780 
1781  // the clamping is necessary due to tiny rounding issues
1782  return minmax<TScalar>(0, result, TScalar(this->sizeY_));
1783 }
1784 
1785 template <typename T, typename TScalar>
1786 inline Vector2 LookupCorner2<T, TScalar>::binTopLeftCornerPosition(const size_t binX, const size_t binY) const
1787 {
1788  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1789 
1790  return Vector2(binTopLeftCornerPositionX(binX), binTopLeftCornerPositionY(binY));
1791 }
1792 
1793 template <typename T, typename TScalar>
1794 inline const T& LookupCorner2<T, TScalar>::binTopLeftCornerValue(const size_t binX, const size_t binY) const
1795 {
1796  ocean_assert(binX <= this->binsX_ && binY <= this->binsY_);
1797  return this->values_[binY * (this->binsX_ + 1) + binX];
1798 }
1799 
1800 template <typename T, typename TScalar>
1801 T LookupCorner2<T, TScalar>::nearestValue(const TScalar x, const TScalar y) const
1802 {
1803  ocean_assert(this->isInside(x, y));
1804 
1805  const size_t bx = size_t(x * TScalar(this->binsX_) * this->invSizeX_ + TScalar(0.5));
1806  ocean_assert(bx <= this->binsX_);
1807 
1808  const size_t by = size_t(y * TScalar(this->binsY_) * this->invSizeY_ + TScalar(0.5));
1809  ocean_assert(by <= this->binsY_);
1810 
1811  return this->values_[by * (this->binsX_ + 1) + bx];
1812 }
1813 
1814 template <typename T, typename TScalar>
1815 T LookupCorner2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y) const
1816 {
1817  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1818  ocean_assert(this->isInside(x, y));
1819 
1820  const size_t xLowBin = this->binX(x);
1821  const size_t yLowBin = this->binY(y);
1822 
1823  ocean_assert(xLowBin <= this->binsX_);
1824  ocean_assert(yLowBin <= this->binsY_);
1825 
1826  const TScalar leftPosition = this->binTopLeftCornerPositionX(xLowBin);
1827  const TScalar topPosition = this->binTopLeftCornerPositionY(yLowBin);
1828 
1829  const TScalar xFactor = (x - leftPosition) * TScalar(this->binsX_) * this->invSizeX_;
1830  const TScalar yFactor = (y - topPosition) * TScalar(this->binsY_) * this->invSizeY_;
1831 
1832 #ifdef OCEAN_DEBUG
1833  if (std::is_same<TScalar, float>::value)
1834  {
1835  ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, xFactor, 1));
1836  ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, yFactor, 1));
1837  }
1838  else
1839  {
1840  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1841  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1842  }
1843 #endif
1844 
1845  const TScalar factorTopLeft = (TScalar(1) - xFactor) * (TScalar(1) - yFactor);
1846  const TScalar factorTopRight = xFactor * (TScalar(1) - yFactor);
1847  const TScalar factorBottomLeft = (TScalar(1) - xFactor) * yFactor;
1848  const TScalar factorBottomRight = xFactor * yFactor;
1849 
1850  const size_t xHighBin = min(xLowBin + 1, this->binsX_);
1851  const size_t yHighBin = min(yLowBin + 1, this->binsY_);
1852 
1853  const T& topLeft = this->binTopLeftCornerValue(xLowBin, yLowBin);
1854  const T& topRight = this->binTopLeftCornerValue(xHighBin, yLowBin);
1855  const T& bottomLeft = this->binTopLeftCornerValue(xLowBin, yHighBin);
1856  const T& bottomRight = this->binTopLeftCornerValue(xHighBin, yHighBin);
1857 
1858  return topLeft * factorTopLeft + topRight * factorTopRight
1859  + bottomLeft * factorBottomLeft + bottomRight * factorBottomRight;
1860 }
1861 
1862 template <typename T, typename TScalar>
1863 template <typename TTarget>
1864 void LookupCorner2<T, TScalar>::bilinearValues(const size_t y, TTarget* values) const
1865 {
1866  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1867  ocean_assert(this->binsX_ <= this->sizeX_ && this->binsY_ <= this->sizeY_);
1868 
1869  ocean_assert(y < this->sizeY_);
1870  ocean_assert(values != nullptr);
1871 
1872  const size_t yLowBin = (y * this->binsY_) / this->sizeY_;
1873  ocean_assert(yLowBin < this->binsY_);
1874  ocean_assert(std::abs(int(yLowBin) - int(this->binY(TScalar(y)))) <= 1);
1875 
1876  const size_t yHighBin = yLowBin + 1;
1877  ocean_assert(yHighBin <= this->binsY_);
1878 
1879  const TScalar yLowBinPosition = this->binTopLeftCornerPositionY(yLowBin);
1880  const TScalar yHighBinPosition = this->binTopLeftCornerPositionY(yHighBin);
1881  ocean_assert(yLowBinPosition < yHighBinPosition);
1882 
1883  const TScalar yFactor = (TScalar(y) - yLowBinPosition) / (yHighBinPosition - yLowBinPosition);
1884  ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), yFactor, TScalar(1)));
1885 
1886  const Vector2* lowBinValues = this->values_.data() + (yLowBin * (this->binsX_ + 1));
1887  const Vector2* highBinValues = this->values_.data() + (yHighBin * (this->binsX_ + 1));
1888 
1889  Vector2 leftBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1890  Vector2 rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1891 
1892  unsigned int nextBinX = 1u;
1893 
1894  TScalar leftBinPositionX = TScalar(0);
1895  TScalar rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1896 
1897  ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1898  TScalar invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1899 
1900  for (size_t x = 0; x < this->sizeX_; ++x)
1901  {
1902  if (TScalar(x) > rightBinPositionX)
1903  {
1904  leftBinValue = rightBinValue;
1905  rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1906 
1907  leftBinPositionX = rightBinPositionX;
1908  rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1909 
1910  ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1911  invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1912  }
1913 
1914  ocean_assert(leftBinPositionX <= TScalar(x));
1915 
1916  const TScalar xFactor = (TScalar(x) - leftBinPositionX) * invBinWidthX;
1917 
1918  if constexpr (std::is_same<TScalar, float>::value)
1919  {
1920  ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), xFactor, TScalar(1)));
1921  }
1922  else
1923  {
1924  ocean_assert(NumericT<TScalar>::isInsideRange(TScalar(0), xFactor, TScalar(1)));
1925  }
1926 
1927  values[x] = TTarget(leftBinValue * (TScalar(1) - xFactor) + rightBinValue * xFactor);
1928 
1929 #ifdef OCEAN_DEBUG
1930  const T debugTestValue = this->bilinearValue(TScalar(x), TScalar(y));
1931  const TScalar debugError = debugTestValue.distance(T(values[x]));
1932  ocean_assert(debugError < TScalar(0.1));
1933 #endif
1934  }
1935 }
1936 
1937 template <typename T, typename TScalar>
1938 template <typename TTarget>
1939 void LookupCorner2<T, TScalar>::bilinearValues(const size_t x, const size_t y, const size_t size, TTarget* values) const
1940 {
1941  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1942  ocean_assert(this->binsX_ <= this->sizeX_ && this->binsY_ <= this->sizeY_);
1943 
1944  ocean_assert(x + size <= this->sizeX_);
1945 
1946  ocean_assert(y < this->sizeY_);
1947  ocean_assert(values != nullptr);
1948 
1949  ocean_assert(size >= 1);
1950 
1951  const size_t xLowBin = (x * this->binsX_) / this->sizeX_;
1952  ocean_assert(xLowBin < this->binsX_);
1953  ocean_assert(std::abs(int(xLowBin) - int(this->binX(TScalar(x)))) <= 1);
1954 
1955  const size_t yLowBin = (y * this->binsY_) / this->sizeY_;
1956  ocean_assert(yLowBin < this->binsY_);
1957  ocean_assert(std::abs(int(yLowBin) - int(this->binY(TScalar(y)))) <= 1);
1958 
1959  const size_t yHighBin = yLowBin + 1;
1960  ocean_assert(yHighBin <= this->binsY_);
1961 
1962  const TScalar yLowBinPosition = this->binTopLeftCornerPositionY(yLowBin);
1963  const TScalar yHighBinPosition = this->binTopLeftCornerPositionY(yHighBin);
1964  ocean_assert(yLowBinPosition < yHighBinPosition);
1965 
1966  const TScalar yFactor = (TScalar(y) - yLowBinPosition) / (yHighBinPosition - yLowBinPosition);
1967  ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), yFactor, TScalar(1)));
1968 
1969  const Vector2* lowBinValues = this->values_.data() + (yLowBin * (this->binsX_ + 1)) + xLowBin;
1970  const Vector2* highBinValues = this->values_.data() + (yHighBin * (this->binsX_ + 1)) + xLowBin;
1971 
1972  Vector2 leftBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1973  Vector2 rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1974 
1975  size_t nextBinX = xLowBin + 1u;
1976 
1977  TScalar leftBinPositionX = TScalar(xLowBin * this->sizeX_) * this->invBinsX_;
1978  TScalar rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1979 
1980  ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1981  TScalar invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1982 
1983  for (size_t nX = x; nX < x + size; ++nX)
1984  {
1985  if (TScalar(nX) > rightBinPositionX)
1986  {
1987  leftBinValue = rightBinValue;
1988  rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1989 
1990  leftBinPositionX = rightBinPositionX;
1991  rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1992 
1993  ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1994  invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1995  }
1996 
1997  ocean_assert(leftBinPositionX <= TScalar(nX) + NumericT<TScalar>::weakEps());
1998 
1999  const TScalar xFactor = (TScalar(nX) - leftBinPositionX) * invBinWidthX;
2000  ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), xFactor, TScalar(1)));
2001 
2002  *values++ = TTarget(leftBinValue * (TScalar(1) - xFactor) + rightBinValue * xFactor);
2003 
2004 #ifdef OCEAN_DEBUG
2005  const T debugTestValue = this->bilinearValue(TScalar(nX), TScalar(y));
2006  const TScalar debugError = debugTestValue.distance(T(TTarget(leftBinValue * (TScalar(1) - xFactor) + rightBinValue * xFactor)));
2007  ocean_assert(debugError < TScalar(0.1));
2008 #endif
2009  }
2010 }
2011 
2012 template <typename T, typename TScalar>
2013 void LookupCorner2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y, T& topLeft, T& topRight, T& bottomLeft, T& bottomRight, TScalar& factorTopLeft, TScalar& factorTopRight, TScalar& factorBottomLeft, TScalar& factorBottomRight) const
2014 {
2015  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2016  ocean_assert(this->isInside(x, y));
2017 
2018  const size_t xLowBin = this->binX(x);
2019  const size_t yLowBin = this->binY(y);
2020 
2021  ocean_assert(xLowBin <= this->binsX_);
2022  ocean_assert(yLowBin <= this->binsY_);
2023 
2024  const TScalar leftPosition = this->binTopLeftCornerPositionX(xLowBin);
2025  const TScalar topPosition = this->binTopLeftCornerPositionY(yLowBin);
2026 
2027  const TScalar xFactor = (x - leftPosition) * TScalar(this->binsX_) * this->invSizeX_;
2028  const TScalar yFactor = (y - topPosition) * TScalar(this->binsY_) * this->invSizeY_;
2029 
2030 #ifdef OCEAN_DEBUG
2031  if (std::is_same<TScalar, float>::value)
2032  {
2033  ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, xFactor, 1));
2034  ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, yFactor, 1));
2035  }
2036  else
2037  {
2038  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
2039  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
2040  }
2041 #endif
2042 
2043  factorTopLeft = (TScalar(1) - xFactor) * (TScalar(1) - yFactor);
2044  factorTopRight = xFactor * (TScalar(1) - yFactor);
2045  factorBottomLeft = (TScalar(1) - xFactor) * yFactor;
2046  factorBottomRight = xFactor * yFactor;
2047 
2048  const size_t xHighBin = min(xLowBin + 1, this->binsX_);
2049  const size_t yHighBin = min(yLowBin + 1, this->binsY_);
2050 
2051  topLeft = this->binTopLeftCornerValue(xLowBin, yLowBin);
2052  topRight = this->binTopLeftCornerValue(xHighBin, yLowBin);
2053  bottomLeft = this->binTopLeftCornerValue(xLowBin, yHighBin);
2054  bottomRight = this->binTopLeftCornerValue(xHighBin, yHighBin);
2055 }
2056 
2057 template <typename T, typename TScalar>
2058 T LookupCorner2<T, TScalar>::bicubicValue(const TScalar x, const TScalar y) const
2059 {
2060  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2061  ocean_assert(this->isInside(x, y));
2062 
2063  const size_t xLowBin = this->binX(x);
2064  const size_t yLowBin = this->binY(y);
2065 
2066  ocean_assert(xLowBin <= this->binsX_);
2067  ocean_assert(yLowBin <= this->binsY_);
2068 
2069  const TScalar leftPosition = this->binTopLeftCornerPositionX(xLowBin);
2070  const TScalar topPosition = this->binTopLeftCornerPositionY(yLowBin);
2071 
2072  const TScalar xFactor = (x - leftPosition) * TScalar(this->binsX_) * this->invSizeX_;
2073  const TScalar yFactor = (y - topPosition) * TScalar(this->binsY_) * this->invSizeY_;
2074 
2075 #ifdef OCEAN_DEBUG
2076  if (std::is_same<TScalar, float>::value)
2077  {
2078  ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, xFactor, 1));
2079  ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, yFactor, 1));
2080  }
2081  else
2082  {
2083  ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
2084  ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
2085  }
2086 #endif
2087 
2088  const size_t xHighBin = min(xLowBin + 1, this->binsX_);
2089  const size_t yHighBin = min(yLowBin + 1, this->binsY_);
2090 
2091  // determine the supporting positions
2092  const size_t xMinusBin = max(0, int(xLowBin) - 1);
2093  const size_t xPlusBin = min(xLowBin + 2, this->binsX_);
2094  const size_t yMinusBin = max(0, int(yLowBin) - 1);
2095  const size_t yPlusBin = min(yLowBin + 2, this->binsY_);
2096 
2097  return Interpolation::cubic(Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yMinusBin), binTopLeftCornerValue(xLowBin, yMinusBin), binTopLeftCornerValue(xHighBin, yMinusBin), binTopLeftCornerValue(xPlusBin, yMinusBin), xFactor),
2098  Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yLowBin), binTopLeftCornerValue(xLowBin, yLowBin), binTopLeftCornerValue(xHighBin, yLowBin), binTopLeftCornerValue(xPlusBin, yLowBin), xFactor),
2099  Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yHighBin), binTopLeftCornerValue(xLowBin, yHighBin), binTopLeftCornerValue(xHighBin, yHighBin), binTopLeftCornerValue(xPlusBin, yHighBin), xFactor),
2100  Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yPlusBin), binTopLeftCornerValue(xLowBin, yPlusBin), binTopLeftCornerValue(xHighBin, yPlusBin), binTopLeftCornerValue(xPlusBin, yPlusBin), xFactor), yFactor);
2101 }
2102 
2103 template <typename T, typename TScalar>
2104 T LookupCorner2<T, TScalar>::clampedNearestValue(const TScalar x, const TScalar y) const
2105 {
2106  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2107 
2108  return nearestValue(minmax<TScalar>(0, x, TScalar(this->sizeX_)), minmax<TScalar>(0, y, TScalar(this->sizeY_)));
2109 }
2110 
2111 template <typename T, typename TScalar>
2112 T LookupCorner2<T, TScalar>::clampedBilinearValue(const TScalar x, const TScalar y) const
2113 {
2114  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2115 
2116  return bilinearValue(minmax<TScalar>(0, x, TScalar(this->sizeX_)), minmax<TScalar>(0, y, TScalar(this->sizeY_)));
2117 }
2118 
2119 template <typename T, typename TScalar>
2120 T LookupCorner2<T, TScalar>::clampedBicubicValue(const TScalar x, const TScalar y) const
2121 {
2122  ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2123 
2124  return bicubicValue(minmax<TScalar>(0, x, TScalar(this->sizeX_)), minmax<TScalar>(0, y, TScalar(this->sizeY_)));
2125 }
2126 
2127 template <typename T, typename TScalar>
2128 inline void LookupCorner2<T, TScalar>::setBinTopLeftCornerValue(const size_t binX, const size_t binY, const T& value)
2129 {
2130  ocean_assert(binX <= this->binsX_ && binY <= this->binsY_);
2131  this->values_[binY * (this->binsX_ + 1) + binX] = value;
2132 }
2133 
2134 template <typename T, typename TScalar>
2136 {
2137  LookupCorner2<T, TScalar> result(*this);
2138 
2139  for (size_t n = 0; n < result.values_.size(); ++n)
2140  {
2141  result.values_[n] += offset;
2142  }
2143 
2144  return result;
2145 }
2146 
2147 template <typename T, typename TScalar>
2149 {
2150  for (size_t n = 0; n < this->values_.size(); ++n)
2151  {
2152  this->values_[n] += offset;
2153  }
2154 
2155  return *this;
2156 }
2157 
2158 template <typename T, typename TScalar>
2160 {
2161  LookupCorner2<T, TScalar> result(*this);
2162 
2163  for (size_t n = 0; n < result.values_.size(); ++n)
2164  {
2165  result.values_[n] -= offset;
2166  }
2167 
2168  return result;
2169 }
2170 
2171 template <typename T, typename TScalar>
2173 {
2174  for (size_t n = 0; n < this->values_.size(); ++n)
2175  {
2176  this->values_[n] -= offset;
2177  }
2178 
2179  return *this;
2180 }
2181 
2182 template <typename T, typename TScalar>
2184 {
2186  return *this;
2187 }
2188 
2189 template <typename T, typename TScalar>
2191 {
2192  Lookup2<T, TScalar>::operator=(std::move(lookup));
2193  return *this;
2194 }
2195 
2196 }
2197 
2198 #endif // META_OCEAN_MATH_LOOKUP2_H
This class implements an advanced 2D lookup object with values at the bins' center positions defining...
Definition: Lookup2.h:424
void setBinCenterValid(const size_t binX, const size_t binY, const bool isValid)
Sets whether a specific lookup bin is valid.
Definition: Lookup2.h:1609
bool nearestValue(const TScalar x, const TScalar y, T &value) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1449
bool bilinearValue(const TScalar x, const TScalar y, T &value) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1468
ValidBins validBins_
The vector individually storing whether a bin is valid or not.
Definition: Lookup2.h:595
bool clampedBilinearValue(const TScalar x, const TScalar y, T &value) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:1592
bool operator!=(const AdvancedLookupCenter2< T, TScalar > &lookup) const
Returns whether two lookup objects are not identical.
Definition: Lookup2.h:1634
AdvancedLookupCenter2()=default
Creates a new empty lookup object.
std::vector< unsigned char > ValidBins
Definition of a vector holding 1 byte values.
Definition: Lookup2.h:430
void setBinCenterValue(const size_t binX, const size_t binY, const T &value, const bool isValid)
Sets the value of one specific lookup bin's center and defines whether this bin is valid.
Definition: Lookup2.h:1600
bool clampedNearestValue(const TScalar x, const TScalar y, T &value) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:1584
bool operator==(const AdvancedLookupCenter2< T, TScalar > &lookup) const
Returns whether two lookup objects are identical.
Definition: Lookup2.h:1628
bool binCenterValid(const size_t binX, const size_t binY) const
Returns whether a specific bin of this lookup object is valid.
Definition: Lookup2.h:1442
AdvancedLookupCenter2< T, TScalar > & operator=(AdvancedLookupCenter2< T, TScalar > &&lookup) noexcept
Move operator.
Definition: Lookup2.h:1616
static T cubic(const T &v0, const T &v1, const T &v2, const T &v3, const TFactor &t)
Performs a cubic (Catmull-Rom) interpolation between mainly two values while two further supporting p...
Definition: Interpolation.h:627
static T bilinear(const T &v00, const T &v01, const T &v10, const T &v11, const TFactor &tx, const TFactor &ty)
Performs a bi-linear interpolation between four values within a 2x2 neighborhood.
Definition: Interpolation.h:525
This class implements a 2D lookup object allowing to separate a two dimensional lookup area into indi...
Definition: Lookup2.h:30
Values values_
The values of the lookup bins.
Definition: Lookup2.h:169
std::vector< T > Values
Definition of a vector holding lookup values.
Definition: Lookup2.h:43
Lookup2< T, TScalar > & operator=(const Lookup2< T, TScalar > &lookup)
Assign operator.
Definition: Lookup2.h:965
TScalar invBinsY_
Inverse number of vertical bins.
Definition: Lookup2.h:166
size_t binsY_
Number of vertical bins.
Definition: Lookup2.h:154
size_t sizeY() const
Returns the vertical dimension of this lookup object.
Definition: Lookup2.h:947
const T * data() const
Returns a pointer to the constant bin data (row aligned).
Definition: Lookup2.h:929
TScalar invSizeY_
Inverse vertical dimension of this lookup object.
Definition: Lookup2.h:160
T * data()
Returns a pointer to the bin data (row aligned).
Definition: Lookup2.h:935
size_t binsX_
Number of horizontal bins.
Definition: Lookup2.h:151
Lookup2(Lookup2< T, TScalar > &&lookup) noexcept
Move constructor.
Definition: Lookup2.h:906
Lookup2< T, TScalar > & operator=(Lookup2< T, TScalar > &&lookup) noexcept
Move operator.
Definition: Lookup2.h:981
size_t sizeX_
Horizontal dimension of this lookup object.
Definition: Lookup2.h:145
size_t sizeX() const
Returns the horizontal dimension of this lookup object.
Definition: Lookup2.h:941
bool operator==(const Lookup2< T, TScalar > &lookup) const
Returns whether two lookup objects are identical.
Definition: Lookup2.h:1021
bool isEmpty() const
Returns whether this lookup object does not hold any lookup bin.
Definition: Lookup2.h:1009
size_t binsY() const
Returns the number of vertical bins of this lookup object.
Definition: Lookup2.h:959
size_t sizeY_
Vertical dimension of this lookup object.
Definition: Lookup2.h:148
Lookup2(const Lookup2< T, TScalar > &lookup)
Copy constructor.
Definition: Lookup2.h:891
TScalar invBinsX_
Inverse number of horizontal bins.
Definition: Lookup2.h:163
size_t binsX() const
Returns the number of horizontal bins of this lookup object.
Definition: Lookup2.h:953
T Type
Definition of the lookup data type.
Definition: Lookup2.h:36
bool operator!=(const Lookup2< T, TScalar > &lookup) const
Returns whether two lookup objects are not identical.
Definition: Lookup2.h:1027
TScalar invSizeX_
Inverse horizontal dimension of this lookup object.
Definition: Lookup2.h:157
Lookup2()=default
Creates a new empty lookup object.
This class implements a 2D lookup object with values at the bins' center positions defining the indiv...
Definition: Lookup2.h:198
T nearestValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1249
LookupCenter2< T, TScalar > & operator=(LookupCenter2< T, TScalar > &&lookup) noexcept
Move operator.
Definition: Lookup2.h:1387
void setBinCenterValue(const size_t binX, const size_t binY, const T &value)
Sets the value of one specific lookup bin's center.
Definition: Lookup2.h:1380
TScalar binCenterPositionY(const size_t binY) const
Returns the vertical center position of a specific bin in relation to the dimension of this lookup ob...
Definition: Lookup2.h:1216
T clampedBilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:1364
T clampedNearestValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:1356
T bicubicValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1309
LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY)
Creates a new lookup object by definition of the dimensions and bin numbers.
Definition: Lookup2.h:1047
size_t binY(const TScalar y) const
Returns the vertical bin that corresponds to a precise vertical lookup position.
Definition: Lookup2.h:1145
size_t binTopLeftY(const size_t binY) const
Returns the vertical top left position of a specified bin with pixel accuracy.
Definition: Lookup2.h:1168
T clampedBicubicValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:1372
LookupCenter2(const LookupCenter2< T, TScalar > &lookup)
Copy constructor.
Definition: Lookup2.h:1033
size_t binBottomRightY(const size_t binY) const
Returns the vertical bottom right position of a specified bin with pixel accuracy.
Definition: Lookup2.h:1192
LookupCenter2()=default
Creates a new empty lookup object.
LookupCenter2(LookupCenter2< T, TScalar > &&lookup) noexcept
Move constructor.
Definition: Lookup2.h:1040
TScalar binCenterPositionX(const size_t binX) const
Returns the horizontal center position of a specific bin in relation to the dimension of this lookup ...
Definition: Lookup2.h:1205
size_t binBottomRightX(const size_t binX) const
Returns the horizontal bottom right position (including) of a specified bin with pixel accuracy.
Definition: Lookup2.h:1179
size_t binTopLeftX(const size_t binX) const
Returns the horizontal top left position of a specified bin with pixel accuracy.
Definition: Lookup2.h:1157
LookupCenter2(const size_t sizeX, const size_t sizeY, const LookupCenter2< T, TScalar > &lookup)
Creates a new lookup object by definition of the dimensions and a given lookup object.
Definition: Lookup2.h:1102
Vector2 binCenterPosition(const size_t binX, const size_t binY) const
Returns the center position of a specific bin in relation to the dimension of this lookup object.
Definition: Lookup2.h:1227
size_t binX(const TScalar x) const
Returns the horizontal bin that corresponds to a precise horizontal lookup position.
Definition: Lookup2.h:1133
const T & binCenterValue(const size_t binX, const size_t binY) const
Returns the lookup value of a specific bin's center of this lookup object.
Definition: Lookup2.h:1235
T bilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1260
bool isInside(const TScalar x, const TScalar y) const
Returns whether a given position lies inside this lookup object and therefore whether this position c...
Definition: Lookup2.h:1126
LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T *binValues)
Creates a new lookup object by definition of the dimensions and bin numbers.
Definition: Lookup2.h:1071
T & binCenterValue(const size_t binX, const size_t binY)
Returns the lookup value of a specific bin's center of this lookup object.
Definition: Lookup2.h:1242
This class implements a 2D lookup object with values at the bins' corners defining the individual loo...
Definition: Lookup2.h:636
LookupCorner2(LookupCorner2< T, TScalar > &&lookup) noexcept
Move constructor.
Definition: Lookup2.h:1647
T clampedNearestValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:2104
LookupCorner2()=default
Creates a new empty lookup object.
T clampedBicubicValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:2120
LookupCorner2< T, TScalar > & operator+=(const T &offset)
Adds an offset value to each lookup value.
Definition: Lookup2.h:2148
bool isInside(const TScalar x, const TScalar y) const
Returns whether a given position lies inside this lookup object and therefore whether this position c...
Definition: Lookup2.h:1733
LookupCorner2< T, TScalar > operator+(const T &offset) const
Adds an offset value to each lookup value.
Definition: Lookup2.h:2135
Vector2 binTopLeftCornerPosition(const size_t binX, const size_t binY) const
Returns the corner position (the top left corner) of a specific bin in relation to the dimension of t...
Definition: Lookup2.h:1786
const T & binTopLeftCornerValue(const size_t binX, const size_t binY) const
Returns the lookup value of a specific bin corner (the top left corner value) of this lookup object.
Definition: Lookup2.h:1794
size_t binX(const TScalar x) const
Returns the horizontal bin that corresponds to a precise horizontal lookup position.
Definition: Lookup2.h:1740
void bilinearValue(const TScalar x, const TScalar y, T &topLeft, T &topRight, T &bottomLeft, T &bottomRight, TScalar &factorTopLeft, TScalar &factorTopRight, TScalar &factorBottomLeft, TScalar &factorBottomRight) const
Applies a lookup for a specific position in this lookup object but does not apply the bilinear interp...
Definition: Lookup2.h:2013
LookupCorner2(const size_t sizeX, const size_t sizeY, const LookupCorner2< T, TScalar > &lookup)
Creates a new lookup object by definition of the dimensions and a given lookup object.
Definition: Lookup2.h:1709
void setBinTopLeftCornerValue(const size_t binX, const size_t binY, const T &value)
Sets the value of one specific lookup bin's top left corner.
Definition: Lookup2.h:2128
LookupCorner2< T, TScalar > & operator-=(const T &offset)
Subtracts an offset value from each lookup value.
Definition: Lookup2.h:2172
void bilinearValues(const size_t y, TTarget *values) const
Applies a lookup for an entire row in this lookup object.
Definition: Lookup2.h:1864
T nearestValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1801
T clampedBilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object while the position is clamped to match...
Definition: Lookup2.h:2112
T bicubicValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:2058
size_t binY(const TScalar y) const
Returns the vertical bin that corresponds to a precise vertical lookup position.
Definition: Lookup2.h:1752
void bilinearValues(const size_t x, const size_t y, const size_t size, TTarget *values) const
Applies a lookup for a subset of a row in this lookup object.
Definition: Lookup2.h:1939
T bilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1815
LookupCorner2(const LookupCorner2< T, TScalar > &lookup)
Copy constructor.
Definition: Lookup2.h:1640
LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T *binCornerValues)
Creates a new lookup object by definition of the dimensions and bin numbers.
Definition: Lookup2.h:1678
LookupCorner2< T, TScalar > operator-(const T &offset) const
Subtracts an offset value from each lookup value.
Definition: Lookup2.h:2159
TScalar binTopLeftCornerPositionY(const size_t binY) const
Returns the vertical corner position of a specific bin corner (the top left corner) in relation to th...
Definition: Lookup2.h:1775
LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY)
Creates a new lookup object by definition of the dimensions and bin numbers.
Definition: Lookup2.h:1654
TScalar binTopLeftCornerPositionX(const size_t binX) const
Returns the horizontal corner position of a specific bin corner (the top left corner) in relation to ...
Definition: Lookup2.h:1764
LookupCorner2< T, TScalar > & operator=(LookupCorner2< T, TScalar > &&lookup) noexcept
Move operator.
Definition: Lookup2.h:2190
LookupCorner2< T, TScalar > & operator=(const LookupCorner2< T, TScalar > &lookup)
Copy operator.
Definition: Lookup2.h:2183
This class provides basic numeric functionalities.
Definition: Numeric.h:57
const T * data() const noexcept
Returns an pointer to the vector elements.
Definition: Vector2.h:722
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition: Vector2.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15