30#include <MeshKernel/Constants.hpp>
31#include <MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp>
32#include <MeshKernel/Entities.hpp>
33#include <MeshKernel/Exceptions.hpp>
34#include <MeshKernel/Mesh1D.hpp>
35#include <MeshKernel/Mesh2D.hpp>
36#include <MeshKernel/MeshEdgeCenters.hpp>
37#include <MeshKernel/Operations.hpp>
38#include <MeshKernel/Splines.hpp>
40#include <MeshKernelApi/GeometryList.hpp>
41#include <MeshKernelApi/GriddedSamples.hpp>
42#include <MeshKernelApi/Mesh1D.hpp>
43#include <MeshKernelApi/Mesh2D.hpp>
45#include "MeshKernel/BilinearInterpolationOnGriddedSamples.hpp"
46#include <MeshKernel/CurvilinearGrid/CurvilinearGridRectangular.hpp>
48#include "MeshKernelApi/CurvilinearGrid.hpp"
61 static std::vector<meshkernel::Point> ConvertGeometryListToPointVector(
const GeometryList& geometryListIn)
63 std::vector<meshkernel::Point> result;
64 if (geometryListIn.num_coordinates == 0)
68 result.reserve(geometryListIn.num_coordinates);
69 result.emplace_back(geometryListIn.coordinates_x[0], geometryListIn.coordinates_y[0]);
71 for (
auto i = 1; i < geometryListIn.num_coordinates; ++i)
78 result.emplace_back(geometryListIn.coordinates_x[i], geometryListIn.coordinates_y[i]);
87 static std::vector<std::vector<meshkernel::Point>> ConvertGeometryListToVectorOfPointVectors(GeometryList
const& geometryListIn)
89 std::vector<std::vector<meshkernel::Point>> result;
90 std::vector<meshkernel::Point> chunk;
91 chunk.reserve(geometryListIn.num_coordinates);
92 for (
auto i = 0; i < geometryListIn.num_coordinates; ++i)
95 if (
meshkernel::IsEqual(geometryListIn.coordinates_x[i], geometryListIn.geometry_separator))
97 result.emplace_back(chunk);
102 chunk.emplace_back(geometryListIn.coordinates_x[i], geometryListIn.coordinates_y[i]);
108 result.emplace_back(chunk);
118 template <
typename T>
119 static std::vector<std::vector<T>> ConvertVectorToVectorOfVectors(
const std::vector<T> input, T separator)
121 std::vector<std::vector<T>> result;
122 std::vector<T> chunk;
123 for (
size_t i = 0; i < input.size(); ++i)
127 result.emplace_back(chunk);
132 chunk.emplace_back(input[i]);
137 result.emplace_back(chunk);
146 static std::vector<bool> ConvertIntegerArrayToBoolVector(
const int inputArray[],
size_t inputSize)
148 std::vector<bool> result(inputSize);
149 for (
size_t i = 0; i < inputSize; ++i)
151 switch (inputArray[i])
160 throw std::invalid_argument(
"MeshKernel: Invalid 1D mask.");
169 static std::vector<meshkernel::Sample> ConvertGeometryListToSampleVector(
const GeometryList& geometryListIn)
171 if (geometryListIn.num_coordinates == 0)
173 throw std::invalid_argument(
"MeshKernel: The samples are empty.");
175 std::vector<meshkernel::Sample> result;
176 result.reserve(geometryListIn.num_coordinates);
178 for (
auto i = 0; i < geometryListIn.num_coordinates; ++i)
180 result.push_back({geometryListIn.coordinates_x[i], geometryListIn.coordinates_y[i], geometryListIn.values[i]});
188 static void ConvertPointVectorToGeometryList(std::vector<meshkernel::Point>
const& pointVector, GeometryList& result)
190 if (pointVector.size() <
static_cast<size_t>(result.num_coordinates))
192 throw std::invalid_argument(
"MeshKernel: Invalid memory allocation, the point-vector size is smaller than the number of coordinates in the result vector.");
195 for (
auto i = 0; i < result.num_coordinates; ++i)
197 result.coordinates_x[i] = pointVector[i].x;
198 result.coordinates_y[i] = pointVector[i].y;
206 static void ConvertSampleVectorToGeometryList(std::vector<meshkernel::Point>
const& valuesCoordinates, std::vector<double>
const& values, GeometryList& result)
208 if (valuesCoordinates.size() != values.size())
210 throw std::invalid_argument(
"MeshKernel: The size of the valuesCoordinates-vector is not equal to the size of the values-vector");
213 if (values.size() <
static_cast<size_t>(result.num_coordinates))
215 throw std::invalid_argument(
"MeshKernel: Invalid memory allocation, the value-vector size is smaller than the number of coordinates in the result vector.");
218 for (
auto i = 0; i < result.num_coordinates; ++i)
220 result.coordinates_x[i] = valuesCoordinates[i].x;
221 result.coordinates_y[i] = valuesCoordinates[i].y;
222 result.values[i] = values[i];
229 template <meshkernel::InterpolatableType T>
230 static std::vector<meshkernel::Sample> ComputeGriddedDataSamples(
const GriddedSamples& griddedSamples)
232 std::vector<meshkernel::Sample> result;
234 const auto numSamples =
static_cast<size_t>(griddedSamples.num_x * griddedSamples.num_y);
235 result.resize(numSamples);
236 const T* valuePtr =
static_cast<T*
>(griddedSamples.values);
237 if (griddedSamples.x_coordinates ==
nullptr || griddedSamples.y_coordinates ==
nullptr)
241 for (
int j = 0; j < griddedSamples.num_x; ++j)
243 for (
int i = griddedSamples.num_y - 1; i >= 0; --i)
245 const auto griddedIndex = griddedSamples.num_x * i + j;
246 result[index].
x = origin.x + j * griddedSamples.cell_size;
247 result[index].y = origin.y + i * griddedSamples.cell_size;
248 result[index].value =
static_cast<double>(valuePtr[griddedIndex]);
256 for (
int j = 0; j < griddedSamples.num_x; ++j)
258 for (
int i = griddedSamples.num_y - 1; i >= 0; --i)
260 const auto griddedIndex = griddedSamples.num_x * i + j;
261 result[index].x = origin.x + griddedSamples.x_coordinates[griddedIndex];
262 result[index].y = origin.y + griddedSamples.y_coordinates[griddedIndex];
263 result[index].value =
static_cast<double>(valuePtr[griddedIndex]);
273 static std::vector<meshkernel::Sample> ConvertGriddedData(
const GriddedSamples& griddedSamples)
275 std::vector<meshkernel::Sample> result;
276 if (griddedSamples.num_x <= 0 || griddedSamples.num_y <= 0)
283 return ComputeGriddedDataSamples<short>(griddedSamples);
287 return ComputeGriddedDataSamples<float>(griddedSamples);
291 return ComputeGriddedDataSamples<double>(griddedSamples);
295 return ComputeGriddedDataSamples<int>(griddedSamples);
305 if (geometryListIn.num_coordinates == 0)
310 const auto splineCornerPoints = ConvertGeometryListToPointVector(geometryListIn);
312 const auto indices =
FindIndices(splineCornerPoints,
315 meshkernel::constants::missing::doubleValue);
317 for (
const auto& index : indices)
319 const auto& [startIndex, endIndex] = index;
320 const auto size = endIndex - startIndex + 1;
323 spline.
AddSpline(splineCornerPoints, startIndex, size);
331 static void SetMesh2dApiDimensions(
const meshkernel::Mesh& mesh2d, Mesh2D& mesh2dApi)
333 size_t num_face_nodes = 0;
339 mesh2dApi.num_face_nodes =
static_cast<int>(num_face_nodes);
340 mesh2dApi.num_faces =
static_cast<int>(mesh2d.
GetNumFaces());
341 mesh2dApi.num_nodes =
static_cast<int>(mesh2d.
GetNumNodes());
343 mesh2dApi.num_edges =
static_cast<int>(mesh2d.
GetNumEdges());
352 if (mesh2dApi.num_nodes !=
static_cast<int>(mesh2d.
GetNumNodes()))
354 throw meshkernel::ConstraintError(
"The number of nodes in the mesh2d api structure does not equal the number of nodes in the grid, {} /= {}",
358 if (mesh2dApi.num_edges !=
static_cast<int>(mesh2d.
GetNumEdges()))
360 throw meshkernel::ConstraintError(
"The number of edges in the mesh2d api structure does not equal the number of edges in the grid, {} /= {}",
366 mesh2dApi.node_x[n] = mesh2d.
Node(n).
x;
367 mesh2dApi.node_y[n] = mesh2d.
Node(n).
y;
372 mesh2dApi.edge_nodes[edgeIndex * 2] =
static_cast<int>(mesh2d.
GetEdge(edgeIndex).first);
373 mesh2dApi.edge_nodes[edgeIndex * 2 + 1] =
static_cast<int>(mesh2d.
GetEdge(edgeIndex).second);
375 SetMesh2dApiDimensions(mesh2d, mesh2dApi);
383 std::vector<meshkernel::Point> edgeCentres = meshkernel::algo::ComputeEdgeCentres(mesh2d);
387 mesh2dApi.node_x[n] = mesh2d.
Node(n).
x;
388 mesh2dApi.node_y[n] = mesh2d.
Node(n).
y;
393 mesh2dApi.edge_x[edgeIndex] = edgeCentres[edgeIndex].x;
394 mesh2dApi.edge_y[edgeIndex] = edgeCentres[edgeIndex].y;
395 mesh2dApi.edge_nodes[edgeIndex * 2] =
static_cast<int>(mesh2d.
GetEdge(edgeIndex).first);
396 mesh2dApi.edge_nodes[edgeIndex * 2 + 1] =
static_cast<int>(mesh2d.
GetEdge(edgeIndex).second);
398 const auto& firstEdgeFace = mesh2d.
m_edgesFaces[edgeIndex][0];
399 mesh2dApi.edge_faces[edgeIndex * 2] = firstEdgeFace == meshkernel::constants::missing::uintValue ? -1 :
static_cast<int>(firstEdgeFace);
400 const auto& secondEdgeFace = mesh2d.
m_edgesFaces[edgeIndex][1];
401 mesh2dApi.edge_faces[edgeIndex * 2 + 1] = secondEdgeFace == meshkernel::constants::missing::uintValue ? -1 :
static_cast<int>(secondEdgeFace);
409 mesh2dApi.nodes_per_face[f] =
static_cast<int>(mesh2d.
m_facesNodes[f].size());
410 for (
size_t n = 0; n < mesh2d.
m_facesNodes[f].size(); ++n)
412 mesh2dApi.face_nodes[faceIndex] =
static_cast<int>(mesh2d.
m_facesNodes[f][n]);
413 mesh2dApi.face_edges[faceIndex] =
static_cast<int>(mesh2d.
m_facesEdges[f][n]);
417 SetMesh2dApiDimensions(mesh2d, mesh2dApi);
423 static void SetCurvilinearGridApiData(
const meshkernel::CurvilinearGrid& curvilinearGrid,
424 CurvilinearGrid& curvilinearGridApi)
426 if (curvilinearGridApi.num_n !=
static_cast<int>(curvilinearGrid.NumN()))
428 throw meshkernel::ConstraintError(
"The number of rows in the api structure does not equal the number of rows in the grid, {} /= {}",
429 curvilinearGridApi.num_n, curvilinearGrid.NumN());
432 if (curvilinearGridApi.num_m !=
static_cast<int>(curvilinearGrid.NumM()))
434 throw meshkernel::ConstraintError(
"The number of columns in the api structure does not equal the number of columns in the grid, {} /= {}",
435 curvilinearGridApi.num_m, curvilinearGrid.NumM());
444 curvilinearGridApi.node_x[count] = curvilinearGrid.GetNode(n, m).x;
445 curvilinearGridApi.node_y[count] = curvilinearGrid.GetNode(n, m).y;
457 mesh1dApi.num_nodes =
static_cast<int>(mesh1d.
GetNumNodes());
459 mesh1dApi.num_edges =
static_cast<int>(mesh1d.
GetNumEdges());
471 mesh1dApi.node_x[n] = mesh1d.
Node(n).
x;
472 mesh1dApi.node_y[n] = mesh1d.
Node(n).
y;
475 size_t edgeIndex = 0;
478 mesh1dApi.edge_nodes[edgeIndex] =
static_cast<int>(mesh1d.
GetEdge(e).first);
480 mesh1dApi.edge_nodes[edgeIndex] =
static_cast<int>(mesh1d.
GetEdge(e).second);
483 SetMesh1dApiDimension(mesh1d, mesh1dApi);
493 meshkernel::CurvilinearGridRectangular grid(projection);
494 return grid.Compute(makeGridParameters.
num_columns,
498 makeGridParameters.
angle,
508 static std::unique_ptr<meshkernel::CurvilinearGrid> CreateRectangularCurvilinearGridFromPolygons(
const meshkernel::MakeGridParameters& makeGridParameters,
509 const GeometryList& geometryList,
512 const meshkernel::CurvilinearGridRectangular grid(projection);
514 auto polygonNodes = ConvertGeometryListToPointVector(geometryList);
516 const auto polygon = std::make_shared<meshkernel::Polygons>(polygonNodes, projection);
518 return grid.Compute(makeGridParameters.
angle,
529 static std::unique_ptr<meshkernel::CurvilinearGrid> CreateRectangularCurvilinearGridOnExtension(
const meshkernel::MakeGridParameters& makeGridParameters,
532 const meshkernel::CurvilinearGridRectangular grid(projection);
536 throw meshkernel::AlgorithmError(
"When generating an uniform grid on an defined extension, the grid angle must be equal to 0");
539 return grid.Compute(makeGridParameters.
origin_x,
547 template <meshkernel::InterpolatableType T>
548 static std::unique_ptr<meshkernel::MeshInterpolation> CreateBilinearInterpolator(
const meshkernel::Mesh2D& mesh2d,
549 const GriddedSamples& griddedSamples)
552 if (griddedSamples.x_coordinates ==
nullptr || griddedSamples.y_coordinates ==
nullptr)
554 return std::make_unique<meshkernel::BilinearInterpolationOnGriddedSamples<T>>(mesh2d,
555 griddedSamples.num_x,
556 griddedSamples.num_y,
558 griddedSamples.cell_size,
559 std::span<T const>{
reinterpret_cast<T const* const
>(griddedSamples.values),
560 static_cast<size_t>(griddedSamples.num_x * griddedSamples.num_y)});
562 return std::make_unique<meshkernel::BilinearInterpolationOnGriddedSamples<T>>(mesh2d,
563 std::span<double const>{griddedSamples.x_coordinates,
564 static_cast<size_t>(griddedSamples.num_x)},
565 std::span<double const>{griddedSamples.y_coordinates,
566 static_cast<size_t>(griddedSamples.num_y)},
567 std::span<T const>{
reinterpret_cast<T const* const
>(griddedSamples.values),
568 static_cast<size_t>(griddedSamples.num_x * griddedSamples.num_y)});
571 static std::unique_ptr<meshkernel::MeshInterpolation> CreateBilinearInterpolatorBasedOnType(
const GriddedSamples& griddedSamples,
578 return CreateBilinearInterpolator<short>(mesh2d, griddedSamples);
580 return CreateBilinearInterpolator<float>(mesh2d, griddedSamples);
582 return CreateBilinearInterpolator<int>(mesh2d, griddedSamples);
584 return CreateBilinearInterpolator<double>(mesh2d, griddedSamples);
591 const std::vector<bool>& facesInPolygon,
592 const GeometryList& facePolygons)
597 if (!facesInPolygon[f])
605 facePolygons.coordinates_x[count] = meshkernel::constants::missing::doubleValue;
606 facePolygons.coordinates_y[count] = meshkernel::constants::missing::doubleValue;
612 const auto& currentNode = mesh2d.
Node(faceNodes[n]);
613 facePolygons.coordinates_x[count] = currentNode.
x;
614 facePolygons.coordinates_y[count] = currentNode.y;
617 const auto& currentNode = mesh2d.
Node(faceNodes[0]);
618 facePolygons.coordinates_x[count] = currentNode.
x;
619 facePolygons.coordinates_y[count] = currentNode.y;
624 static std::optional<double> MinValidElement(
const std::vector<double>& values)
626 auto filtered = values | std::views::filter([](
const double& v)
627 {
return v != meshkernel::constants::missing::doubleValue; });
628 auto begin = std::ranges::begin(filtered);
629 auto end = std::ranges::end(filtered);
636 return *std::ranges::min_element(filtered);
A class for throwing algorithm exceptions.
Definition Exceptions.hpp:248
An exception class thrown when an attempt is made that violates a range constraint.
Definition Exceptions.hpp:267
A class derived from Mesh, which describes 1d meshes.
Definition Mesh1D.hpp:43
A class derived from Mesh, which describes unstructures 2d meshes.
Definition Mesh2D.hpp:58
A class describing an unstructured mesh. This class contains the shared functionality between 1d or 2...
Definition Mesh.hpp:99
const Edge & GetEdge(const UInt index) const
Get constant reference to an edge.
Definition Mesh.hpp:542
std::vector< std::vector< UInt > > m_facesEdges
The edge indices composing the face (netcelllin)
Definition Mesh.hpp:473
const Point & Node(const UInt index) const
Get the node at the position.
Definition Mesh.hpp:523
std::vector< std::vector< UInt > > m_facesNodes
The nodes composing the faces, in ccw order (netcellNod)
Definition Mesh.hpp:471
auto GetNumFaces() const
Get the number of valid faces.
Definition Mesh.hpp:153
auto GetNumEdges() const
Get the number of valid edges.
Definition Mesh.hpp:149
std::vector< Point > m_facesMassCenters
The faces centers of mass (xzw, yzw)
Definition Mesh.hpp:474
UInt GetNumValidNodes() const
Get the number of valid nodes.
std::vector< std::array< UInt, 2 > > m_edgesFaces
For each edge, the shared face index (lne)
Definition Mesh.hpp:467
auto GetNumNodes() const
Get the number of valid nodes.
Definition Mesh.hpp:145
UInt GetNumValidEdges() const
Get the number of valid edges.
A class for throwing general MeshKernel exceptions.
Definition Exceptions.hpp:142
A struct describing a point in a two-dimensional space.
Definition Point.hpp:41
double x
X-coordinate.
Definition Point.hpp:43
double y
Y-coordinate.
Definition Point.hpp:44
A class describing splines.
Definition Splines.hpp:48
void AddSpline(const std::vector< Point > &splines, UInt start, UInt size)
Adds a new spline to m_splineCornerPoints.
Projection
Enumerator describing the supported projections.
Definition Definitions.hpp:43
bool IsEqual(const Point &p1, const Point &p2, const double epsilon)
Test points for equality upto a tolerance.
Definition Point.hpp:450
std::uint32_t UInt
Integer type used when indexing mesh graph entities.
Definition Definitions.hpp:39
InterpolationDataTypes
The possible types of the values to be interpolated in the gridded sample.
Definition Definitions.hpp:100
std::vector< std::pair< UInt, UInt > > FindIndices(const std::vector< Point > &vec, size_t start, size_t end, double separator)
Find all start-end positions in a vector separated by a separator.
Contains all structs and functions exposed at the API level.
Definition BoundingBox.hpp:33
This struct describes the necessary parameters to create a new curvilinear grid in a C-compatible man...
Definition Parameters.hpp:38
double origin_y
The y coordinate of the origin, located at the bottom left corner.
Definition Parameters.hpp:52
double upper_right_x
The x coordinate of the upper right corner.
Definition Parameters.hpp:61
double angle
The grid angle.
Definition Parameters.hpp:46
int num_rows
The number of rows in y direction.
Definition Parameters.hpp:43
double origin_x
The x coordinate of the origin, located at the bottom left corner.
Definition Parameters.hpp:49
int num_columns
The number of columns in x direction.
Definition Parameters.hpp:40
double block_size_x
The grid block size in x dimension, used only for squared grids.
Definition Parameters.hpp:55
double block_size_y
The grid block size in y dimension, used only for squared grids.
Definition Parameters.hpp:58
double upper_right_y
The y coordinate of the upper right corner.
Definition Parameters.hpp:64