MeshKernel
MeshConversion.hpp
1 //---- GPL ---------------------------------------------------------------------
2 //
3 // Copyright (C) Stichting Deltares, 2011-2023.
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 <concepts>
31 
32 #include "MeshKernel/Definitions.hpp"
33 #include "MeshKernel/Exceptions.hpp"
34 #include "MeshKernel/Mesh.hpp"
35 #include "MeshKernel/Point.hpp"
36 #include "MeshKernel/UndoActions/MeshConversionAction.hpp"
37 
38 namespace meshkernel
39 {
40 
42  template <typename Operation>
43  concept HasTransformationOperation = requires(Operation op, Point p) {{ op(p)} -> std::same_as<Point>; };
44 
46  template <typename Operation>
47  concept HasConversionProjection = requires(Operation op) {{ op.SourceProjection()} -> std::same_as<Projection>;
48  { op.TargetProjection()} -> std::same_as<Projection>; };
49 
51  template <typename Operation>
52  concept ConversionFunctor = HasTransformationOperation<Operation> && HasConversionProjection<Operation>;
53 
56  {
57  public:
59  template <ConversionFunctor Conversion>
60  [[nodiscard]] static std::unique_ptr<UndoAction> Compute(const Mesh& sourceMesh, Mesh& targetMesh, const Conversion& conversion)
61  {
62  if (sourceMesh.m_projection != conversion.SourceProjection())
63  {
64  throw MeshKernelError("Incorrect source mesh coordinate system, expecting '{}', found '{}'",
65  ProjectionToString(conversion.SourceProjection()), ProjectionToString(sourceMesh.m_projection));
66  }
67 
68  if (targetMesh.m_projection != conversion.TargetProjection())
69  {
70  throw MeshKernelError("Incorrect target mesh coordinate system, expecting '{}', found '{}'",
71  ProjectionToString(conversion.TargetProjection()), ProjectionToString(targetMesh.m_projection));
72  }
73 
74  if (sourceMesh.GetNumNodes() != targetMesh.GetNumNodes())
75  {
76  throw MeshKernelError("Source and target meshes have different numbers of nodes, source = '{}', target = '{}'",
77  sourceMesh.GetNumNodes(), targetMesh.GetNumNodes());
78  }
79 
80  std::vector<Point> targetNodes(targetMesh.Nodes());
81  std::unique_ptr<MeshConversionAction> undoAction = MeshConversionAction::Create(targetMesh);
82 
83 #pragma omp parallel for
84  for (int i = 0; i < static_cast<int>(sourceMesh.GetNumNodes()); ++i)
85  {
86  if (sourceMesh.Node(i).IsValid())
87  {
88  targetNodes[i] = conversion(sourceMesh.Node(i));
89  }
90  else
91  {
92  targetNodes[i] = sourceMesh.Node(i);
93  }
94 
95 #if 0
96  if (sourceMesh.Node(i).IsValid())
97  {
98  targetMesh.SetNode(i, conversion(sourceMesh.Node(i)));
99  }
100  else
101  {
102  targetMesh.SetNode(i, sourceMesh.Node(i));
103  }
104 #endif
105  }
106 
107  targetMesh.SetNodes(targetNodes);
108  targetMesh.Administrate();
109  return undoAction;
110  }
111 
113  template <ConversionFunctor Conversion>
114  [[nodiscard]] static std::unique_ptr<UndoAction> Compute(Mesh& mesh, const Conversion& conversion)
115  {
116  if (mesh.m_projection != conversion.SourceProjection())
117  {
118  throw MeshKernelError("Incorrect mesh coordinate system, expecting '{}', found '{}'",
119  ProjectionToString(conversion.SourceProjection()), ProjectionToString(mesh.m_projection));
120  }
121 
122  std::vector<Point> nodes(mesh.Nodes());
123  std::unique_ptr<MeshConversionAction> undoAction = MeshConversionAction::Create(mesh);
124 
125 #pragma omp parallel for
126  for (int i = 0; i < static_cast<int>(mesh.GetNumNodes()); ++i)
127  {
128  if (nodes[i].IsValid())
129  {
130  nodes[i] = conversion(nodes[i]);
131  }
132 #if 0
133  if (mesh.Node(i).IsValid())
134  {
135  mesh.SetNode(i, conversion(mesh.Node(i)));
136  }
137 #endif
138  }
139 
140  mesh.SetNodes(nodes);
141  mesh.m_projection = conversion.TargetProjection();
142  mesh.Administrate();
143  return undoAction;
144  }
145  };
146 
147 } // namespace meshkernel
meshkernel::ProjectionToString
const std::string & ProjectionToString(Projection projection)
Get the string representation of the Projection enumeration values.
meshkernel::MeshConversion
Apply a conversion to nodes of a mesh.
Definition: MeshConversion.hpp:55
meshkernel::Mesh::Nodes
const std::vector< Point > & Nodes() const
Get vector of all nodes.
Definition: Mesh.hpp:533
meshkernel::Mesh::Administrate
virtual void Administrate(CompoundUndoAction *undoAction=nullptr)
Perform complete administration.
meshkernel::MeshConversion::Compute
static std::unique_ptr< UndoAction > Compute(Mesh &mesh, const Conversion &conversion)
Apply a conversion to nodes of a mesh.
Definition: MeshConversion.hpp:114
meshkernel::Mesh::GetNumNodes
auto GetNumNodes() const
Get the number of valid nodes.
Definition: Mesh.hpp:145
meshkernel::ConversionFunctor
concept ConversionFunctor
Ensure the MeshConversion template parameter has a valid interface.
Definition: MeshConversion.hpp:52
meshkernel::HasConversionProjection
concept HasConversionProjection
Ensure any instantiation of the MeshConversion Compute function is able to determine source and targe...
Definition: MeshConversion.hpp:47
meshkernel::Point
A struct describing a point in a two-dimensional space.
Definition: Point.hpp:40
meshkernel::Mesh::Node
const Point & Node(const UInt index) const
Get the node at the position.
Definition: Mesh.hpp:538
meshkernel::Mesh::SetNodes
void SetNodes(const std::vector< Point > &newValues)
Set all nodes to a new set of values.
Definition: Mesh.hpp:548
meshkernel::Mesh::m_projection
Projection m_projection
The projection used.
Definition: Mesh.hpp:486
meshkernel
Contains the logic of the C++ static library.
Definition: AveragingInterpolation.hpp:36
meshkernel::HasTransformationOperation
concept HasTransformationOperation
Ensure any instantiation of the MeshTransformation Compute function is with the correct operation.
Definition: MeshConversion.hpp:43
meshkernel::Point::IsValid
bool IsValid(const double missingValue=constants::missing::doubleValue) const
Determines if one of the point coordinates equals to missingValue.
Definition: Point.hpp:116
meshkernel::MeshConversion::Compute
static std::unique_ptr< UndoAction > Compute(const Mesh &sourceMesh, Mesh &targetMesh, const Conversion &conversion)
Apply a conversion to nodes of a mesh.
Definition: MeshConversion.hpp:60
meshkernel::Mesh::SetNode
void SetNode(const UInt index, const Point &newValue)
Set a node to a new value, bypassing the undo action.
meshkernel::MeshKernelError
A class for throwing general MeshKernel exceptions.
Definition: Exceptions.hpp:141
meshkernel::Mesh
A class describing an unstructured mesh. This class contains the shared functionality between 1d or 2...
Definition: Mesh.hpp:98