FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
UniformGrid3.h
1#pragma once
4
5#include <algorithm>
6#include <cmath>
7#include <cstddef>
8#include <stdexcept>
9#include <vector>
10
11namespace marenv::grid
12{
25template<class T>
27{
28public:
30 UniformGrid3() = default;
31
40 UniformGrid3(const double lower[3], const double spacing[3], const int numCells[3], const T& initial = T {})
41 {
42 std::size_t size = 1;
43 for (int a = 0; a < 3; ++a) {
44 if (!(spacing[a] > 0.0))
45 throw std::invalid_argument("UniformGrid3: the spacing must be positive");
46 if (numCells[a] < 1)
47 throw std::invalid_argument("UniformGrid3: the number of cells must be at least 1");
48 m_lower[a] = lower[a];
49 m_spacing[a] = spacing[a];
50 m_numCells[a] = numCells[a];
51 size *= static_cast<std::size_t>(numCells[a] + 1);
52 }
53 m_values.assign(size, initial);
54 }
55
57 int NumCells(int axis) const { return m_numCells[axis]; }
58
60 double Spacing(int axis) const { return m_spacing[axis]; }
61
63 double NodeCoordinate(int axis, int index) const { return m_lower[axis] + index * m_spacing[axis]; }
64
66 T& At(int i, int j, int k) { return m_values[Index(i, j, k)]; }
67
69 const T& At(int i, int j, int k) const { return m_values[Index(i, j, k)]; }
70
78 bool Contains(const double pos[3]) const
79 {
80 if (m_values.empty())
81 return false;
82 for (int a = 0; a < 3; ++a) {
83 const double scaled = (pos[a] - m_lower[a]) / m_spacing[a];
84 if (!(scaled >= -boundarySlack && scaled <= m_numCells[a] + boundarySlack))
85 return false;
86 }
87 return true;
88 }
89
96 bool Interpolate(const double pos[3], T& out) const
97 {
98 if (!Contains(pos)) {
99 out = T {};
100 return false;
101 }
102 int cell[3];
103 double fraction[3];
104 for (int a = 0; a < 3; ++a) {
105 const double scaled = std::clamp((pos[a] - m_lower[a]) / m_spacing[a], 0.0, static_cast<double>(m_numCells[a]));
106 cell[a] = std::min(static_cast<int>(std::floor(scaled)), m_numCells[a] - 1);
107 fraction[a] = scaled - cell[a];
108 }
109 T sum {};
110 for (int corner = 0; corner < 8; ++corner) {
111 double weight = 1.0;
112 int node[3];
113 for (int a = 0; a < 3; ++a) {
114 const bool upper = (corner >> a) & 1;
115 node[a] = cell[a] + (upper ? 1 : 0);
116 weight *= upper ? fraction[a] : 1.0 - fraction[a];
117 }
118 sum = sum + weight * At(node[0], node[1], node[2]);
119 }
120 out = sum;
121 return true;
122 }
123
124private:
125 static constexpr double boundarySlack = 1e-9;
126
127 std::size_t Index(int i, int j, int k) const
128 {
129 const std::size_t numX = static_cast<std::size_t>(m_numCells[0] + 1);
130 const std::size_t numY = static_cast<std::size_t>(m_numCells[1] + 1);
131 return static_cast<std::size_t>(i) + numX * (static_cast<std::size_t>(j) + numY * static_cast<std::size_t>(k));
132 }
133
134 double m_lower[3] = {0.0, 0.0, 0.0};
135 double m_spacing[3] = {1.0, 1.0, 1.0};
136 int m_numCells[3] = {0, 0, 0};
137 std::vector<T> m_values;
138};
139} // namespace marenv::grid
Definition UniformGrid3.h:27
double Spacing(int axis) const
Node spacing along axis.
Definition UniformGrid3.h:60
double NodeCoordinate(int axis, int index) const
Coordinate of node index along axis.
Definition UniformGrid3.h:63
T & At(int i, int j, int k)
Value at node (i, j, k); no bounds check.
Definition UniformGrid3.h:66
UniformGrid3()=default
An empty grid; Contains() is false everywhere.
bool Contains(const double pos[3]) const
Definition UniformGrid3.h:78
int NumCells(int axis) const
Number of cells along axis.
Definition UniformGrid3.h:57
const T & At(int i, int j, int k) const
Value at node (i, j, k); no bounds check.
Definition UniformGrid3.h:69
UniformGrid3(const double lower[3], const double spacing[3], const int numCells[3], const T &initial=T {})
Definition UniformGrid3.h:40
bool Interpolate(const double pos[3], T &out) const
Definition UniformGrid3.h:96