MeshKernel
BoundingBox.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/Point.hpp"
31 
32 #include <algorithm>
33 #include <limits>
34 
35 namespace meshkernel
36 {
37 
40  {
41  public:
43  BoundingBox() : m_lowerLeft(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest()),
44  m_upperRight(std::numeric_limits<double>::max(), std::numeric_limits<double>::max()) {}
45 
50  : m_lowerLeft(lowerLeft),
51  m_upperRight(upperRight)
52  {
53  }
54 
58  template <typename T>
59  explicit BoundingBox(const std::vector<T>& points)
60  {
61  Reset(points);
62  }
63 
67  template <typename T>
68  void Reset(const std::vector<T>& points);
69 
75  template <typename T>
76  void Reset(const std::vector<T>& points, size_t start, size_t end);
77 
83  template <typename T>
84  BoundingBox(const std::vector<T>& points, size_t start, size_t end)
85  {
86  Reset(points, start, end);
87  }
88 
92  bool operator!=(const BoundingBox& other) const
93  {
94  return other.m_lowerLeft != m_lowerLeft || other.m_upperRight != m_upperRight;
95  }
96 
101  template <typename T>
102  bool Contains(const T& point) const
103  {
104 
105  return point.x >= m_lowerLeft.x && point.x <= m_upperRight.x &&
106  point.y >= m_lowerLeft.y && point.y <= m_upperRight.y;
107  }
108 
112  bool Overlaps(const BoundingBox& boundingBox) const;
113 
116  [[nodiscard]] auto& lowerLeft() const { return m_lowerLeft; }
117 
120  [[nodiscard]] auto& upperRight() const { return m_upperRight; }
121 
124  Point MassCentre() const { return (m_lowerLeft + m_upperRight) * 0.5; }
125 
128  double Width() const { return m_upperRight.x - m_lowerLeft.x; }
129 
132  double Height() const { return m_upperRight.y - m_lowerLeft.y; }
133 
135  void Extend(double factor)
136  {
137  // TODO should check that the BB does not cover the entire fp space.
138  const double width = Width();
139  const double height = Height();
140  m_lowerLeft.x -= width * factor;
141  m_lowerLeft.y -= height * factor;
142  m_upperRight.x += width * factor;
143  m_upperRight.y += height * factor;
144  }
145 
147  Vector Delta() const;
148 
150  template <std::derived_from<Point> T>
151  static BoundingBox CreateBoundingBox(const T& first, const T& second)
152  {
153  const auto lowerLeftX = std::min(first.x, second.x);
154  const auto lowerLeftY = std::min(first.y, second.y);
155  const auto upperRightX = std::max(first.x, second.x);
156  const auto upperRightY = std::max(first.y, second.y);
157 
158  return BoundingBox({lowerLeftX, lowerLeftY}, {upperRightX, upperRightY});
159  }
160 
161  private:
162  Point m_lowerLeft;
163  Point m_upperRight;
164  };
165 
167  static BoundingBox Merge(const BoundingBox& b1, const BoundingBox& b2);
168 
170  static BoundingBox CreateNonOverlappingBoundingBox();
171 
172 } // namespace meshkernel
173 
174 template <typename T>
175 void meshkernel::BoundingBox::Reset(const std::vector<T>& points)
176 {
177 
178  if (points.size() > 0)
179  {
180  Reset(points, 0, points.size() - 1);
181  }
182  else
183  {
184  m_lowerLeft = Point(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
185  m_upperRight = Point(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
186  }
187 
188 } // namespace meshkernel
189 
190 template <typename T>
191 void meshkernel::BoundingBox::Reset(const std::vector<T>& points, size_t start, size_t end)
192 {
193  double minx = std::numeric_limits<double>::max();
194  double maxx = std::numeric_limits<double>::lowest();
195  double miny = std::numeric_limits<double>::max();
196  double maxy = std::numeric_limits<double>::lowest();
197 
198  for (size_t i = start; i <= end; ++i)
199  {
200  const auto& point = points[i];
201 
202  if (point.IsValid())
203  {
204  minx = std::min(minx, point.x);
205  maxx = std::max(maxx, point.x);
206  miny = std::min(miny, point.y);
207  maxy = std::max(maxy, point.y);
208  }
209  }
210  m_lowerLeft = Point(minx, miny);
211  m_upperRight = Point(maxx, maxy);
212 }
213 
214 meshkernel::BoundingBox meshkernel::Merge(const BoundingBox& b1, const BoundingBox& b2)
215 {
216  Point lowerLeft{std::min(b1.lowerLeft().x, b2.lowerLeft().x), std::min(b1.lowerLeft().y, b2.lowerLeft().y)};
217  Point upperRight{std::max(b1.upperRight().x, b2.upperRight().x), std::max(b1.upperRight().y, b2.upperRight().y)};
218 
219  return {lowerLeft, upperRight};
220 }
221 
222 meshkernel::BoundingBox meshkernel::CreateNonOverlappingBoundingBox()
223 {
224  Point lowerLeft(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
225  Point upperRight(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
226  return {lowerLeft, upperRight};
227 }
228 
230 {
231  return Vector(m_upperRight.x - m_lowerLeft.x, m_upperRight.y - m_lowerLeft.y);
232 }
233 
234 inline bool meshkernel::BoundingBox::Overlaps(const BoundingBox& other) const
235 {
236  const auto& otherLowerleft = other.lowerLeft();
237  const auto& otherUpperRight = other.upperRight();
238  if (m_upperRight.x < otherLowerleft.x ||
239  otherUpperRight.x < m_lowerLeft.x ||
240  m_upperRight.y < otherLowerleft.y ||
241  otherUpperRight.y < m_lowerLeft.y)
242  {
243  return false;
244  }
245 
246  return true;
247 }
meshkernel::BoundingBox::Width
double Width() const
Returns the bounding box width.
Definition: BoundingBox.hpp:128
meshkernel::BoundingBox::Reset
void Reset(const std::vector< T > &points)
Reset bounding box with a vector of coordinates types.
Definition: BoundingBox.hpp:175
meshkernel::BoundingBox::operator!=
bool operator!=(const BoundingBox &other) const
Not equal operator.
Definition: BoundingBox.hpp:92
meshkernel::BoundingBox
A class defining a bounding box.
Definition: BoundingBox.hpp:39
meshkernel::Point
A struct describing a point in a two-dimensional space.
Definition: Point.hpp:40
meshkernel::Point::x
double x
X-coordinate.
Definition: Point.hpp:43
meshkernel::Vector
A class defining a vector.
Definition: Vector.hpp:38
meshkernel::Point::y
double y
Y-coordinate.
Definition: Point.hpp:44
meshkernel::BoundingBox::lowerLeft
auto & lowerLeft() const
Returns the lower left corner of the bounding box.
Definition: BoundingBox.hpp:116
meshkernel::BoundingBox::BoundingBox
BoundingBox()
Default constructor.
Definition: BoundingBox.hpp:43
meshkernel::BoundingBox::Overlaps
bool Overlaps(const BoundingBox &boundingBox) const
Checks if two bounding boxes overlaps.
Definition: BoundingBox.hpp:234
meshkernel
Contains the logic of the C++ static library.
Definition: AveragingInterpolation.hpp:36
meshkernel::BoundingBox::Delta
Vector Delta() const
Return the delta of the bounding box.
Definition: BoundingBox.hpp:229
meshkernel::BoundingBox::BoundingBox
BoundingBox(const std::vector< T > &points)
Constructor taking a vector of coordinates types.
Definition: BoundingBox.hpp:59
meshkernel::BoundingBox::Height
double Height() const
Returns the bounding box height.
Definition: BoundingBox.hpp:132
meshkernel::BoundingBox::Contains
bool Contains(const T &point) const
Checks if a point is inside a bounding box.
Definition: BoundingBox.hpp:102
meshkernel::BoundingBox::upperRight
auto & upperRight() const
Returns the upper right corner.
Definition: BoundingBox.hpp:120
meshkernel::BoundingBox::BoundingBox
BoundingBox(const std::vector< T > &points, size_t start, size_t end)
Constructor taking a vector of coordinates types.
Definition: BoundingBox.hpp:84
meshkernel::BoundingBox::Extend
void Extend(double factor)
Extends the bounding box by a factor.
Definition: BoundingBox.hpp:135
meshkernel::BoundingBox::BoundingBox
BoundingBox(const Point &lowerLeft, const Point &upperRight)
Constructor taking the corner points of the bounding box.
Definition: BoundingBox.hpp:49
meshkernel::BoundingBox::MassCentre
Point MassCentre() const
Returns the mass centre.
Definition: BoundingBox.hpp:124
meshkernel::BoundingBox::CreateBoundingBox
static BoundingBox CreateBoundingBox(const T &first, const T &second)
Create a bounding box from two points.
Definition: BoundingBox.hpp:151