AliceVision
Photogrammetric Computer Vision Framework
boundingBox.hpp
1 // This file is part of the AliceVision project.
2 // Copyright (c) 2020 AliceVision contributors.
3 // This Source Code Form is subject to the terms of the Mozilla Public License,
4 // v. 2.0. If a copy of the MPL was not distributed with this file,
5 // You can obtain one at https://mozilla.org/MPL/2.0/.
6 
7 #pragma once
8 
9 #include <aliceVision/numeric/numeric.hpp>
10 #include <algorithm>
11 #include <stdint.h>
12 #include <cmath>
13 #include <iostream>
14 
15 namespace aliceVision {
16 
18 {
19  int left;
20  int top;
21  int width;
22  int height;
23 
24  BoundingBox()
25  {
26  left = -1;
27  top = -1;
28  width = 0;
29  height = 0;
30  };
31 
32  BoundingBox(int l, int t, int w, int h)
33  : left(l),
34  top(t),
35  width(w),
36  height(h)
37  {}
38 
39  int getRight() const { return left + width - 1; }
40 
41  int getBottom() const { return top + height - 1; }
42 
43  bool isEmpty() const { return (width <= 0 || height <= 0); }
44 
45  int area() const { return width * height; }
46 
47  void snapToGrid(uint32_t gridSize)
48  {
49  int right = getRight();
50  int bottom = getBottom();
51 
52  int leftBounded = int(std::floor(double(left) / double(gridSize))) * int(gridSize);
53  int topBounded = int(std::floor(double(top) / double(gridSize))) * int(gridSize);
54  int widthBounded = divideRoundUp<int>(right - leftBounded + 1, gridSize) * int(gridSize);
55  int heightBounded = divideRoundUp<int>(bottom - topBounded + 1, gridSize) * int(gridSize);
56 
57  left = leftBounded;
58  top = topBounded;
59  width = widthBounded;
60  height = heightBounded;
61  }
62 
63  BoundingBox unionWith(const BoundingBox& other) const
64  {
65  BoundingBox ret;
66 
67  if (left < 0 && top < 0)
68  {
69  ret.left = other.left;
70  ret.top = other.top;
71  ret.width = other.width;
72  ret.height = other.height;
73  return ret;
74  }
75 
76  int rt = getRight();
77  int ro = other.getRight();
78  int bt = getBottom();
79  int bo = other.getBottom();
80 
81  ret.left = std::min(left, other.left);
82  ret.top = std::min(top, other.top);
83 
84  int maxr = std::max(rt, ro);
85  int maxb = std::max(bt, bo);
86 
87  ret.width = maxr - ret.left + 1;
88  ret.height = maxb - ret.top + 1;
89 
90  return ret;
91  }
92 
93  BoundingBox intersectionWith(const BoundingBox& other) const
94  {
95  BoundingBox intersection;
96 
97  intersection.left = std::max(left, other.left);
98  intersection.top = std::max(top, other.top);
99 
100  int right = std::min(getRight(), other.getRight());
101  int bottom = std::min(getBottom(), other.getBottom());
102 
103  intersection.width = std::max(0, right - intersection.left + 1);
104  intersection.height = std::max(0, bottom - intersection.top + 1);
105 
106  return intersection;
107  }
108 
109  bool isInside(const BoundingBox& other) const
110  {
111  if (other.left > left)
112  return false;
113  if (other.top > top)
114  return false;
115 
116  if (other.getRight() < getRight())
117  return false;
118  if (other.getBottom() < getBottom())
119  return false;
120 
121  return true;
122  }
123 
124  BoundingBox dilate(int units)
125  {
126  BoundingBox b;
127 
128  b.left = left - units;
129  b.top = top - units;
130  b.width = width + units * 2;
131  b.height = height + units * 2;
132 
133  return b;
134  }
135 
136  void clampLeft()
137  {
138  if (left < 0)
139  {
140  width += left;
141  left = 0;
142  }
143  }
144 
145  void clampRight(int maxRight)
146  {
147  if (getRight() > maxRight)
148  {
149  int removal = getRight() - maxRight;
150  width -= removal;
151  }
152  }
153 
154  void clampTop()
155  {
156  if (top < 0)
157  {
158  height += top;
159  top = 0;
160  }
161  }
162 
163  void clampBottom(int maxBottom)
164  {
165  if (getBottom() > maxBottom)
166  {
167  int removal = getBottom() - maxBottom;
168  height -= removal;
169  }
170  }
171 
172  BoundingBox doubleSize() const
173  {
174  BoundingBox b;
175 
176  b.left = left * 2;
177  b.top = top * 2;
178  b.width = width * 2;
179  b.height = height * 2;
180 
181  return b;
182  }
183 
184  BoundingBox multiply(int scale) const
185  {
186  BoundingBox b;
187 
188  int factor = pow(2, scale);
189 
190  b.left = left * factor;
191  b.top = top * factor;
192  b.width = width * factor;
193  b.height = height * factor;
194 
195  return b;
196  }
197 
198  BoundingBox divide(int scale) const
199  {
200  BoundingBox b;
201 
202  int factor = pow(2, scale);
203 
204  b.left = int(floor(double(left) / double(factor)));
205  b.top = int(floor(double(top) / double(factor)));
206 
207  int sleft = b.left * factor;
208  int stop = b.top * factor;
209 
210  int nwidth = getRight() - sleft;
211  int nheight = getBottom() - stop;
212 
213  b.width = int(ceil(double(nwidth) / double(factor)));
214  b.height = int(ceil(double(nheight) / double(factor)));
215 
216  return b;
217  }
218 
219  BoundingBox limitInside(const BoundingBox& other) const
220  {
221  BoundingBox b;
222 
223  b.left = left;
224  if (b.left < other.left)
225  {
226  b.left = other.left;
227  }
228 
229  b.top = top;
230  if (b.top < other.top)
231  {
232  b.top = other.top;
233  }
234 
235  int nright = getRight();
236  if (nright > other.getRight())
237  {
238  nright = other.getRight();
239  }
240 
241  int nbottom = getBottom();
242  if (nbottom > other.getBottom())
243  {
244  nbottom = other.getBottom();
245  }
246 
247  b.width = nright - b.left + 1;
248  b.height = nbottom - b.top + 1;
249 
250  return b;
251  }
252 };
253 
254 std::ostream& operator<<(std::ostream& os, const BoundingBox& in);
255 
256 } // namespace aliceVision
aliceVision::BoundingBox
Definition: boundingBox.hpp:17
aliceVision
Definition: checkerDetector.cpp:32