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 using Type = T;
37
38 protected:
39
40 /**
41 * Definition of a vector holding lookup values.
42 */
43 using Values = std::vector<T>;
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 using ValidBins = std::vector<unsigned char>;
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 an entire row in this lookup object, with an option to use an optimized accumulation path.
784 * When isOptimized is false, delegates to the existing bilinearValues(y, values) implementation.
785 * When isOptimized is true, uses an additive accumulation approach that replaces per-pixel lerp with per-pixel addition.
786 * @param y The vertical position of the row for which the lookup values will be determined, with range [0, sizeY())
787 * @param values The resulting `sizeX()` lookup values
788 * @param isOptimized True to use the optimized accumulation path; false to use the standard bilinear interpolation
789 * @tparam TTarget The data type of the interpolated target values, e.g., T == VectorD2, TTarget == VectorF2
790 * @see bilinearValues().
791 */
792 template <typename TTarget = T>
793 void bilinearValues(const size_t y, TTarget* values, const bool isOptimized) const;
794
795 /**
796 * 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.
797 * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.<br>
798 * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX()]
799 * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY()]
800 * @param topLeft The lookup value of the top left bin (in relation to the lookup position)
801 * @param topRight The lookup value of the top right bin (in relation to the lookup position)
802 * @param bottomLeft The lookup value of the bottom left bin (in relation to the lookup position)
803 * @param bottomRight The lookup value of the bottom right bin (in relation to the lookup position)
804 * @param factorTopLeft The interpolation value for value of the top left bin, with range [0, 1]
805 * @param factorTopRight The interpolation value for value of the top right bin, with range [0, 1]
806 * @param factorBottomLeft The interpolation value for value of the bottom left bin, with range [0, 1]
807 * @param factorBottomRight The interpolation value for value of the bottom right bin, with range [0, 1]
808 * @see nearestValue(), bicubicValue(), clampedBilinearValue().
809 */
810 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;
811
812 /**
813 * Applies a lookup for a specific position in this lookup object.
814 * The resulting value is cubic interpolated within the 16-neighborhood of the lookup bins.<br>
815 * @param x Precise horizontal position for the resulting lookup value, with range [0, sizeX()]
816 * @param y Precise vertical position for the resulting lookup value, with range [0, sizeY()]
817 * @return The bi-cubic interpolated lookup value
818 * @see nearestValue(), bilinearValue(), clampedBicubicValue().
819 */
820 T bicubicValue(const TScalar x, const TScalar y) const;
821
822 /**
823 * 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.
824 * The resulting value is specified by the nearest bin (determined by the bin's corner positions).<br>
825 * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
826 * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
827 * @return The nearest lookup value
828 * @see clampedBilinearValue(), clampedBicubicValue(), nearestValue().
829 */
830 T clampedNearestValue(const TScalar x, const TScalar y) const;
831
832 /**
833 * 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.
834 * The resulting value is bilinear interpolated within the 4-neighborhood of the lookup bins.<br>
835 * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
836 * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
837 * @return The bilinear interpolated lookup value
838 * @see clampedNearestValue(), clampedBicubicValue(), bilinearValue().
839 */
840 T clampedBilinearValue(const TScalar x, const TScalar y) const;
841
842 /**
843 * 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.
844 * The resulting value is cubic interpolated within the 16-neighborhood of the lookup bins.<br>
845 * @param x Precise horizontal position for the resulting lookup value, with range -(infinity, infinity)
846 * @param y Precise vertical position for the resulting lookup value, with range -(infinity, infinity)
847 * @return The bi-cubic interpolated lookup value
848 * @see clampedNearestValue(), clampedBilinearValue(), bicubicValue().
849 */
850 T clampedBicubicValue(const TScalar x, const TScalar y) const;
851
852 /**
853 * Sets the value of one specific lookup bin's top left corner.
854 * @param binX Horizontal bin position, with range [0, binsX()]
855 * @param binY Vertical bin position, with range [0, binsY()]
856 * @param value The value to be set
857 */
858 inline void setBinTopLeftCornerValue(const size_t binX, const size_t binY, const T& value);
859
860 /**
861 * Adds an offset value to each lookup value.
862 * @param offset The offset to be added
863 * @return The new lookup object with shifted lookup values.
864 */
865 LookupCorner2<T, TScalar> operator+(const T& offset) const;
866
867 /**
868 * Adds an offset value to each lookup value.
869 * @param offset The offset to be added
870 * @return The reference to this shifted lookup object
871 */
873
874 /**
875 * Subtracts an offset value from each lookup value.
876 * @param offset The offset to be subtracted
877 * @return The new lookup object with shifted lookup values.
878 */
879 LookupCorner2<T, TScalar> operator-(const T& offset) const;
880
881 /**
882 * Subtracts an offset value from each lookup value.
883 * @param offset The offset to be subtracted
884 * @return The reference to this shifted lookup object
885 */
887
888 /**
889 * Copy operator.
890 * @param lookup The lookup object to be copied
891 * @return Reference to this object
892 */
894
895 /**
896 * Move operator.
897 * @param lookup The lookup object to be moved
898 * @return Reference to this object
899 */
901};
902
903template <typename T, typename TScalar>
905 sizeX_(lookup.sizeX_),
906 sizeY_(lookup.sizeY_),
907 binsX_(lookup.binsX_),
908 binsY_(lookup.binsY_),
909 invSizeX_(lookup.invSizeX_),
910 invSizeY_(lookup.invSizeY_),
911 invBinsX_(lookup.invBinsX_),
912 invBinsY_(lookup.invBinsY_),
913 values_(lookup.values_)
914{
915 // nothing to do here
916}
917
918template <typename T, typename TScalar>
920 sizeX_(lookup.sizeX_),
921 sizeY_(lookup.sizeY_),
922 binsX_(lookup.binsX_),
923 binsY_(lookup.binsY_),
924 invSizeX_(lookup.invSizeX_),
925 invSizeY_(lookup.invSizeY_),
926 invBinsX_(lookup.invBinsX_),
927 invBinsY_(lookup.invBinsY_),
928 values_(std::move(lookup.values_))
929{
930 lookup.sizeX_ = 0;
931 lookup.sizeY_ = 0;
932 lookup.binsX_ = 0;
933 lookup.binsY_ = 0;
934
935 lookup.invSizeX_ = 0;
936 lookup.invSizeY_ = 0;
937 lookup.invBinsX_ = 0;
938 lookup.invBinsY_ = 0;
939}
940
941template <typename T, typename TScalar>
942inline const T* Lookup2<T, TScalar>::data() const
943{
944 return values_.data();
945}
946
947template <typename T, typename TScalar>
949{
950 return values_.data();
951}
952
953template <typename T, typename TScalar>
954inline size_t Lookup2<T, TScalar>::sizeX() const
955{
956 return sizeX_;
957}
958
959template <typename T, typename TScalar>
960inline size_t Lookup2<T, TScalar>::sizeY() const
961{
962 return sizeY_;
963}
964
965template <typename T, typename TScalar>
966inline size_t Lookup2<T, TScalar>::binsX() const
967{
968 return binsX_;
969}
970
971template <typename T, typename TScalar>
972inline size_t Lookup2<T, TScalar>::binsY() const
973{
974 return binsY_;
975}
976
977template <typename T, typename TScalar>
979{
980 sizeX_ = lookup.sizeX_;
981 sizeY_ = lookup.sizeY_;
982 binsX_ = lookup.binsX_;
983 binsY_ = lookup.binsY_;
984 invSizeX_ = lookup.invSizeX_;
985 invSizeY_ = lookup.invSizeY_;
986 invBinsX_ = lookup.invBinsX_;
987 invBinsY_ = lookup.invBinsY_;
988 values_ = lookup.values_;
989
990 return *this;
991}
992
993template <typename T, typename TScalar>
995{
996 if (this != &lookup)
997 {
998 sizeX_ = lookup.sizeX_;
999 sizeY_ = lookup.sizeY_;
1000 binsX_ = lookup.binsX_;
1001 binsY_ = lookup.binsY_;
1002 invSizeX_ = lookup.invSizeX_;
1003 invSizeY_ = lookup.invSizeY_;
1004 invBinsX_ = lookup.invBinsX_;
1005 invBinsY_ = lookup.invBinsY_;
1006 values_ = std::move(lookup.values_);
1007
1008 lookup.sizeX_ = 0;
1009 lookup.sizeY_ = 0;
1010 lookup.binsX_ = 0;
1011 lookup.binsY_ = 0;
1012 lookup.invSizeX_ = 0;
1013 lookup.invSizeY_ = 0;
1014 lookup.invBinsX_ = 0;
1015 lookup.invBinsY_ = 0;
1016 }
1017
1018 return *this;
1019}
1020
1021template <typename T, typename TScalar>
1023{
1024 return values_.empty();
1025}
1026
1027template <typename T, typename TScalar>
1029{
1030 return !values_.empty();
1031}
1032
1033template <typename T, typename TScalar>
1035{
1036 return sizeX_ == lookup.sizeX_ && sizeY_ == lookup.sizeY_ && binsX_ == lookup.binsX_ && binsY_ == lookup.binsY_ && values_ == lookup.values_;
1037}
1038
1039template <typename T, typename TScalar>
1041{
1042 return !(*this == lookup);
1043}
1044
1045template <typename T, typename TScalar>
1047 Lookup2<T, TScalar>(lookup)
1048{
1049 // nothing to do here
1050}
1051
1052template <typename T, typename TScalar>
1054 Lookup2<T, TScalar>(std::move(lookup))
1055{
1056 // nothing to do here
1057}
1058
1059template <typename T, typename TScalar>
1060LookupCenter2<T, TScalar>::LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY) :
1061 Lookup2<T, TScalar>()
1062{
1063 this->sizeX_ = sizeX;
1064 this->sizeY_ = sizeY;
1065 this->binsX_ = min(binsX, sizeX);
1066 this->binsY_ = min(binsY, sizeY);
1067 this->values_.resize(this->binsX_ * this->binsY_);
1068
1069 ocean_assert(binsX <= sizeX);
1070 ocean_assert(binsY <= sizeY);
1071
1072 ocean_assert(sizeX > 0);
1073 ocean_assert(sizeY > 0);
1074 this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1075 this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1076
1077 ocean_assert(binsX > 0);
1078 ocean_assert(binsY > 0);
1079 this->invBinsX_ = TScalar(1) / TScalar(binsX);
1080 this->invBinsY_ = TScalar(1) / TScalar(binsY);
1081}
1082
1083template <typename T, typename TScalar>
1084LookupCenter2<T, TScalar>::LookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binValues) :
1085 Lookup2<T, TScalar>()
1086{
1087 ocean_assert(binValues);
1088
1089 this->sizeX_ = sizeX;
1090 this->sizeY_ = sizeY;
1091 this->binsX_ = min(binsX, sizeX);
1092 this->binsY_ = min(binsY, sizeY);
1093 this->values_.resize(this->binsX_ * this->binsY_);
1094
1095 ocean_assert(binsX <= sizeX);
1096 ocean_assert(binsY <= sizeY);
1097
1098 ocean_assert(sizeX > 0);
1099 ocean_assert(sizeY > 0);
1100 this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1101 this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1102
1103 ocean_assert(binsX > 0);
1104 ocean_assert(binsY > 0);
1105 this->invBinsX_ = TScalar(1) / TScalar(binsX);
1106 this->invBinsY_ = TScalar(1) / TScalar(binsY);
1107
1108 for (size_t n = 0; n < this->values_.size(); ++n)
1109 {
1110 this->values_[n] = binValues[n];
1111 }
1112}
1113
1114template <typename T, typename TScalar>
1115LookupCenter2<T, TScalar>::LookupCenter2(const size_t sizeX, const size_t sizeY, const LookupCenter2<T, TScalar>& lookup) :
1116 Lookup2<T, TScalar>()
1117{
1118 this->sizeX_ = sizeX;
1119 this->sizeY_ = sizeY;
1120 this->binsX_ = lookup.binsX_;
1121 this->binsY_ = lookup.binsY_;
1122 this->values_ = lookup.values_;
1123
1124 ocean_assert(this->binsX_ <= sizeX);
1125 ocean_assert(this->binsY_ <= sizeY);
1126
1127 ocean_assert(sizeX > 0);
1128 ocean_assert(sizeY > 0);
1129 this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1130 this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1131
1132 ocean_assert(this->binsX_ > 0);
1133 ocean_assert(this->binsY_ > 0);
1134 this->invBinsX_ = TScalar(1) / TScalar(this->binsX_);
1135 this->invBinsY_ = TScalar(1) / TScalar(this->binsY_);
1136}
1137
1138template <typename T, typename TScalar>
1139inline bool LookupCenter2<T, TScalar>::isInside(const TScalar x, const TScalar y) const
1140{
1141 ocean_assert(!this->isEmpty());
1142 return x >= TScalar(0) && y >= TScalar(0) && x <= TScalar(this->sizeX_ - 1) && y <= TScalar(this->sizeY_ - 1);
1143}
1144
1145template <typename T, typename TScalar>
1146inline size_t LookupCenter2<T, TScalar>::binX(const TScalar x) const
1147{
1148 ocean_assert(this->sizeX_ > 0);
1149 ocean_assert(x >= 0 && x <= TScalar(this->sizeX_ - 1));
1150
1151 const size_t result = size_t(x * TScalar(this->binsX_) * this->invSizeX_ + (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps()));
1152 ocean_assert(result < this->binsX_);
1153
1154 return result;
1155}
1156
1157template <typename T, typename TScalar>
1158inline size_t LookupCenter2<T, TScalar>::binY(const TScalar y) const
1159{
1160 ocean_assert(this->sizeY_ > 0);
1161 ocean_assert(y >= 0 && y <= TScalar(this->sizeY_ - 1));
1162
1163 const size_t result = size_t(y * TScalar(this->binsY_) * this->invSizeY_ + (std::is_same<TScalar, float>::value ? TScalar(0.0001) : NumericT<TScalar>::eps()));
1164 ocean_assert(result < this->binsY_);
1165
1166 return result;
1167}
1168
1169template <typename T, typename TScalar>
1170inline size_t LookupCenter2<T, TScalar>::binTopLeftX(const size_t binX) const
1171{
1172 ocean_assert(binX < this->binsX_);
1173
1174 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())));
1175 ocean_assert(binX == this->binX(TScalar(x)));
1176
1177 return x;
1178}
1179
1180template <typename T, typename TScalar>
1181inline size_t LookupCenter2<T, TScalar>::binTopLeftY(const size_t binY) const
1182{
1183 ocean_assert(binY < this->binsY_);
1184
1185 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())));
1186 ocean_assert(binY == this->binY(TScalar(y)));
1187
1188 return y;
1189}
1190
1191template <typename T, typename TScalar>
1192inline size_t LookupCenter2<T, TScalar>::binBottomRightX(const size_t binX) const
1193{
1194 ocean_assert(binX < this->binsX_);
1195
1196 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())));
1197
1198 ocean_assert(x >= 1);
1199 ocean_assert(binX == this->binX(TScalar(x - 1)));
1200
1201 return x - 1;
1202}
1203
1204template <typename T, typename TScalar>
1205inline size_t LookupCenter2<T, TScalar>::binBottomRightY(const size_t binY) const
1206{
1207 ocean_assert(binY < this->binsY_);
1208
1209 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())));
1210
1211 ocean_assert(y >= 1);
1212 ocean_assert(binY == this->binY(TScalar(y - 1)));
1213
1214 return y - 1;
1215}
1216
1217template <typename T, typename TScalar>
1218inline TScalar LookupCenter2<T, TScalar>::binCenterPositionX(const size_t binX) const
1219{
1220 ocean_assert(binX < this->binsX_);
1221
1222 const TScalar result = TScalar(binTopLeftX(binX) + binBottomRightX(binX)) * TScalar(0.5);
1223 ocean_assert(result >= 0 && result < TScalar(this->sizeX_));
1224
1225 return result;
1226}
1227
1228template <typename T, typename TScalar>
1229inline TScalar LookupCenter2<T, TScalar>::binCenterPositionY(const size_t binY) const
1230{
1231 ocean_assert(binY < this->binsY_);
1232
1233 const TScalar result = TScalar(binTopLeftY(binY) + binBottomRightY(binY)) * TScalar(0.5);
1234 ocean_assert(result >= 0 && result < TScalar(this->sizeY_));
1235
1236 return result;
1237}
1238
1239template <typename T, typename TScalar>
1240inline Vector2 LookupCenter2<T, TScalar>::binCenterPosition(const size_t binX, const size_t binY) const
1241{
1242 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1243
1244 return Vector2(binCenterPositionX(binX), binCenterPositionY(binY));
1245}
1246
1247template <typename T, typename TScalar>
1248inline const T& LookupCenter2<T, TScalar>::binCenterValue(const size_t binX, const size_t binY) const
1249{
1250 ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1251 return this->values_[binY * this->binsX_ + binX];
1252}
1253
1254template <typename T, typename TScalar>
1255inline T& LookupCenter2<T, TScalar>::binCenterValue(const size_t binX, const size_t binY)
1256{
1257 ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1258 return this->values_[binY * this->binsX_ + binX];
1259}
1260
1261template <typename T, typename TScalar>
1262T LookupCenter2<T, TScalar>::nearestValue(const TScalar x, const TScalar y) const
1263{
1264 ocean_assert(this->isInside(x, y));
1265
1266 const size_t bx = this->binX(x);
1267 const size_t by = this->binY(y);
1268
1269 return this->values_[by * this->binsX_ + bx];
1270}
1271
1272template <typename T, typename TScalar>
1273T LookupCenter2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y) const
1274{
1275 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1276 ocean_assert(this->isInside(x, y));
1277
1278 const size_t bX = this->binX(x);
1279 const size_t bY = this->binY(y);
1280
1281 const TScalar bCenterX = this->binCenterPositionX(bX);
1282 const TScalar bCenterY = this->binCenterPositionY(bY);
1283
1284 const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1285 const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1286 const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1287 const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1288 ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1289 ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1290
1291 const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1292 const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1293 const TScalar topCenter = this->binCenterPositionY(yLowBin);
1294 const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1295 ocean_assert(leftCenter <= rightCenter);
1296 ocean_assert(topCenter <= bottomCenter);
1297
1298 ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1299 ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1300
1301 const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1302 const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1303
1304 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1305 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1306
1307 const TScalar factorTopLeft = (TScalar(1) - xFactor) * (TScalar(1) - yFactor);
1308 const TScalar factorTopRight = xFactor * (TScalar(1) - yFactor);
1309 const TScalar factorBottomLeft = (TScalar(1) - xFactor) * yFactor;
1310 const TScalar factorBottomRight = xFactor * yFactor;
1311
1312 const T& topLeft = binCenterValue(xLowBin, yLowBin);
1313 const T& topRight = binCenterValue(xHighBin, yLowBin);
1314 const T& bottomLeft = binCenterValue(xLowBin, yHighBin);
1315 const T& bottomRight = binCenterValue(xHighBin, yHighBin);
1316
1317 return topLeft * factorTopLeft + topRight * factorTopRight
1318 + bottomLeft * factorBottomLeft + bottomRight * factorBottomRight;
1319}
1320
1321template <typename T, typename TScalar>
1322T LookupCenter2<T, TScalar>::bicubicValue(const TScalar x, const TScalar y) const
1323{
1324 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1325 ocean_assert(this->isInside(x, y));
1326
1327 const size_t bX = this->binX(x);
1328 const size_t bY = this->binY(y);
1329
1330 const TScalar bCenterX = this->binCenterPositionX(bX);
1331 const TScalar bCenterY = this->binCenterPositionY(bY);
1332
1333 const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1334 const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1335 const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1336 const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1337 ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1338 ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1339
1340 // determine the supporting positions
1341 const size_t xMinusBin = max(0, int(xLowBin) - 1);
1342 const size_t xPlusBin = min(xHighBin + 1, this->binsX_ - 1);
1343 const size_t yMinusBin = max(0, int(yLowBin) - 1);
1344 const size_t yPlusBin = min(yHighBin + 1, this->binsY_ - 1);
1345
1346 const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1347 const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1348 const TScalar topCenter = this->binCenterPositionY(yLowBin);
1349 const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1350 ocean_assert(leftCenter <= rightCenter);
1351 ocean_assert(topCenter <= bottomCenter);
1352
1353 ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1354 ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1355
1356 const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1357 const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1358
1359 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1360 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1361
1362 return Interpolation::cubic(Interpolation::cubic(binCenterValue(xMinusBin, yMinusBin), binCenterValue(xLowBin, yMinusBin), binCenterValue(xHighBin, yMinusBin), binCenterValue(xPlusBin, yMinusBin), xFactor),
1363 Interpolation::cubic(binCenterValue(xMinusBin, yLowBin), binCenterValue(xLowBin, yLowBin), binCenterValue(xHighBin, yLowBin), binCenterValue(xPlusBin, yLowBin), xFactor),
1364 Interpolation::cubic(binCenterValue(xMinusBin, yHighBin), binCenterValue(xLowBin, yHighBin), binCenterValue(xHighBin, yHighBin), binCenterValue(xPlusBin, yHighBin), xFactor),
1365 Interpolation::cubic(binCenterValue(xMinusBin, yPlusBin), binCenterValue(xLowBin, yPlusBin), binCenterValue(xHighBin, yPlusBin), binCenterValue(xPlusBin, yPlusBin), xFactor), yFactor);
1366}
1367
1368template <typename T, typename TScalar>
1369T LookupCenter2<T, TScalar>::clampedNearestValue(const TScalar x, const TScalar y) const
1370{
1371 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1372
1373 return nearestValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)));
1374}
1375
1376template <typename T, typename TScalar>
1377T LookupCenter2<T, TScalar>::clampedBilinearValue(const TScalar x, const TScalar y) const
1378{
1379 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1380
1381 return bilinearValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)));
1382}
1383
1384template <typename T, typename TScalar>
1385T LookupCenter2<T, TScalar>::clampedBicubicValue(const TScalar x, const TScalar y) const
1386{
1387 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1388
1389 return bicubicValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)));
1390}
1391
1392template <typename T, typename TScalar>
1393inline void LookupCenter2<T, TScalar>::setBinCenterValue(const size_t binX, const size_t binY, const T& value)
1394{
1395 ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1396 this->values_[binY * this->binsX_ + binX] = value;
1397}
1398
1399template <typename T, typename TScalar>
1405
1406template <typename T, typename TScalar>
1408 LookupCenter2<T, TScalar>(lookup),
1409 validBins_(lookup.validBins_)
1410{
1411 // nothing to do here
1412}
1413
1414template <typename T, typename TScalar>
1417 validBins_(std::move(lookup.validBins_))
1418{
1419 // nothing to do here
1420}
1421
1422template <typename T, typename TScalar>
1423AdvancedLookupCenter2<T, TScalar>::AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY) :
1424 LookupCenter2<T, TScalar>(sizeX, sizeY, binsX, binsY),
1425 validBins_(binsX * binsY, 1u)
1426{
1427 // nothing to do here
1428}
1429
1430template <typename T, typename TScalar>
1431AdvancedLookupCenter2<T, TScalar>::AdvancedLookupCenter2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const bool binsValid) :
1432 LookupCenter2<T, TScalar>(sizeX, sizeY, binsX, binsY),
1433 validBins_(binsX * binsY, binsValid ? 1u : 0u)
1434{
1435 // nothing to do here
1436}
1437
1438template <typename T, typename TScalar>
1439AdvancedLookupCenter2<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) :
1440 LookupCenter2<T, TScalar>(sizeX, sizeY, binsX, binsY, binValues),
1441 validBins_(binsX * binsY)
1442{
1443 memcpy(validBins_.data(), validBins, binsX * binsY * sizeof(unsigned char));
1444}
1445
1446template <typename T, typename TScalar>
1448 LookupCenter2<T, TScalar>(sizeX, sizeY, lookup),
1449 validBins_(lookup.validBins_)
1450{
1451 // nothing to do here
1452}
1453
1454template <typename T, typename TScalar>
1455inline bool AdvancedLookupCenter2<T, TScalar>::binCenterValid(const size_t binX, const size_t binY) const
1456{
1457 ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1458 return validBins_[binY * this->binsX_ + binX] != 0u;
1459}
1460
1461template <typename T, typename TScalar>
1462bool AdvancedLookupCenter2<T, TScalar>::nearestValue(const TScalar x, const TScalar y, T& value) const
1463{
1464 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1465 ocean_assert(this->values_.size() == validBins_.size());
1466 ocean_assert(this->isInside(x, y));
1467
1468 const size_t bx = this->binX(x);
1469 const size_t by = this->binY(y);
1470
1471 if (validBins_[by * this->binsX_ + bx] == 0u)
1472 {
1473 return false;
1474 }
1475
1476 value = this->values_[by * this->binsX_ + bx];
1477 return true;
1478}
1479
1480template <typename T, typename TScalar>
1481bool AdvancedLookupCenter2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y, T& value) const
1482{
1483 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1484 ocean_assert(this->values_.size() == validBins_.size());
1485 ocean_assert(this->isInside(x, y));
1486
1487 const size_t bX = this->binX(x);
1488 const size_t bY = this->binY(y);
1489
1490 const TScalar bCenterX = this->binCenterPositionX(bX);
1491 const TScalar bCenterY = this->binCenterPositionY(bY);
1492
1493 const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1494 const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1495 const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1496 const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1497 ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1498 ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1499
1500 const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1501 const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1502 const TScalar topCenter = this->binCenterPositionY(yLowBin);
1503 const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1504 ocean_assert(leftCenter <= rightCenter);
1505 ocean_assert(topCenter <= bottomCenter);
1506
1507 ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1508 ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1509
1510 const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1511 const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1512
1513 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1514 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1515
1516 const T& topLeft = this->binCenterValue(xLowBin, yLowBin);
1517 const T& topRight = this->binCenterValue(xHighBin, yLowBin);
1518 const T& bottomLeft = this->binCenterValue(xLowBin, yHighBin);
1519 const T& bottomRight = this->binCenterValue(xHighBin, yHighBin);
1520
1521 const bool validTopLeft = validBins_[yLowBin * this->binsX_ + xLowBin] != 0u;
1522 const bool validTopRight = validBins_[yLowBin * this->binsX_ + xHighBin] != 0u;
1523 const bool validBottomLeft = validBins_[yHighBin * this->binsX_ + xLowBin] != 0u;
1524 const bool validBottomRight = validBins_[yHighBin * this->binsX_ + xHighBin] != 0u;
1525
1526 if (validTopLeft || validTopRight || validBottomLeft || validBottomRight)
1527 {
1528 value = Interpolation::bilinear(topLeft, topRight, bottomLeft, bottomRight, validTopLeft, validTopRight, validBottomLeft, validBottomRight, xFactor, yFactor);
1529 return true;
1530 }
1531
1532 return false;
1533}
1534
1535template <typename T, typename TScalar>
1536bool AdvancedLookupCenter2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y, const unsigned int minimalValidBins, T& value) const
1537{
1538 ocean_assert(minimalValidBins >= 1u && minimalValidBins <= 4u);
1539 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1540 ocean_assert(this->values_.size() == validBins_.size());
1541 ocean_assert(this->isInside(x, y));
1542
1543 const size_t bX = this->binX(x);
1544 const size_t bY = this->binY(y);
1545
1546 const TScalar bCenterX = this->binCenterPositionX(bX);
1547 const TScalar bCenterY = this->binCenterPositionY(bY);
1548
1549 const size_t xLowBin = (x >= bCenterX) ? bX : max(0, int(bX) - 1);
1550 const size_t xHighBin = (x < bCenterX) ? bX : min(xLowBin + 1, this->binsX_ - 1);
1551 const size_t yLowBin = (y >= bCenterY) ? bY : max(0, int(bY) - 1);
1552 const size_t yHighBin = (y < bCenterY) ? bY : min(yLowBin + 1, this->binsY_ - 1);
1553 ocean_assert(((xLowBin == 0 || xLowBin == this->binsX_ - 1) && xHighBin == xLowBin) || xLowBin + 1 == xHighBin);
1554 ocean_assert(((yLowBin == 0 || yLowBin == this->binsY_ - 1) && yHighBin == yLowBin) || yLowBin + 1 == yHighBin);
1555
1556 const TScalar leftCenter = this->binCenterPositionX(xLowBin);
1557 const TScalar rightCenter = this->binCenterPositionX(xHighBin);
1558 const TScalar topCenter = this->binCenterPositionY(yLowBin);
1559 const TScalar bottomCenter = this->binCenterPositionY(yHighBin);
1560 ocean_assert(leftCenter <= rightCenter);
1561 ocean_assert(topCenter <= bottomCenter);
1562
1563 ocean_assert(xLowBin == xHighBin || (leftCenter <= x && NumericT<TScalar>::isNotEqual(leftCenter, rightCenter)));
1564 ocean_assert(yLowBin == yHighBin || (topCenter <= y && NumericT<TScalar>::isNotEqual(topCenter, bottomCenter)));
1565
1566 const TScalar xFactor = xLowBin != xHighBin ? (x - leftCenter) / (rightCenter - leftCenter) : TScalar(1);
1567 const TScalar yFactor = yLowBin != yHighBin ? (y - topCenter) / (bottomCenter - topCenter) : TScalar(1);
1568
1569 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1570 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1571
1572 const T& topLeft = this->binCenterValue(xLowBin, yLowBin);
1573 const T& topRight = this->binCenterValue(xHighBin, yLowBin);
1574 const T& bottomLeft = this->binCenterValue(xLowBin, yHighBin);
1575 const T& bottomRight = this->binCenterValue(xHighBin, yHighBin);
1576
1577 const bool validTopLeft = validBins_[yLowBin * this->binsX_ + xLowBin] != 0u;
1578 const bool validTopRight = validBins_[yLowBin * this->binsX_ + xHighBin] != 0u;
1579 const bool validBottomLeft = validBins_[yHighBin * this->binsX_ + xLowBin] != 0u;
1580 const bool validBottomRight = validBins_[yHighBin * this->binsX_ + xHighBin] != 0u;
1581
1582 ocean_assert(validTopLeft == 0 || validTopLeft == 1);
1583 ocean_assert(validTopRight == 0 || validTopRight == 1);
1584 ocean_assert(validBottomLeft == 0 || validBottomLeft == 1);
1585 ocean_assert(validBottomRight == 0 || validBottomRight == 1);
1586
1587 if ((unsigned int)(validTopLeft + validTopRight + validBottomLeft + validBottomRight) >= minimalValidBins)
1588 {
1589 value = Interpolation::bilinear(topLeft, topRight, bottomLeft, bottomRight, validTopLeft, validTopRight, validBottomLeft, validBottomRight, xFactor, yFactor);
1590 return true;
1591 }
1592
1593 return false;
1594}
1595
1596template <typename T, typename TScalar>
1597bool AdvancedLookupCenter2<T, TScalar>::clampedNearestValue(const TScalar x, const TScalar y, T& value) const
1598{
1599 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1600
1601 return nearestValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)), value);
1602}
1603
1604template <typename T, typename TScalar>
1605bool AdvancedLookupCenter2<T, TScalar>::clampedBilinearValue(const TScalar x, const TScalar y, T& value) const
1606{
1607 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1608
1609 return bilinearValue(minmax<TScalar>(0, x, TScalar(this->sizeX_ - 1)), minmax<TScalar>(0, y, TScalar(this->sizeY_ - 1)), value);
1610}
1611
1612template <typename T, typename TScalar>
1613inline void AdvancedLookupCenter2<T, TScalar>::setBinCenterValue(const size_t binX, const size_t binY, const T& value, const bool isValid)
1614{
1615 ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1616
1617 this->values_[binY * this->binsX_ + binX] = value;
1618 validBins_[binY * this->binsX_ + binX] = isValid ? 1u : 0u;
1619}
1620
1621template <typename T, typename TScalar>
1622inline void AdvancedLookupCenter2<T, TScalar>::setBinCenterValid(const size_t binX, const size_t binY, const bool isValid)
1623{
1624 ocean_assert(binX < this->binsX_ && binY < this->binsY_);
1625 validBins_[binY * this->binsX_ + binX] = isValid ? 1u: 0u;
1626}
1627
1628template <typename T, typename TScalar>
1630{
1631 if (this != &lookup)
1632 {
1633 LookupCenter2<T, TScalar>::operator=(std::move(lookup));
1634 validBins_ = std::move(lookup.validBins_);
1635 }
1636
1637 return *this;
1638}
1639
1640template <typename T, typename TScalar>
1642{
1643 return validBins_ == lookup.validBins_ && (LookupCenter2<T, TScalar>&)*this == (LookupCenter2<T, TScalar>&)lookup;
1644}
1645
1646template <typename T, typename TScalar>
1648{
1649 return !(*this == lookup);
1650}
1651
1652template <typename T, typename TScalar>
1654 Lookup2<T, TScalar>(std::move(lookup))
1655{
1656 // nothing to do here
1657}
1658
1659template <typename T, typename TScalar>
1661 Lookup2<T, TScalar>(std::move(lookup))
1662{
1663 // nothing to do here
1664}
1665
1666template <typename T, typename TScalar>
1667LookupCorner2<T, TScalar>::LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY) :
1668 Lookup2<T, TScalar>()
1669{
1670 this->sizeX_ = sizeX;
1671 this->sizeY_ = sizeY;
1672 this->binsX_ = min(binsX, sizeX);
1673 this->binsY_ = min(binsY, sizeY);
1674 this->values_.resize((this->binsX_ + 1) * (this->binsY_ + 1));
1675
1676 ocean_assert(binsX <= sizeX);
1677 ocean_assert(binsY <= sizeY);
1678
1679 ocean_assert(sizeX >= 1);
1680 ocean_assert(sizeY >= 1);
1681 this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1682 this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1683
1684 ocean_assert(binsX > 0);
1685 ocean_assert(binsY > 0);
1686 this->invBinsX_ = TScalar(1) / TScalar(binsX);
1687 this->invBinsY_ = TScalar(1) / TScalar(binsY);
1688}
1689
1690template <typename T, typename TScalar>
1691LookupCorner2<T, TScalar>::LookupCorner2(const size_t sizeX, const size_t sizeY, const size_t binsX, const size_t binsY, const T* binCornerValues) :
1692 Lookup2<T, TScalar>()
1693{
1694 ocean_assert(binCornerValues);
1695
1696 this->sizeX_ = sizeX;
1697 this->sizeY_ = sizeY;
1698 this->binsX_ = min(binsX, sizeX);
1699 this->binsY_ = min(binsY, sizeY);
1700 this->values_.resize((this->binsX_ + 1) * (this->binsY_ + 1));
1701
1702 ocean_assert(binsX <= sizeX);
1703 ocean_assert(binsY <= sizeY);
1704
1705 ocean_assert(sizeX > 1);
1706 ocean_assert(sizeY > 1);
1707 this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1708 this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1709
1710 ocean_assert(binsX > 0);
1711 ocean_assert(binsY > 0);
1712 this->invBinsX_ = TScalar(1) / TScalar(binsX);
1713 this->invBinsY_ = TScalar(1) / TScalar(binsY);
1714
1715 for (size_t n = 0; n < this->values_.size(); ++n)
1716 {
1717 this->values_[n] = binCornerValues[n];
1718 }
1719}
1720
1721template <typename T, typename TScalar>
1722LookupCorner2<T, TScalar>::LookupCorner2(const size_t sizeX, const size_t sizeY, const LookupCorner2<T, TScalar>& lookup) :
1723 Lookup2<T, TScalar>()
1724{
1725 this->sizeX_ = sizeX;
1726 this->sizeY_ = sizeY;
1727 this->binsX_ = lookup.binsX_;
1728 this->binsY_ = lookup.binsY_;
1729 this->values_ = lookup.values_;
1730
1731 ocean_assert(this->binsX_ <= sizeX);
1732 ocean_assert(this->binsY_ <= sizeY);
1733
1734 ocean_assert(sizeX > 1);
1735 ocean_assert(sizeY > 1);
1736 this->invSizeX_ = TScalar(1) / TScalar(sizeX);
1737 this->invSizeY_ = TScalar(1) / TScalar(sizeY);
1738
1739 ocean_assert(this->binsX_ > 0);
1740 ocean_assert(this->binsY_ > 0);
1741 this->invBinsX_ = TScalar(1) / TScalar(this->binsX_);
1742 this->invBinsY_ = TScalar(1) / TScalar(this->binsY_);
1743}
1744
1745template <typename T, typename TScalar>
1746inline bool LookupCorner2<T, TScalar>::isInside(const TScalar x, const TScalar y) const
1747{
1748 ocean_assert(!this->isEmpty());
1749 return x >= TScalar(0) && y >= TScalar(0) && x <= TScalar(this->sizeX_) && y <= TScalar(this->sizeY_);
1750}
1751
1752template <typename T, typename TScalar>
1753inline size_t LookupCorner2<T, TScalar>::binX(const TScalar x) const
1754{
1755 ocean_assert(this->sizeX_ > 0);
1756 ocean_assert(x >= 0 && x <= TScalar(this->sizeX_));
1757
1758 const size_t result = size_t(x * TScalar(this->binsX_) * this->invSizeX_);
1759 ocean_assert(result <= this->binsX_);
1760
1761 return result;
1762}
1763
1764template <typename T, typename TScalar>
1765inline size_t LookupCorner2<T, TScalar>::binY(const TScalar y) const
1766{
1767 ocean_assert(this->sizeY_ > 0);
1768 ocean_assert(y >= 0 && y <= TScalar(this->sizeY_));
1769
1770 const size_t result = size_t(y * TScalar(this->binsY_) * this->invSizeY_);
1771 ocean_assert(result <= this->binsY_);
1772
1773 return result;
1774}
1775
1776template <typename T, typename TScalar>
1777inline TScalar LookupCorner2<T, TScalar>::binTopLeftCornerPositionX(const size_t binX) const
1778{
1779 ocean_assert(binX <= this->binsX_ && this->sizeX_ >= 1);
1780
1781 const TScalar result = TScalar(binX * this->sizeX_) * this->invBinsX_;
1782
1783 // the clamping is necessary due to tiny rounding issues
1784 return minmax<TScalar>(0, result, TScalar(this->sizeX_));
1785}
1786
1787template <typename T, typename TScalar>
1788inline TScalar LookupCorner2<T, TScalar>::binTopLeftCornerPositionY(const size_t binY) const
1789{
1790 ocean_assert(binY <= this->binsY_ && this->sizeY_ >= 1);
1791
1792 const TScalar result = TScalar(binY * this->sizeY_) * this->invBinsY_;
1793
1794 // the clamping is necessary due to tiny rounding issues
1795 return minmax<TScalar>(0, result, TScalar(this->sizeY_));
1796}
1797
1798template <typename T, typename TScalar>
1799inline Vector2 LookupCorner2<T, TScalar>::binTopLeftCornerPosition(const size_t binX, const size_t binY) const
1800{
1801 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1802
1803 return Vector2(binTopLeftCornerPositionX(binX), binTopLeftCornerPositionY(binY));
1804}
1805
1806template <typename T, typename TScalar>
1807inline const T& LookupCorner2<T, TScalar>::binTopLeftCornerValue(const size_t binX, const size_t binY) const
1808{
1809 ocean_assert(binX <= this->binsX_ && binY <= this->binsY_);
1810 return this->values_[binY * (this->binsX_ + 1) + binX];
1811}
1812
1813template <typename T, typename TScalar>
1814T LookupCorner2<T, TScalar>::nearestValue(const TScalar x, const TScalar y) const
1815{
1816 ocean_assert(this->isInside(x, y));
1817
1818 const size_t bx = size_t(x * TScalar(this->binsX_) * this->invSizeX_ + TScalar(0.5));
1819 ocean_assert(bx <= this->binsX_);
1820
1821 const size_t by = size_t(y * TScalar(this->binsY_) * this->invSizeY_ + TScalar(0.5));
1822 ocean_assert(by <= this->binsY_);
1823
1824 return this->values_[by * (this->binsX_ + 1) + bx];
1825}
1826
1827template <typename T, typename TScalar>
1828T LookupCorner2<T, TScalar>::bilinearValue(const TScalar x, const TScalar y) const
1829{
1830 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1831 ocean_assert(this->isInside(x, y));
1832
1833 const size_t xLowBin = this->binX(x);
1834 const size_t yLowBin = this->binY(y);
1835
1836 ocean_assert(xLowBin <= this->binsX_);
1837 ocean_assert(yLowBin <= this->binsY_);
1838
1839 const TScalar leftPosition = this->binTopLeftCornerPositionX(xLowBin);
1840 const TScalar topPosition = this->binTopLeftCornerPositionY(yLowBin);
1841
1842 const TScalar xFactor = (x - leftPosition) * TScalar(this->binsX_) * this->invSizeX_;
1843 const TScalar yFactor = (y - topPosition) * TScalar(this->binsY_) * this->invSizeY_;
1844
1845#ifdef OCEAN_DEBUG
1846 if (std::is_same<TScalar, float>::value)
1847 {
1848 ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, xFactor, 1));
1849 ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, yFactor, 1));
1850 }
1851 else
1852 {
1853 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
1854 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
1855 }
1856#endif
1857
1858 const TScalar factorTopLeft = (TScalar(1) - xFactor) * (TScalar(1) - yFactor);
1859 const TScalar factorTopRight = xFactor * (TScalar(1) - yFactor);
1860 const TScalar factorBottomLeft = (TScalar(1) - xFactor) * yFactor;
1861 const TScalar factorBottomRight = xFactor * yFactor;
1862
1863 const size_t xHighBin = min(xLowBin + 1, this->binsX_);
1864 const size_t yHighBin = min(yLowBin + 1, this->binsY_);
1865
1866 const T& topLeft = this->binTopLeftCornerValue(xLowBin, yLowBin);
1867 const T& topRight = this->binTopLeftCornerValue(xHighBin, yLowBin);
1868 const T& bottomLeft = this->binTopLeftCornerValue(xLowBin, yHighBin);
1869 const T& bottomRight = this->binTopLeftCornerValue(xHighBin, yHighBin);
1870
1871 return topLeft * factorTopLeft + topRight * factorTopRight
1872 + bottomLeft * factorBottomLeft + bottomRight * factorBottomRight;
1873}
1874
1875template <typename T, typename TScalar>
1876template <typename TTarget>
1877void LookupCorner2<T, TScalar>::bilinearValues(const size_t y, TTarget* values) const
1878{
1879 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1880 ocean_assert(this->binsX_ <= this->sizeX_ && this->binsY_ <= this->sizeY_);
1881
1882 ocean_assert(y < this->sizeY_);
1883 ocean_assert(values != nullptr);
1884
1885 const size_t yLowBin = (y * this->binsY_) / this->sizeY_;
1886 ocean_assert(yLowBin < this->binsY_);
1887 ocean_assert(std::abs(int(yLowBin) - int(this->binY(TScalar(y)))) <= 1);
1888
1889 const size_t yHighBin = yLowBin + 1;
1890 ocean_assert(yHighBin <= this->binsY_);
1891
1892 const TScalar yLowBinPosition = this->binTopLeftCornerPositionY(yLowBin);
1893 const TScalar yHighBinPosition = this->binTopLeftCornerPositionY(yHighBin);
1894 ocean_assert(yLowBinPosition < yHighBinPosition);
1895
1896 const TScalar yFactor = (TScalar(y) - yLowBinPosition) / (yHighBinPosition - yLowBinPosition);
1897 ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), yFactor, TScalar(1)));
1898
1899 const Vector2* lowBinValues = this->values_.data() + (yLowBin * (this->binsX_ + 1));
1900 const Vector2* highBinValues = this->values_.data() + (yHighBin * (this->binsX_ + 1));
1901
1902 Vector2 leftBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1903 Vector2 rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1904
1905 unsigned int nextBinX = 1u;
1906
1907 TScalar leftBinPositionX = TScalar(0);
1908 TScalar rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1909
1910 ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1911 TScalar invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1912
1913 for (size_t x = 0; x < this->sizeX_; ++x)
1914 {
1915 if (TScalar(x) > rightBinPositionX)
1916 {
1917 leftBinValue = rightBinValue;
1918 rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1919
1920 leftBinPositionX = rightBinPositionX;
1921 rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1922
1923 ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1924 invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1925 }
1926
1927 ocean_assert(leftBinPositionX <= TScalar(x));
1928
1929 const TScalar xFactor = (TScalar(x) - leftBinPositionX) * invBinWidthX;
1930
1931 if constexpr (std::is_same<TScalar, float>::value)
1932 {
1933 ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), xFactor, TScalar(1)));
1934 }
1935 else
1936 {
1937 ocean_assert(NumericT<TScalar>::isInsideRange(TScalar(0), xFactor, TScalar(1)));
1938 }
1939
1940 values[x] = TTarget(leftBinValue * (TScalar(1) - xFactor) + rightBinValue * xFactor);
1941
1942#ifdef OCEAN_DEBUG
1943 const T debugTestValue = this->bilinearValue(TScalar(x), TScalar(y));
1944 const TScalar debugError = debugTestValue.distance(T(values[x]));
1945 ocean_assert(debugError < TScalar(0.1));
1946#endif
1947 }
1948}
1949
1950template <typename T, typename TScalar>
1951template <typename TTarget>
1952void LookupCorner2<T, TScalar>::bilinearValues(const size_t x, const size_t y, const size_t size, TTarget* values) const
1953{
1954 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
1955 ocean_assert(this->binsX_ <= this->sizeX_ && this->binsY_ <= this->sizeY_);
1956
1957 ocean_assert(x + size <= this->sizeX_);
1958
1959 ocean_assert(y < this->sizeY_);
1960 ocean_assert(values != nullptr);
1961
1962 ocean_assert(size >= 1);
1963
1964 const size_t xLowBin = (x * this->binsX_) / this->sizeX_;
1965 ocean_assert(xLowBin < this->binsX_);
1966 ocean_assert(std::abs(int(xLowBin) - int(this->binX(TScalar(x)))) <= 1);
1967
1968 const size_t yLowBin = (y * this->binsY_) / this->sizeY_;
1969 ocean_assert(yLowBin < this->binsY_);
1970 ocean_assert(std::abs(int(yLowBin) - int(this->binY(TScalar(y)))) <= 1);
1971
1972 const size_t yHighBin = yLowBin + 1;
1973 ocean_assert(yHighBin <= this->binsY_);
1974
1975 const TScalar yLowBinPosition = this->binTopLeftCornerPositionY(yLowBin);
1976 const TScalar yHighBinPosition = this->binTopLeftCornerPositionY(yHighBin);
1977 ocean_assert(yLowBinPosition < yHighBinPosition);
1978
1979 const TScalar yFactor = (TScalar(y) - yLowBinPosition) / (yHighBinPosition - yLowBinPosition);
1980 ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), yFactor, TScalar(1)));
1981
1982 const Vector2* lowBinValues = this->values_.data() + (yLowBin * (this->binsX_ + 1)) + xLowBin;
1983 const Vector2* highBinValues = this->values_.data() + (yHighBin * (this->binsX_ + 1)) + xLowBin;
1984
1985 Vector2 leftBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1986 Vector2 rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
1987
1988 size_t nextBinX = xLowBin + 1u;
1989
1990 TScalar leftBinPositionX = TScalar(xLowBin * this->sizeX_) * this->invBinsX_;
1991 TScalar rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
1992
1993 ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
1994 TScalar invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
1995
1996 for (size_t nX = x; nX < x + size; ++nX)
1997 {
1998 if (TScalar(nX) > rightBinPositionX)
1999 {
2000 leftBinValue = rightBinValue;
2001 rightBinValue = *lowBinValues++ * (TScalar(1) - yFactor) + *highBinValues++ * yFactor;
2002
2003 leftBinPositionX = rightBinPositionX;
2004 rightBinPositionX = TScalar(nextBinX++ * this->sizeX_) * this->invBinsX_;
2005
2006 ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
2007 invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
2008 }
2009
2010 ocean_assert(leftBinPositionX <= TScalar(nX) + NumericT<TScalar>::weakEps());
2011
2012 const TScalar xFactor = (TScalar(nX) - leftBinPositionX) * invBinWidthX;
2013 ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), xFactor, TScalar(1)));
2014
2015 *values++ = TTarget(leftBinValue * (TScalar(1) - xFactor) + rightBinValue * xFactor);
2016
2017#ifdef OCEAN_DEBUG
2018 const T debugTestValue = this->bilinearValue(TScalar(nX), TScalar(y));
2019 const TScalar debugError = debugTestValue.distance(T(TTarget(leftBinValue * (TScalar(1) - xFactor) + rightBinValue * xFactor)));
2020 ocean_assert(debugError < TScalar(0.1));
2021#endif
2022 }
2023}
2024
2025template <typename T, typename TScalar>
2026template <typename TTarget>
2027void LookupCorner2<T, TScalar>::bilinearValues(const size_t y, TTarget* values, const bool isOptimized) const
2028{
2029 if (!isOptimized)
2030 {
2031 bilinearValues(y, values);
2032 return;
2033 }
2034
2035 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2036 ocean_assert(this->binsX_ <= this->sizeX_ && this->binsY_ <= this->sizeY_);
2037 ocean_assert(y < this->sizeY_);
2038 ocean_assert(values != nullptr);
2039
2040 const size_t yLowBin = (y * this->binsY_) / this->sizeY_;
2041 ocean_assert(yLowBin < this->binsY_);
2042
2043 const size_t yHighBin = yLowBin + 1;
2044 ocean_assert(yHighBin <= this->binsY_);
2045
2046 const TScalar yLowBinPosition = this->binTopLeftCornerPositionY(yLowBin);
2047 const TScalar yHighBinPosition = this->binTopLeftCornerPositionY(yHighBin);
2048 ocean_assert(yLowBinPosition < yHighBinPosition);
2049
2050 const TScalar yFactor = (TScalar(y) - yLowBinPosition) / (yHighBinPosition - yLowBinPosition);
2051 ocean_assert(NumericT<TScalar>::isInsideWeakRange(TScalar(0), yFactor, TScalar(1)));
2052
2053 const Vector2* lowBinValues = this->values_.data() + (yLowBin * (this->binsX_ + 1));
2054 const Vector2* highBinValues = this->values_.data() + (yHighBin * (this->binsX_ + 1));
2055
2056 // Bin-based outer loop with additive accumulation
2057 size_t xStart = 0;
2058
2059 for (size_t bin = 0; bin < this->binsX_; ++bin)
2060 {
2061 const Vector2 leftBinValue = lowBinValues[bin] * (TScalar(1) - yFactor) + highBinValues[bin] * yFactor;
2062 const Vector2 rightBinValue = lowBinValues[bin + 1] * (TScalar(1) - yFactor) + highBinValues[bin + 1] * yFactor;
2063
2064 const TScalar leftBinPositionX = TScalar(bin * this->sizeX_) * this->invBinsX_;
2065 const TScalar rightBinPositionX = TScalar((bin + 1) * this->sizeX_) * this->invBinsX_;
2066
2067 ocean_assert(rightBinPositionX - leftBinPositionX > NumericT<TScalar>::eps());
2068 const TScalar invBinWidthX = TScalar(1) / (rightBinPositionX - leftBinPositionX);
2069
2070 const Vector2 delta = (rightBinValue - leftBinValue) * invBinWidthX;
2071
2072 // Compute xEnd: the original loop transitions when TScalar(x) > rightBinPositionX,
2073 // so pixels up to and including floor(rightBinPositionX) belong to this bin
2074 const size_t xEnd = (bin + 1 < this->binsX_)
2075 ? std::min(static_cast<size_t>(rightBinPositionX) + 1, this->sizeX_)
2076 : this->sizeX_;
2077
2078 // Derive exact starting value from lerp to avoid accumulated drift
2079 const TScalar xStartFactor = (TScalar(xStart) - leftBinPositionX) * invBinWidthX;
2080 const Vector2 startValue = leftBinValue + (rightBinValue - leftBinValue) * xStartFactor;
2081
2082 TScalar currentX = startValue.x();
2083 TScalar currentY = startValue.y();
2084 const TScalar deltaX = delta.x();
2085 const TScalar deltaY = delta.y();
2086
2087 for (size_t x = xStart; x < xEnd; ++x)
2088 {
2089 values[x] = TTarget(currentX, currentY);
2090 currentX += deltaX;
2091 currentY += deltaY;
2092 }
2093
2094 xStart = xEnd;
2095 }
2096
2097}
2098
2099template <typename T, typename TScalar>
2100void 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
2101{
2102 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2103 ocean_assert(this->isInside(x, y));
2104
2105 const size_t xLowBin = this->binX(x);
2106 const size_t yLowBin = this->binY(y);
2107
2108 ocean_assert(xLowBin <= this->binsX_);
2109 ocean_assert(yLowBin <= this->binsY_);
2110
2111 const TScalar leftPosition = this->binTopLeftCornerPositionX(xLowBin);
2112 const TScalar topPosition = this->binTopLeftCornerPositionY(yLowBin);
2113
2114 const TScalar xFactor = (x - leftPosition) * TScalar(this->binsX_) * this->invSizeX_;
2115 const TScalar yFactor = (y - topPosition) * TScalar(this->binsY_) * this->invSizeY_;
2116
2117#ifdef OCEAN_DEBUG
2118 if (std::is_same<TScalar, float>::value)
2119 {
2120 ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, xFactor, 1));
2121 ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, yFactor, 1));
2122 }
2123 else
2124 {
2125 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
2126 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
2127 }
2128#endif
2129
2130 factorTopLeft = (TScalar(1) - xFactor) * (TScalar(1) - yFactor);
2131 factorTopRight = xFactor * (TScalar(1) - yFactor);
2132 factorBottomLeft = (TScalar(1) - xFactor) * yFactor;
2133 factorBottomRight = xFactor * yFactor;
2134
2135 const size_t xHighBin = min(xLowBin + 1, this->binsX_);
2136 const size_t yHighBin = min(yLowBin + 1, this->binsY_);
2137
2138 topLeft = this->binTopLeftCornerValue(xLowBin, yLowBin);
2139 topRight = this->binTopLeftCornerValue(xHighBin, yLowBin);
2140 bottomLeft = this->binTopLeftCornerValue(xLowBin, yHighBin);
2141 bottomRight = this->binTopLeftCornerValue(xHighBin, yHighBin);
2142}
2143
2144template <typename T, typename TScalar>
2145T LookupCorner2<T, TScalar>::bicubicValue(const TScalar x, const TScalar y) const
2146{
2147 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2148 ocean_assert(this->isInside(x, y));
2149
2150 const size_t xLowBin = this->binX(x);
2151 const size_t yLowBin = this->binY(y);
2152
2153 ocean_assert(xLowBin <= this->binsX_);
2154 ocean_assert(yLowBin <= this->binsY_);
2155
2156 const TScalar leftPosition = this->binTopLeftCornerPositionX(xLowBin);
2157 const TScalar topPosition = this->binTopLeftCornerPositionY(yLowBin);
2158
2159 const TScalar xFactor = (x - leftPosition) * TScalar(this->binsX_) * this->invSizeX_;
2160 const TScalar yFactor = (y - topPosition) * TScalar(this->binsY_) * this->invSizeY_;
2161
2162#ifdef OCEAN_DEBUG
2163 if (std::is_same<TScalar, float>::value)
2164 {
2165 ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, xFactor, 1));
2166 ocean_assert(NumericT<TScalar>::isInsideWeakRange(0, yFactor, 1));
2167 }
2168 else
2169 {
2170 ocean_assert(NumericT<TScalar>::isInsideRange(0, xFactor, 1));
2171 ocean_assert(NumericT<TScalar>::isInsideRange(0, yFactor, 1));
2172 }
2173#endif
2174
2175 const size_t xHighBin = min(xLowBin + 1, this->binsX_);
2176 const size_t yHighBin = min(yLowBin + 1, this->binsY_);
2177
2178 // determine the supporting positions
2179 const size_t xMinusBin = max(0, int(xLowBin) - 1);
2180 const size_t xPlusBin = min(xLowBin + 2, this->binsX_);
2181 const size_t yMinusBin = max(0, int(yLowBin) - 1);
2182 const size_t yPlusBin = min(yLowBin + 2, this->binsY_);
2183
2184 return Interpolation::cubic(Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yMinusBin), binTopLeftCornerValue(xLowBin, yMinusBin), binTopLeftCornerValue(xHighBin, yMinusBin), binTopLeftCornerValue(xPlusBin, yMinusBin), xFactor),
2185 Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yLowBin), binTopLeftCornerValue(xLowBin, yLowBin), binTopLeftCornerValue(xHighBin, yLowBin), binTopLeftCornerValue(xPlusBin, yLowBin), xFactor),
2186 Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yHighBin), binTopLeftCornerValue(xLowBin, yHighBin), binTopLeftCornerValue(xHighBin, yHighBin), binTopLeftCornerValue(xPlusBin, yHighBin), xFactor),
2187 Interpolation::cubic(binTopLeftCornerValue(xMinusBin, yPlusBin), binTopLeftCornerValue(xLowBin, yPlusBin), binTopLeftCornerValue(xHighBin, yPlusBin), binTopLeftCornerValue(xPlusBin, yPlusBin), xFactor), yFactor);
2188}
2189
2190template <typename T, typename TScalar>
2191T LookupCorner2<T, TScalar>::clampedNearestValue(const TScalar x, const TScalar y) const
2192{
2193 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2194
2195 return nearestValue(minmax<TScalar>(0, x, TScalar(this->sizeX_)), minmax<TScalar>(0, y, TScalar(this->sizeY_)));
2196}
2197
2198template <typename T, typename TScalar>
2199T LookupCorner2<T, TScalar>::clampedBilinearValue(const TScalar x, const TScalar y) const
2200{
2201 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2202
2203 return bilinearValue(minmax<TScalar>(0, x, TScalar(this->sizeX_)), minmax<TScalar>(0, y, TScalar(this->sizeY_)));
2204}
2205
2206template <typename T, typename TScalar>
2207T LookupCorner2<T, TScalar>::clampedBicubicValue(const TScalar x, const TScalar y) const
2208{
2209 ocean_assert(this->binsX_ > 0 && this->binsY_ > 0);
2210
2211 return bicubicValue(minmax<TScalar>(0, x, TScalar(this->sizeX_)), minmax<TScalar>(0, y, TScalar(this->sizeY_)));
2212}
2213
2214template <typename T, typename TScalar>
2215inline void LookupCorner2<T, TScalar>::setBinTopLeftCornerValue(const size_t binX, const size_t binY, const T& value)
2216{
2217 ocean_assert(binX <= this->binsX_ && binY <= this->binsY_);
2218 this->values_[binY * (this->binsX_ + 1) + binX] = value;
2219}
2220
2221template <typename T, typename TScalar>
2223{
2224 LookupCorner2<T, TScalar> result(*this);
2225
2226 for (size_t n = 0; n < result.values_.size(); ++n)
2227 {
2228 result.values_[n] += offset;
2229 }
2230
2231 return result;
2232}
2233
2234template <typename T, typename TScalar>
2236{
2237 for (size_t n = 0; n < this->values_.size(); ++n)
2238 {
2239 this->values_[n] += offset;
2240 }
2241
2242 return *this;
2243}
2244
2245template <typename T, typename TScalar>
2247{
2248 LookupCorner2<T, TScalar> result(*this);
2249
2250 for (size_t n = 0; n < result.values_.size(); ++n)
2251 {
2252 result.values_[n] -= offset;
2253 }
2254
2255 return result;
2256}
2257
2258template <typename T, typename TScalar>
2260{
2261 for (size_t n = 0; n < this->values_.size(); ++n)
2262 {
2263 this->values_[n] -= offset;
2264 }
2265
2266 return *this;
2267}
2268
2269template <typename T, typename TScalar>
2275
2276template <typename T, typename TScalar>
2278{
2279 Lookup2<T, TScalar>::operator=(std::move(lookup));
2280 return *this;
2281}
2282
2283}
2284
2285#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
std::vector< unsigned char > ValidBins
Definition of a vector holding 1 byte values.
Definition Lookup2.h:430
void setBinCenterValid(const size_t binX, const size_t binY, const bool isValid)
Sets whether a specific lookup bin is valid.
Definition Lookup2.h:1622
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:1462
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:1481
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:1605
bool operator!=(const AdvancedLookupCenter2< T, TScalar > &lookup) const
Returns whether two lookup objects are not identical.
Definition Lookup2.h:1647
AdvancedLookupCenter2()=default
Creates a new empty lookup object.
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:1613
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:1597
bool operator==(const AdvancedLookupCenter2< T, TScalar > &lookup) const
Returns whether two lookup objects are identical.
Definition Lookup2.h:1641
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:1455
AdvancedLookupCenter2< T, TScalar > & operator=(AdvancedLookupCenter2< T, TScalar > &&lookup) noexcept
Move operator.
Definition Lookup2.h:1629
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:644
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:539
This class implements a 2D lookup object allowing to separate a two dimensional lookup area into indi...
Definition Lookup2.h:30
std::vector< T > Values
Definition of a vector holding lookup values.
Definition Lookup2.h:43
Values values_
The values of the lookup bins.
Definition Lookup2.h:169
Lookup2< T, TScalar > & operator=(const Lookup2< T, TScalar > &lookup)
Assign operator.
Definition Lookup2.h:978
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:960
const T * data() const
Returns a pointer to the constant bin data (row aligned).
Definition Lookup2.h:942
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:948
size_t binsX_
Number of horizontal bins.
Definition Lookup2.h:151
Lookup2(Lookup2< T, TScalar > &&lookup) noexcept
Move constructor.
Definition Lookup2.h:919
Lookup2< T, TScalar > & operator=(Lookup2< T, TScalar > &&lookup) noexcept
Move operator.
Definition Lookup2.h:994
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:954
bool operator==(const Lookup2< T, TScalar > &lookup) const
Returns whether two lookup objects are identical.
Definition Lookup2.h:1034
bool isEmpty() const
Returns whether this lookup object does not hold any lookup bin.
Definition Lookup2.h:1022
T Type
Definition of the lookup data type.
Definition Lookup2.h:36
size_t binsY() const
Returns the number of vertical bins of this lookup object.
Definition Lookup2.h:972
size_t sizeY_
Vertical dimension of this lookup object.
Definition Lookup2.h:148
Lookup2(const Lookup2< T, TScalar > &lookup)
Copy constructor.
Definition Lookup2.h:904
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:966
bool operator!=(const Lookup2< T, TScalar > &lookup) const
Returns whether two lookup objects are not identical.
Definition Lookup2.h:1040
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:1262
LookupCenter2< T, TScalar > & operator=(LookupCenter2< T, TScalar > &&lookup) noexcept
Move operator.
Definition Lookup2.h:1400
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:1393
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:1229
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:1377
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:1369
T bicubicValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition Lookup2.h:1322
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:1060
size_t binY(const TScalar y) const
Returns the vertical bin that corresponds to a precise vertical lookup position.
Definition Lookup2.h:1158
size_t binTopLeftY(const size_t binY) const
Returns the vertical top left position of a specified bin with pixel accuracy.
Definition Lookup2.h:1181
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:1385
LookupCenter2(const LookupCenter2< T, TScalar > &lookup)
Copy constructor.
Definition Lookup2.h:1046
size_t binBottomRightY(const size_t binY) const
Returns the vertical bottom right position of a specified bin with pixel accuracy.
Definition Lookup2.h:1205
LookupCenter2()=default
Creates a new empty lookup object.
LookupCenter2(LookupCenter2< T, TScalar > &&lookup) noexcept
Move constructor.
Definition Lookup2.h:1053
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:1218
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:1192
size_t binTopLeftX(const size_t binX) const
Returns the horizontal top left position of a specified bin with pixel accuracy.
Definition Lookup2.h:1170
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:1115
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:1240
size_t binX(const TScalar x) const
Returns the horizontal bin that corresponds to a precise horizontal lookup position.
Definition Lookup2.h:1146
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:1248
T bilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition Lookup2.h:1273
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:1139
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:1084
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:1255
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:1660
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:2191
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:2207
LookupCorner2< T, TScalar > & operator+=(const T &offset)
Adds an offset value to each lookup value.
Definition Lookup2.h:2235
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:1746
LookupCorner2< T, TScalar > operator+(const T &offset) const
Adds an offset value to each lookup value.
Definition Lookup2.h:2222
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:1799
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:1807
size_t binX(const TScalar x) const
Returns the horizontal bin that corresponds to a precise horizontal lookup position.
Definition Lookup2.h:1753
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:2100
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:1722
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:2215
LookupCorner2< T, TScalar > & operator-=(const T &offset)
Subtracts an offset value from each lookup value.
Definition Lookup2.h:2259
void bilinearValues(const size_t y, TTarget *values) const
Applies a lookup for an entire row in this lookup object.
Definition Lookup2.h:1877
void bilinearValues(const size_t y, TTarget *values, const bool isOptimized) const
Applies a lookup for an entire row in this lookup object, with an option to use an optimized accumula...
Definition Lookup2.h:2027
T nearestValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition Lookup2.h:1814
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:2199
T bicubicValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition Lookup2.h:2145
size_t binY(const TScalar y) const
Returns the vertical bin that corresponds to a precise vertical lookup position.
Definition Lookup2.h:1765
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:1952
T bilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition Lookup2.h:1828
LookupCorner2(const LookupCorner2< T, TScalar > &lookup)
Copy constructor.
Definition Lookup2.h:1653
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:1691
LookupCorner2< T, TScalar > operator-(const T &offset) const
Subtracts an offset value from each lookup value.
Definition Lookup2.h:2246
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:1788
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:1667
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:1777
LookupCorner2< T, TScalar > & operator=(LookupCorner2< T, TScalar > &&lookup) noexcept
Move operator.
Definition Lookup2.h:2277
LookupCorner2< T, TScalar > & operator=(const LookupCorner2< T, TScalar > &lookup)
Copy operator.
Definition Lookup2.h:2270
This class provides basic numeric functionalities.
Definition Numeric.h:57
static constexpr T eps()
Returns a small epsilon.
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
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