MeshKernel
Loading...
Searching...
No Matches
BilinearInterpolationOnGriddedSamples.hpp
1//---- GPL ---------------------------------------------------------------------
2//
3// Copyright (C) Stichting Deltares, 2011-2021.
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation version 3.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17// contact: delft3d.support@deltares.nl
18// Stichting Deltares
19// P.O. Box 177
20// 2600 MH Delft, The Netherlands
21//
22// All indications and logos of, and references to, "Delft3D" and "Deltares"
23// are registered trademarks of Stichting Deltares, and remain the property of
24// Stichting Deltares. All rights reserved.
25//
26//------------------------------------------------------------------------------
27
28#pragma once
29
30#include <MeshKernel/Mesh2D.hpp>
31#include <MeshKernel/MeshInterpolation.hpp>
32
33#include <concepts>
34#include <span>
35
36namespace meshkernel
37{
38
40 template <typename T>
41 concept InterpolatableType = std::same_as<T, short> ||
42 std::same_as<T, float> ||
43 std::same_as<T, double> ||
44 std::same_as<T, int>;
45
47 template <InterpolatableType T>
49 {
50 public:
59 UInt numXCoord,
60 UInt numYCoord,
61 const Point& origin,
62 double cellSize,
63 std::span<T const> values);
64
71 std::span<double const> xCoordinates,
72 std::span<double const> yCoordinates,
73 std::span<T const> values);
74
76 void Compute() override;
77
78 private:
82 [[nodiscard]] double Interpolation(const Point& point) const;
83
87 [[nodiscard]] double GetFractionalNumberOfColumns(const Point& point) const;
88
92 [[nodiscard]] double GetFractionalNumberOfRows(const Point& point) const;
93
96 [[nodiscard]] double GetGriddedValue(UInt columnIndex, UInt rowIndex) const;
97
98 const Mesh2D& m_mesh;
99 UInt m_numXCoord;
100 UInt m_numYCoord;
101 Point m_origin;
102 double m_cellSize = 0.0;
103
104 std::span<double const> m_xCoordinates;
105 std::span<double const> m_yCoordinates;
106 std::span<T const> m_values;
107 bool m_isCellSizeConstant;
108 };
109
110 template <InterpolatableType T>
112 UInt numXCoord,
113 UInt numYCoord,
114 const Point& origin,
115 double cellSize,
116 std::span<T const> values)
117 : m_mesh(mesh),
118 m_numXCoord(numXCoord),
119 m_numYCoord(numYCoord),
120 m_origin(origin),
121 m_cellSize(cellSize),
122 m_values(values),
123 m_isCellSizeConstant{true}
124 {
125 }
126
127 template <InterpolatableType T>
129 std::span<double const> xCoordinates,
130 std::span<double const> yCoordinates,
131 std::span<T const> values)
132 : m_mesh(mesh),
133 m_numXCoord(static_cast<UInt>(xCoordinates.size())),
134 m_numYCoord(static_cast<UInt>(yCoordinates.size())),
135 m_xCoordinates(xCoordinates),
136 m_yCoordinates(yCoordinates),
137 m_values{values},
138 m_isCellSizeConstant(false)
139 {
140 }
141
142 template <InterpolatableType T>
144 {
145 const auto numNodes = m_mesh.GetNumNodes();
146 const auto numEdges = m_mesh.GetNumEdges();
147 const auto numFaces = m_mesh.GetNumFaces();
148
149 m_nodeResults.resize(numNodes);
150 std::ranges::fill(m_nodeResults, constants::missing::doubleValue);
151 for (UInt n = 0; n < numNodes; ++n)
152 {
153 const auto node = m_mesh.Node(n);
154
155 if (node.IsValid())
156 {
157 m_nodeResults[n] = Interpolation(node);
158 }
159 }
160
161 m_edgeResults.resize(numEdges);
162 std::ranges::fill(m_edgeResults, constants::missing::doubleValue);
163 for (UInt e = 0; e < numEdges; ++e)
164 {
165 const auto& [first, second] = m_mesh.GetEdge(e);
166
167 if (first != constants::missing::uintValue && second != constants::missing::uintValue)
168 {
169 m_edgeResults[e] = 0.5 * (m_nodeResults[first] + m_nodeResults[second]);
170 }
171 }
172
173 m_faceResults.resize(numFaces, constants::missing::doubleValue);
174 std::ranges::fill(m_faceResults, constants::missing::doubleValue);
175 for (UInt f = 0; f < numFaces; ++f)
176 {
177 if (m_mesh.m_facesMassCenters[f].IsValid())
178 {
179 m_faceResults[f] = Interpolation(m_mesh.m_facesMassCenters[f]);
180 }
181 }
182 }
183
184 template <InterpolatableType T>
186 {
187
188 double fractionalColumnIndex = GetFractionalNumberOfColumns(point);
189 double fractionalRowIndex = GetFractionalNumberOfRows(point);
190
191 double columnIndexTmp;
192 fractionalColumnIndex = std::modf(fractionalColumnIndex, &columnIndexTmp);
193
194 double rowIndexTmp;
195 fractionalRowIndex = std::modf(fractionalRowIndex, &rowIndexTmp);
196
197 if (columnIndexTmp < 0 || rowIndexTmp < 0)
198 {
199 return constants::missing::doubleValue;
200 }
201
202 UInt const columnIndex = static_cast<UInt>(columnIndexTmp);
203 UInt const rowIndex = static_cast<UInt>(rowIndexTmp);
204
205 if (columnIndex + 1 >= m_numXCoord || rowIndex + 1 >= m_numYCoord)
206 {
207 return constants::missing::doubleValue;
208 }
209
210 const auto result = fractionalColumnIndex * fractionalRowIndex * GetGriddedValue(columnIndex + 1, rowIndex + 1) +
211 (1.0 - fractionalColumnIndex) * fractionalRowIndex * GetGriddedValue(columnIndex, rowIndex + 1) +
212 (1.0 - fractionalColumnIndex) * (1.0 - fractionalRowIndex) * GetGriddedValue(columnIndex, rowIndex) +
213 fractionalColumnIndex * (1.0 - fractionalRowIndex) * GetGriddedValue(columnIndex + 1, rowIndex);
214 return result;
215 }
216
217 template <InterpolatableType T>
218 double BilinearInterpolationOnGriddedSamples<T>::GetFractionalNumberOfColumns(const Point& point) const
219 {
220 if (m_isCellSizeConstant)
221 {
222 return (point.x - m_origin.x) / m_cellSize;
223 }
224 double result = constants::missing::doubleValue;
225 if (m_xCoordinates.size() < 2)
226 {
227 return result;
228 }
229 for (UInt i = 0; i < m_xCoordinates.size() - 1; ++i)
230 {
231
232 if (point.x >= m_xCoordinates[i] && point.x < m_xCoordinates[i + 1])
233 {
234 const double dx = m_xCoordinates[i + 1] - m_xCoordinates[i];
235 result = static_cast<double>(i) + (point.x - m_xCoordinates[i]) / dx;
236 break;
237 }
238 }
239 return result;
240 }
241
242 template <InterpolatableType T>
243 double BilinearInterpolationOnGriddedSamples<T>::GetFractionalNumberOfRows(const Point& point) const
244 {
245 if (m_isCellSizeConstant)
246 {
247 return (point.y - m_origin.y) / m_cellSize;
248 }
249
250 double result = constants::missing::doubleValue;
251 if (m_yCoordinates.size() < 2)
252 {
253 return result;
254 }
255
256 for (UInt i = 0; i < m_yCoordinates.size() - 1; ++i)
257 {
258
259 if (point.y >= m_yCoordinates[i] && point.y < m_yCoordinates[i + 1])
260 {
261 const double dy = m_yCoordinates[i + 1] - m_yCoordinates[i];
262 result = static_cast<double>(i) + (point.y - m_yCoordinates[i]) / dy;
263 break;
264 }
265 }
266 return result;
267 }
268
269 template <InterpolatableType T>
270 double BilinearInterpolationOnGriddedSamples<T>::GetGriddedValue(UInt columnIndex, UInt rowIndex) const
271 {
272 const auto index = rowIndex * m_numXCoord + columnIndex;
273 return static_cast<double>(m_values[index]);
274 }
275
276} // namespace meshkernel
A class for performing bilinear interpolation on gridded samples.
Definition BilinearInterpolationOnGriddedSamples.hpp:49
void Compute() override
Compute interpolation.
Definition BilinearInterpolationOnGriddedSamples.hpp:143
BilinearInterpolationOnGriddedSamples(const Mesh2D &mesh, UInt numXCoord, UInt numYCoord, const Point &origin, double cellSize, std::span< T const > values)
Bilinear interpolation with constant cell size (faster because no linear search is performed for each...
Definition BilinearInterpolationOnGriddedSamples.hpp:111
A class derived from Mesh, which describes unstructures 2d meshes.
Definition Mesh2D.hpp:59
Interface for interpolation methods.
Definition MeshInterpolation.hpp:43
A struct describing a point in a two-dimensional space.
Definition Point.hpp:41
Defines the iterpolatable data types.
Definition BilinearInterpolationOnGriddedSamples.hpp:41
Contains the logic of the C++ static library.
Definition AveragingInterpolation.hpp:37
std::uint32_t UInt
Integer type used when indexing mesh graph entities.
Definition Definitions.hpp:39