Ocean
Loading...
Searching...
No Matches
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
17namespace 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 */
28template <typename T, typename TScalar = Scalar>
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 */
196template <typename T, typename TScalar = Scalar>
197class 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 */
422template <typename T, typename TScalar = Scalar>
423class 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 */
634template <typename T, typename TScalar = Scalar>
635class 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
890template <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
905template <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
928template <typename T, typename TScalar>
929inline const T* Lookup2<T, TScalar>::data() const
930{
931 return values_.data();
932}
933
934template <typename T, typename TScalar>
936{
937 return values_.data();
938}
939
940template <typename T, typename TScalar>
941inline size_t Lookup2<T, TScalar>::sizeX() const
942{
943 return sizeX_;
944}
945
946template <typename T, typename TScalar>
947inline size_t Lookup2<T, TScalar>::sizeY() const
948{
949 return sizeY_;
950}
951
952template <typename T, typename TScalar>
953inline size_t Lookup2<T, TScalar>::binsX() const
954{
955 return binsX_;
956}
957
958template <typename T, typename TScalar>
959inline size_t Lookup2<T, TScalar>::binsY() const
960{
961 return binsY_;
962}
963
964template <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
980template <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
1008template <typename T, typename TScalar>
1010{
1011 return values_.empty();
1012}
1013
1014template <typename T, typename TScalar>
1016{
1017 return !values_.empty();
1018}
1019
1020template <typename T, typename TScalar>
1022{
1023 return sizeX_ == lookup.sizeX_ && sizeY_ == lookup.sizeY_ && binsX_ == lookup.binsX_ && binsY_ == lookup.binsY_ && values_ == lookup.values_;
1024}
1025
1026template <typename T, typename TScalar>
1028{
1029 return !(*this == lookup);
1030}
1031
1032template <typename T, typename TScalar>
1034 Lookup2<T, TScalar>(lookup)
1035{
1036 // nothing to do here
1037}
1038
1039template <typename T, typename TScalar>
1041 Lookup2<T, TScalar>(std::move(lookup))
1042{
1043 // nothing to do here
1044}
1045
1046template <typename T, typename TScalar>
1047LookupCenter2<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
1070template <typename T, typename TScalar>
1071LookupCenter2<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
1101template <typename T, typename TScalar>
1102LookupCenter2<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
1125template <typename T, typename TScalar>
1126inline 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
1132template <typename T, typename TScalar>
1133inline 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
1144template <typename T, typename TScalar>
1145inline 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
1156template <typename T, typename TScalar>
1157inline 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
1167template <typename T, typename TScalar>
1168inline 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
1178template <typename T, typename TScalar>
1179inline 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
1191template <typename T, typename TScalar>
1192inline 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
1204template <typename T, typename TScalar>
1205inline 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
1215template <typename T, typename TScalar>
1216inline 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
1226template <typename T, typename TScalar>
1227inline 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
1234template <typename T, typename TScalar>
1235inline 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
1241template <typename T, typename TScalar>
1242inline 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
1248template <typename T, typename TScalar>
1249T 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
1259template <typename T, typename TScalar>
1260T 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
1308template <typename T, typename TScalar>
1309T 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
1355template <typename T, typename TScalar>
1356T 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
1363template <typename T, typename TScalar>
1364T 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
1371template <typename T, typename TScalar>
1372T 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
1379template <typename T, typename TScalar>
1380inline 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
1386template <typename T, typename TScalar>
1392
1393template <typename T, typename TScalar>
1395 LookupCenter2<T, TScalar>(lookup),
1396 validBins_(lookup.validBins_)
1397{
1398 // nothing to do here
1399}
1400
1401template <typename T, typename TScalar>
1404 validBins_(std::move(lookup.validBins_))
1405{
1406 // nothing to do here
1407}
1408
1409template <typename T, typename TScalar>
1410AdvancedLookupCenter2<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
1417template <typename T, typename TScalar>
1418AdvancedLookupCenter2<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
1425template <typename T, typename TScalar>
1426AdvancedLookupCenter2<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
1433template <typename T, typename TScalar>
1435 LookupCenter2<T, TScalar>(sizeX, sizeY, lookup),
1436 validBins_(lookup.validBins_)
1437{
1438 // nothing to do here
1439}
1440
1441template <typename T, typename TScalar>
1442inline 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
1448template <typename T, typename TScalar>
1449bool 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
1467template <typename T, typename TScalar>
1468bool 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
1522template <typename T, typename TScalar>
1523bool 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
1583template <typename T, typename TScalar>
1584bool 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
1591template <typename T, typename TScalar>
1592bool 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
1599template <typename T, typename TScalar>
1600inline 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
1608template <typename T, typename TScalar>
1609inline 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
1615template <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
1627template <typename T, typename TScalar>
1629{
1630 return validBins_ == lookup.validBins_ && (LookupCenter2<T, TScalar>&)*this == (LookupCenter2<T, TScalar>&)lookup;
1631}
1632
1633template <typename T, typename TScalar>
1635{
1636 return !(*this == lookup);
1637}
1638
1639template <typename T, typename TScalar>
1641 Lookup2<T, TScalar>(std::move(lookup))
1642{
1643 // nothing to do here
1644}
1645
1646template <typename T, typename TScalar>
1648 Lookup2<T, TScalar>(std::move(lookup))
1649{
1650 // nothing to do here
1651}
1652
1653template <typename T, typename TScalar>
1654LookupCorner2<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
1677template <typename T, typename TScalar>
1678LookupCorner2<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
1708template <typename T, typename TScalar>
1709LookupCorner2<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
1732template <typename T, typename TScalar>
1733inline 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
1739template <typename T, typename TScalar>
1740inline 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
1751template <typename T, typename TScalar>
1752inline 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
1763template <typename T, typename TScalar>
1764inline 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
1774template <typename T, typename TScalar>
1775inline 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
1785template <typename T, typename TScalar>
1786inline 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
1793template <typename T, typename TScalar>
1794inline 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
1800template <typename T, typename TScalar>
1801T 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
1814template <typename T, typename TScalar>
1815T 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
1862template <typename T, typename TScalar>
1863template <typename TTarget>
1864void 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
1937template <typename T, typename TScalar>
1938template <typename TTarget>
1939void 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
2012template <typename T, typename TScalar>
2013void 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
2057template <typename T, typename TScalar>
2058T 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
2103template <typename T, typename TScalar>
2104T 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
2111template <typename T, typename TScalar>
2112T 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
2119template <typename T, typename TScalar>
2120T 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
2127template <typename T, typename TScalar>
2128inline 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
2134template <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
2147template <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
2158template <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
2171template <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
2182template <typename T, typename TScalar>
2188
2189template <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
static constexpr T eps()
Returns a small epsilon.
const T * data() const noexcept
Returns an pointer to the vector elements.
Definition Vector2.h:734
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition Vector2.h:28
The namespace covering the entire Ocean framework.
Definition Accessor.h:15