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 const std::size_t nodes = static_cast<std::size_t>(numCells[a]) + 1;
52 if (size > std::vector<T>().max_size() / nodes)
53 throw std::invalid_argument("UniformGrid3: too many nodes");
54 size *= nodes;
55 }
56 m_values.assign(size, initial);
57 }
58
60 int NumCells(int axis) const { return m_numCells[axis]; }
61
63 double Spacing(int axis) const { return m_spacing[axis]; }
64
66 double NodeCoordinate(int axis, int index) const { return m_lower[axis] + index * m_spacing[axis]; }
67
69 T& At(int i, int j, int k) { return m_values[Index(i, j, k)]; }
70
72 const T& At(int i, int j, int k) const { return m_values[Index(i, j, k)]; }
73
81 bool Contains(const double pos[3]) const
82 {
83 if (m_values.empty())
84 return false;
85 for (int a = 0; a < 3; ++a) {
86 const double scaled = (pos[a] - m_lower[a]) / m_spacing[a];
87 if (!(scaled >= -boundarySlack && scaled <= m_numCells[a] + boundarySlack))
88 return false;
89 }
90 return true;
91 }
92
99 bool Interpolate(const double pos[3], T& out) const
100 {
101 if (!Contains(pos)) {
102 out = T {};
103 return false;
104 }
105 int cell[3];
106 double fraction[3];
107 for (int a = 0; a < 3; ++a) {
108 const double scaled = std::clamp((pos[a] - m_lower[a]) / m_spacing[a], 0.0, static_cast<double>(m_numCells[a]));
109 cell[a] = std::min(static_cast<int>(std::floor(scaled)), m_numCells[a] - 1);
110 fraction[a] = scaled - cell[a];
111 }
112 T sum {};
113 for (int corner = 0; corner < 8; ++corner) {
114 double weight = 1.0;
115 int node[3];
116 for (int a = 0; a < 3; ++a) {
117 const bool upper = (corner >> a) & 1;
118 node[a] = cell[a] + (upper ? 1 : 0);
119 weight *= upper ? fraction[a] : 1.0 - fraction[a];
120 }
121 sum = sum + weight * At(node[0], node[1], node[2]);
122 }
123 out = sum;
124 return true;
125 }
126
127private:
128 static constexpr double boundarySlack = 1e-9;
129
130 std::size_t Index(int i, int j, int k) const
131 {
132 const std::size_t numX = static_cast<std::size_t>(m_numCells[0] + 1);
133 const std::size_t numY = static_cast<std::size_t>(m_numCells[1] + 1);
134 return static_cast<std::size_t>(i) + numX * (static_cast<std::size_t>(j) + numY * static_cast<std::size_t>(k));
135 }
136
137 double m_lower[3] = {0.0, 0.0, 0.0};
138 double m_spacing[3] = {1.0, 1.0, 1.0};
139 int m_numCells[3] = {0, 0, 0};
140 std::vector<T> m_values;
141};
142} // namespace marenv::grid
Definition UniformGrid3.h:27
double Spacing(int axis) const
Node spacing along axis.
Definition UniformGrid3.h:63
double NodeCoordinate(int axis, int index) const
Coordinate of node index along axis.
Definition UniformGrid3.h:66
T & At(int i, int j, int k)
Value at node (i, j, k); no bounds check.
Definition UniformGrid3.h:69
UniformGrid3()=default
An empty grid; Contains() is false everywhere.
bool Contains(const double pos[3]) const
Definition UniformGrid3.h:81
int NumCells(int axis) const
Number of cells along axis.
Definition UniformGrid3.h:60
const T & At(int i, int j, int k) const
Value at node (i, j, k); no bounds check.
Definition UniformGrid3.h:72
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:99