MeshKernel
MeshTransformation.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 <cmath>
31 #include <concepts>
32 #include <memory>
33 
34 #include "MeshKernel/Definitions.hpp"
35 #include "MeshKernel/Exceptions.hpp"
36 #include "MeshKernel/Mesh.hpp"
37 #include "MeshKernel/Point.hpp"
38 #include "MeshKernel/UndoActions/NodeTranslationAction.hpp"
39 #include "MeshKernel/Vector.hpp"
40 
41 namespace meshkernel
42 {
43 
45  template <typename Function>
46  concept HasTransformationFunction = requires(Function op, Point p) {{ op(p)} -> std::same_as<Point>; };
47 
49  template <typename Function>
50  concept HasTransformationProjection = requires(Function op) {{ op.TransformationProjection()} -> std::same_as<Projection>; };
51 
53  template <typename Function>
54  concept TransformationFunction = HasTransformationFunction<Function> && HasTransformationProjection<Function>;
55 
58  {
59  public:
61  Translation() = default;
62 
64  explicit Translation(const Vector& trans) : m_translation(trans) {}
65 
67  [[nodiscard]] Projection TransformationProjection() const
68  {
69  return Projection::cartesian;
70  }
71 
73  void identity()
74  {
75  m_translation = {0.0, 0.0};
76  }
77 
79  void reset(const Vector& trans)
80  {
81  m_translation = trans;
82  }
83 
85  const Vector& vector() const
86  {
87  return m_translation;
88  }
89 
91  Translation compose(const Translation& trans) const
92  {
93  return Translation(m_translation + trans.m_translation);
94  }
95 
97  Point operator()(const Point& pnt) const
98  {
99  return pnt + m_translation;
100  }
101 
103  Vector operator()(const Vector& vec) const
104  {
105  return vec + m_translation;
106  }
107 
108  private:
110  Vector m_translation{0.0, 0.0};
111  };
112 
114  class Rotation
115  {
116  public:
118  Rotation() = default;
119 
121  explicit Rotation(const double angle)
122  {
123  reset(angle);
124  }
125 
127  [[nodiscard]] Projection TransformationProjection() const
128  {
129  return Projection::cartesian;
130  }
131 
133  void identity()
134  {
135  m_theta = 0.0;
136  m_cosTheta = 1.0;
137  m_sinTheta = 0.0;
138  }
139 
143  void reset(const double angle)
144  {
145  m_theta = angle;
146  m_cosTheta = std::cos(m_theta * constants::conversion::degToRad);
147  m_sinTheta = std::sin(m_theta * constants::conversion::degToRad);
148  }
149 
151  double angle() const
152  {
153  return m_theta;
154  }
155 
157  Rotation compose(const Rotation& rot) const
158  {
159  return Rotation(m_theta + rot.m_theta);
160  }
161 
163  Point operator()(const Point& pnt) const
164  {
165  Point result({m_cosTheta * pnt.x - m_sinTheta * pnt.y,
166  m_sinTheta * pnt.x + m_cosTheta * pnt.y});
167  return result;
168  }
169 
171  Vector operator()(const Vector& vec) const
172  {
173  Vector result({m_cosTheta * vec.x() - m_sinTheta * vec.y(),
174  m_sinTheta * vec.x() + m_cosTheta * vec.y()});
175  return result;
176  }
177 
178  private:
180  double m_theta = 0.0;
181 
183  double m_cosTheta = 1.0;
184 
186  double m_sinTheta = 0.0;
187  };
188 
191  {
192  public:
194  RigidBodyTransformation() = default;
195 
197  [[nodiscard]] Projection TransformationProjection() const
198  {
199  return Projection::cartesian;
200  }
201 
203  void identity()
204  {
205  m_rotation.identity();
206  m_translation.identity();
207  }
208 
212  void compose(const Rotation& rot)
213  {
214  m_rotation = rot.compose(m_rotation);
215  m_translation.reset(rot(m_translation.vector()));
216  }
217 
221  void compose(const Translation& trans)
222  {
223  m_translation = trans.compose(m_translation);
224  }
225 
227  const Rotation& rotation() const
228  {
229  return m_rotation;
230  }
231 
233  const Translation& translation() const
234  {
235  return m_translation;
236  }
237 
239  Point operator()(const Point& pnt) const
240  {
241  Point result = m_rotation(pnt);
242  result = m_translation(result);
243  return result;
244  }
245 
247  Vector operator()(const Vector& vec) const
248  {
249  Vector result = m_rotation(vec);
250  result = m_translation(result);
251  return result;
252  }
253 
254  private:
256  Rotation m_rotation;
257 
259  Translation m_translation;
260  };
261 
264  {
265  public:
267  template <TransformationFunction Transformation>
268  [[nodiscard]] static std::unique_ptr<UndoAction> Compute(Mesh& mesh, Transformation transformation)
269  {
270  if (mesh.m_projection != transformation.TransformationProjection())
271  {
272  throw MeshKernelError("Incorrect mesh coordinate system, expecting '{}', found '{}'",
273  ProjectionToString(transformation.TransformationProjection()), ProjectionToString(mesh.m_projection));
274  }
275 
276  std::unique_ptr<NodeTranslationAction> undoAction = NodeTranslationAction::Create(mesh);
277  std::vector<Point> nodes(mesh.Nodes());
278 
279 #pragma omp parallel for
280  for (int i = 0; i < static_cast<int>(mesh.GetNumNodes()); ++i)
281  {
282  if (nodes[i].IsValid())
283  {
284  nodes[i] = transformation(nodes[i]);
285  }
286 
287 #if 0
288  if (mesh.Node(i).IsValid())
289  {
290  mesh.SetNode(i, transformation(mesh.Node(i)));
291  }
292 #endif
293  }
294 
295  mesh.SetNodes(nodes);
296  mesh.Administrate();
297  return undoAction;
298  }
299  };
300 
301 } // namespace meshkernel
meshkernel::Projection
Projection
Enumerator describing the supported projections.
Definition: Definitions.hpp:41
meshkernel::ProjectionToString
const std::string & ProjectionToString(Projection projection)
Get the string representation of the Projection enumeration values.
meshkernel::Translation::vector
const Vector & vector() const
Get the current defined translation vector.
Definition: MeshTransformation.hpp:85
meshkernel::Translation::Translation
Translation()=default
Default constructor, default is no translation.
meshkernel::Mesh::Nodes
const std::vector< Point > & Nodes() const
Get vector of all nodes.
Definition: Mesh.hpp:533
meshkernel::RigidBodyTransformation::compose
void compose(const Rotation &rot)
Compose rotation and transformation object.
Definition: MeshTransformation.hpp:212
meshkernel::RigidBodyTransformation::TransformationProjection
Projection TransformationProjection() const
Get the projection required for the transformation.
Definition: MeshTransformation.hpp:197
meshkernel::Mesh::Administrate
virtual void Administrate(CompoundUndoAction *undoAction=nullptr)
Perform complete administration.
meshkernel::Rotation::Rotation
Rotation()=default
Default constructor, default is theta = 0.
meshkernel::Mesh::GetNumNodes
auto GetNumNodes() const
Get the number of valid nodes.
Definition: Mesh.hpp:145
meshkernel::RigidBodyTransformation::operator()
Point operator()(const Point &pnt) const
Apply the transformation to a point in Cartesian coordinate system.
Definition: MeshTransformation.hpp:239
meshkernel::Rotation::TransformationProjection
Projection TransformationProjection() const
Get the projection required for the rotation.
Definition: MeshTransformation.hpp:127
meshkernel::Translation
Apply a translation transformation to a point or a vector.
Definition: MeshTransformation.hpp:57
meshkernel::Point
A struct describing a point in a two-dimensional space.
Definition: Point.hpp:40
meshkernel::Translation::Translation
Translation(const Vector &trans)
Construct with user defined translation.
Definition: MeshTransformation.hpp:64
meshkernel::Point::x
double x
X-coordinate.
Definition: Point.hpp:43
meshkernel::RigidBodyTransformation::translation
const Translation & translation() const
Get the current translation.
Definition: MeshTransformation.hpp:233
meshkernel::Vector
A class defining a vector.
Definition: Vector.hpp:38
meshkernel::RigidBodyTransformation::rotation
const Rotation & rotation() const
Get the current rotation.
Definition: MeshTransformation.hpp:227
meshkernel::Translation::identity
void identity()
Reset translation to identity translation (i.e. no translation)
Definition: MeshTransformation.hpp:73
meshkernel::TransformationFunction
concept TransformationFunction
To ensure the MeshTransformation Compute template parameter has a valid interface.
Definition: MeshTransformation.hpp:54
meshkernel::Mesh::Node
const Point & Node(const UInt index) const
Get the node at the position.
Definition: Mesh.hpp:538
meshkernel::Point::y
double y
Y-coordinate.
Definition: Point.hpp:44
meshkernel::Mesh::SetNodes
void SetNodes(const std::vector< Point > &newValues)
Set all nodes to a new set of values.
Definition: Mesh.hpp:548
meshkernel::HasTransformationFunction
concept HasTransformationFunction
Ensure any instantiation of the MeshTransformation Compute function is with the correct operation.
Definition: MeshTransformation.hpp:46
meshkernel::Mesh::m_projection
Projection m_projection
The projection used.
Definition: Mesh.hpp:486
meshkernel::MeshTransformation
Apply a transformation to a mesh.
Definition: MeshTransformation.hpp:263
meshkernel::Rotation::operator()
Point operator()(const Point &pnt) const
Apply the rotation to a point in Cartesian coordinate system.
Definition: MeshTransformation.hpp:163
meshkernel::Translation::compose
Translation compose(const Translation &trans) const
Compose two translation objects.
Definition: MeshTransformation.hpp:91
meshkernel
Contains the logic of the C++ static library.
Definition: AveragingInterpolation.hpp:36
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::Vector::y
double y() const
Gets the y coordinate of the vector.
Definition: Vector.hpp:66
meshkernel::Rotation::identity
void identity()
Reset rotation to identity translation (i.e. no rotation, theta = 0)
Definition: MeshTransformation.hpp:133
meshkernel::HasTransformationProjection
concept HasTransformationProjection
Ensure any instantiation of the MeshTransformation Compute function is able to determine the projecti...
Definition: MeshTransformation.hpp:50
meshkernel::Rotation::angle
double angle() const
Get the current defined rotation angle in degrees.
Definition: MeshTransformation.hpp:151
meshkernel::Translation::TransformationProjection
Projection TransformationProjection() const
Get the projection required for the translation.
Definition: MeshTransformation.hpp:67
meshkernel::Translation::reset
void reset(const Vector &trans)
Reset the translation to a new translation quantity.
Definition: MeshTransformation.hpp:79
meshkernel::RigidBodyTransformation::identity
void identity()
Reset transformation to identity transformation (i.e. no transformation)
Definition: MeshTransformation.hpp:203
meshkernel::Vector::x
double x() const
Gets the x coordinate of the vector.
Definition: Vector.hpp:52
meshkernel::Rotation::compose
Rotation compose(const Rotation &rot) const
Compose two rotation objects.
Definition: MeshTransformation.hpp:157
meshkernel::Rotation::Rotation
Rotation(const double angle)
Construct with user defined rotation angle, in degrees.
Definition: MeshTransformation.hpp:121
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::Rotation::reset
void reset(const double angle)
Reset the rotation to a new rotation angle.
Definition: MeshTransformation.hpp:143
meshkernel::Rotation::operator()
Vector operator()(const Vector &vec) const
Apply the rotation to a vector in Cartesian coordinate system.
Definition: MeshTransformation.hpp:171
meshkernel::Translation::operator()
Vector operator()(const Vector &vec) const
Apply the translation to a vector in Cartesian coordinate system.
Definition: MeshTransformation.hpp:103
meshkernel::RigidBodyTransformation::RigidBodyTransformation
RigidBodyTransformation()=default
Default constructor, default is no transformation.
meshkernel::RigidBodyTransformation::operator()
Vector operator()(const Vector &vec) const
Apply the transformation to a vector in Cartesian coordinate system.
Definition: MeshTransformation.hpp:247
meshkernel::Rotation
Apply a rotation transformation to a point or a vector.
Definition: MeshTransformation.hpp:114
meshkernel::RigidBodyTransformation::compose
void compose(const Translation &trans)
Compose translation and transformation object.
Definition: MeshTransformation.hpp:221
meshkernel::MeshTransformation::Compute
static std::unique_ptr< UndoAction > Compute(Mesh &mesh, Transformation transformation)
Apply a transformation to a mesh with a Cartesian projection.
Definition: MeshTransformation.hpp:268
meshkernel::Mesh
A class describing an unstructured mesh. This class contains the shared functionality between 1d or 2...
Definition: Mesh.hpp:98
meshkernel::RigidBodyTransformation
A composition of translation and rotation transformations.
Definition: MeshTransformation.hpp:190
meshkernel::Translation::operator()
Point operator()(const Point &pnt) const
Apply the translation to a point in Cartesian coordinate system.
Definition: MeshTransformation.hpp:97