LSSTApplications  11.0-24-g0a022a1,15.0+13,15.0+9,15.0-1-g19261fa+5,15.0-1-g1eca518+15,15.0-1-g60afb23+12,15.0-1-g615e0bb+4,15.0-1-g6668b0b+5,15.0-1-g788a293+12,15.0-1-ga91101e+12,15.0-1-gae1598d+8,15.0-1-gc45031d+15,15.0-1-gd076f1f+12,15.0-1-gdf18595+2,15.0-1-gf4f1c34+8,15.0-2-g100d730+5,15.0-2-g18f3f21+5,15.0-2-g35685a8+6,15.0-2-gf38729e+5,15.0-21-g91b8abf62,15.0-3-g150fc43+14,15.0-3-g6f085af+5,15.0-3-g707930d,15.0-3-g9103c06+8,15.0-3-ga03b4ca+16,15.0-3-gaec6799+5,15.0-3-gb7a597c+12,15.0-3-ge6a6747+5,15.0-4-g45f767a+8,15.0-4-g654b129+10,15.0-4-gf5d1e39,15.0-4-gff20472+15,15.0-5-ga70c291+5,15.0-6-g9a9df217+5,15.0-7-gab4c137+6,15.0-7-gab79a70c+4
LSSTDataManagementBasePackage
Box.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008-2014 LSST Corporation.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #include <cmath>
24 #include <limits>
25 
26 #include "lsst/afw/geom/Box.h"
27 
28 namespace lsst {
29 namespace afw {
30 namespace geom {
31 
32 Box2I::Box2I(Point2I const& minimum, Point2I const& maximum, bool invert)
33  : _minimum(minimum), _dimensions(maximum - minimum) {
34  for (int n = 0; n < 2; ++n) {
35  if (_dimensions[n] < 0) {
36  if (invert) {
37  _minimum[n] += _dimensions[n];
38  _dimensions[n] = -_dimensions[n];
39  } else {
40  *this = Box2I();
41  return;
42  }
43  }
44  }
45  _dimensions += Extent2I(1);
46 }
47 
48 Box2I::Box2I(Point2I const& minimum, Extent2I const& dimensions, bool invert)
49  : _minimum(minimum), _dimensions(dimensions) {
50  for (int n = 0; n < 2; ++n) {
51  if (_dimensions[n] == 0) {
52  *this = Box2I();
53  return;
54  } else if (_dimensions[n] < 0) {
55  if (invert) {
56  _minimum[n] += (_dimensions[n] + 1);
57  _dimensions[n] = -_dimensions[n];
58  } else {
59  *this = Box2I();
60  return;
61  }
62  }
63  }
64  if (!isEmpty() && any(getMin().gt(getMax()))) {
66  "Box dimensions too large; integer overflow detected.");
67  }
68 }
69 
70 Box2I::Box2I(Box2D const& other, EdgeHandlingEnum edgeHandling) : _minimum(), _dimensions() {
71  if (other.isEmpty()) {
72  *this = Box2I();
73  return;
74  }
75  if (!std::isfinite(other.getMinX()) || !std::isfinite(other.getMinY()) ||
76  !std::isfinite(other.getMaxX()) || !std::isfinite(other.getMaxY())) {
77  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, "Cannot convert non-finite Box2D to Box2I");
78  }
79  Point2D fpMin(other.getMin() + Extent2D(0.5));
80  Point2D fpMax(other.getMax() - Extent2D(0.5));
81  switch (edgeHandling) {
82  case EXPAND:
83  for (int n = 0; n < 2; ++n) {
84  _minimum[n] = static_cast<int>(std::floor(fpMin[n]));
85  _dimensions[n] = static_cast<int>(std::ceil(fpMax[n])) + 1 - _minimum[n];
86  }
87  break;
88  case SHRINK:
89  for (int n = 0; n < 2; ++n) {
90  _minimum[n] = static_cast<int>(std::ceil(fpMin[n]));
91  _dimensions[n] = static_cast<int>(std::floor(fpMax[n])) + 1 - _minimum[n];
92  }
93  break;
94  }
95 }
96 
97 ndarray::View<boost::fusion::vector2<ndarray::index::Range, ndarray::index::Range> > Box2I::getSlices()
98  const {
99  return ndarray::view(getBeginY(), getEndY())(getBeginX(), getEndX());
100 }
101 
102 bool Box2I::contains(Point2I const& point) const {
103  return all(point.ge(this->getMin())) && all(point.le(this->getMax()));
104 }
105 
106 bool Box2I::contains(Box2I const& other) const {
107  return other.isEmpty() ||
108  (all(other.getMin().ge(this->getMin())) && all(other.getMax().le(this->getMax())));
109 }
110 
111 bool Box2I::overlaps(Box2I const& other) const {
112  return !(other.isEmpty() || this->isEmpty() || any(other.getMax().lt(this->getMin())) ||
113  any(other.getMin().gt(this->getMax())));
114 }
115 
116 void Box2I::grow(Extent2I const& buffer) {
117  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
118  _minimum -= buffer;
119  _dimensions += buffer * 2;
120  if (any(_dimensions.le(0))) *this = Box2I();
121 }
122 
123 void Box2I::shift(Extent2I const& offset) {
124  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
125  _minimum += offset;
126 }
127 
128 void Box2I::flipLR(int xextent) {
129  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
130  // Apply flip about y-axis assumine parent coordinate system
131  _minimum[0] = xextent - (_minimum[0] + _dimensions[0]);
132  // _dimensions should remain unchanged
133 }
134 
135 void Box2I::flipTB(int yextent) {
136  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
137  // Apply flip about y-axis assumine parent coordinate system
138  _minimum[1] = yextent - (_minimum[1] + _dimensions[1]);
139  // _dimensions should remain unchanged
140 }
141 
142 void Box2I::include(Point2I const& point) {
143  if (isEmpty()) {
144  _minimum = point;
145  _dimensions = Extent2I(1);
146  return;
147  }
148  Point2I maximum(getMax());
149  for (int n = 0; n < 2; ++n) {
150  if (point[n] < _minimum[n]) {
151  _minimum[n] = point[n];
152  } else if (point[n] > maximum[n]) {
153  maximum[n] = point[n];
154  }
155  }
156  _dimensions = Extent2I(1) + maximum - _minimum;
157 }
158 
159 void Box2I::include(Box2I const& other) {
160  if (other.isEmpty()) return;
161  if (this->isEmpty()) {
162  *this = other;
163  return;
164  }
165  Point2I maximum(getMax());
166  Point2I const& otherMin = other.getMin();
167  Point2I const otherMax = other.getMax();
168  for (int n = 0; n < 2; ++n) {
169  if (otherMin[n] < _minimum[n]) {
170  _minimum[n] = otherMin[n];
171  }
172  if (otherMax[n] > maximum[n]) {
173  maximum[n] = otherMax[n];
174  }
175  }
176  _dimensions = Extent2I(1) + maximum - _minimum;
177 }
178 
179 void Box2I::clip(Box2I const& other) {
180  if (isEmpty()) return;
181  if (other.isEmpty()) {
182  *this = Box2I();
183  return;
184  }
185  Point2I maximum(getMax());
186  Point2I const& otherMin = other.getMin();
187  Point2I const otherMax = other.getMax();
188  for (int n = 0; n < 2; ++n) {
189  if (otherMin[n] > _minimum[n]) {
190  _minimum[n] = otherMin[n];
191  }
192  if (otherMax[n] < maximum[n]) {
193  maximum[n] = otherMax[n];
194  }
195  }
196  if (any(maximum.lt(_minimum))) {
197  *this = Box2I();
198  return;
199  }
200  _dimensions = Extent2I(1) + maximum - _minimum;
201 }
202 
203 bool Box2I::operator==(Box2I const& other) const {
204  return other._minimum == this->_minimum && other._dimensions == this->_dimensions;
205 }
206 
207 bool Box2I::operator!=(Box2I const& other) const {
208  return other._minimum != this->_minimum || other._dimensions != this->_dimensions;
209 }
210 
212  std::vector<Point2I> retVec;
213  retVec.push_back(getMin());
214  retVec.push_back(Point2I(getMaxX(), getMinY()));
215  retVec.push_back(getMax());
216  retVec.push_back(Point2I(getMinX(), getMaxY()));
217  return retVec;
218 }
219 
221 
223 
224 Box2D::Box2D() : _minimum(INVALID), _maximum(INVALID) {}
225 
226 Box2D::Box2D(Point2D const& minimum, Point2D const& maximum, bool invert)
227  : _minimum(minimum), _maximum(maximum) {
228  for (int n = 0; n < 2; ++n) {
229  if (_minimum[n] == _maximum[n]) {
230  *this = Box2D();
231  return;
232  } else if (_minimum[n] > _maximum[n]) {
233  if (invert) {
234  std::swap(_minimum[n], _maximum[n]);
235  } else {
236  *this = Box2D();
237  return;
238  }
239  }
240  }
241 }
242 
243 Box2D::Box2D(Point2D const& minimum, Extent2D const& dimensions, bool invert)
244  : _minimum(minimum), _maximum(minimum + dimensions) {
245  for (int n = 0; n < 2; ++n) {
246  if (_minimum[n] == _maximum[n]) {
247  *this = Box2D();
248  return;
249  } else if (_minimum[n] > _maximum[n]) {
250  if (invert) {
251  std::swap(_minimum[n], _maximum[n]);
252  } else {
253  *this = Box2D();
254  return;
255  }
256  }
257  }
258 }
259 
261  : _minimum(Point2D(other.getMin()) - Extent2D(0.5)),
262  _maximum(Point2D(other.getMax()) + Extent2D(0.5)) {
263  if (other.isEmpty()) *this = Box2D();
264 }
265 
266 bool Box2D::contains(Point2D const& point) const {
267  return all(point.ge(this->getMin())) && all(point.lt(this->getMax()));
268 }
269 
270 bool Box2D::contains(Box2D const& other) const {
271  return other.isEmpty() ||
272  (all(other.getMin().ge(this->getMin())) && all(other.getMax().le(this->getMax())));
273 }
274 
275 bool Box2D::overlaps(Box2D const& other) const {
276  return !(other.isEmpty() || this->isEmpty() || any(other.getMax().le(this->getMin())) ||
277  any(other.getMin().ge(this->getMax())));
278 }
279 
280 void Box2D::grow(Extent2D const& buffer) {
281  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
282  _minimum -= buffer;
283  _maximum += buffer;
284  if (any(_minimum.ge(_maximum))) *this = Box2D();
285 }
286 
287 void Box2D::shift(Extent2D const& offset) {
288  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
289  _minimum += offset;
290  _maximum += offset;
291 }
292 
293 void Box2D::flipLR(float xextent) {
294  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
295  // Swap min and max values for x dimension
296  _minimum[0] += _maximum[0];
297  _maximum[0] = _minimum[0] - _maximum[0];
298  _minimum[0] -= _maximum[0];
299  // Apply flip assuming coordinate system of parent.
300  _minimum[0] = xextent - _minimum[0];
301  _maximum[0] = xextent - _maximum[0];
302  // _dimensions should remain unchanged
303 }
304 
305 void Box2D::flipTB(float yextent) {
306  if (isEmpty()) return; // should we throw an exception here instead of a no-op?
307  // Swap min and max values for y dimension
308  _minimum[1] += _maximum[1];
309  _maximum[1] = _minimum[1] - _maximum[1];
310  _minimum[1] -= _maximum[1];
311  // Apply flip assuming coordinate system of parent.
312  _minimum[1] = yextent - _minimum[1];
313  _maximum[1] = yextent - _maximum[1];
314  // _dimensions should remain unchanged
315 }
316 
317 void Box2D::include(Point2D const& point) {
318  if (isEmpty()) {
319  _minimum = point;
320  _maximum = point;
321  _tweakMax(0);
322  _tweakMax(1);
323  return;
324  }
325  for (int n = 0; n < 2; ++n) {
326  if (point[n] < _minimum[n]) {
327  _minimum[n] = point[n];
328  } else if (point[n] >= _maximum[n]) {
329  _maximum[n] = point[n];
330  _tweakMax(n);
331  }
332  }
333 }
334 
335 void Box2D::include(Box2D const& other) {
336  if (other.isEmpty()) return;
337  if (this->isEmpty()) {
338  *this = other;
339  return;
340  }
341  Point2D const& otherMin = other.getMin();
342  Point2D const& otherMax = other.getMax();
343  for (int n = 0; n < 2; ++n) {
344  if (otherMin[n] < _minimum[n]) {
345  _minimum[n] = otherMin[n];
346  }
347  if (otherMax[n] > _maximum[n]) {
348  _maximum[n] = otherMax[n];
349  }
350  }
351 }
352 
353 void Box2D::clip(Box2D const& other) {
354  if (isEmpty()) return;
355  if (other.isEmpty()) {
356  *this = Box2D();
357  return;
358  }
359  Point2D const& otherMin = other.getMin();
360  Point2D const& otherMax = other.getMax();
361  for (int n = 0; n < 2; ++n) {
362  if (otherMin[n] > _minimum[n]) {
363  _minimum[n] = otherMin[n];
364  }
365  if (otherMax[n] < _maximum[n]) {
366  _maximum[n] = otherMax[n];
367  }
368  }
369  if (any(_maximum.le(_minimum))) {
370  *this = Box2D();
371  return;
372  }
373 }
374 
375 bool Box2D::operator==(Box2D const& other) const {
376  return (other.isEmpty() && this->isEmpty()) ||
377  (other._minimum == this->_minimum && other._maximum == this->_maximum);
378 }
379 
380 bool Box2D::operator!=(Box2D const& other) const {
381  return !(other.isEmpty() && other.isEmpty()) &&
382  (other._minimum != this->_minimum || other._maximum != this->_maximum);
383 }
384 
386  std::vector<Point2D> retVec;
387  retVec.push_back(getMin());
388  retVec.push_back(Point2D(getMaxX(), getMinY()));
389  retVec.push_back(getMax());
390  retVec.push_back(Point2D(getMinX(), getMaxY()));
391  return retVec;
392 }
393 
395  if (box.isEmpty()) return os << "Box2I()";
396  return os << "Box2I(Point2I" << box.getMin() << ", Extent2I" << box.getDimensions() << ")";
397 }
398 
400  if (box.isEmpty()) return os << "Box2D()";
401  return os << "Box2D(Point2D" << box.getMin() << ", Extent2D" << box.getDimensions() << ")";
402 }
403 }
404 }
405 } // end lsst::afw::geom
bool overlaps(Box2D const &other) const
Return true if any points in other are also in this.
Definition: Box.cc:275
void grow(double buffer)
Increase the size of the box by the given buffer amount in all directions.
Definition: Box.h:399
Point2I const getMin() const
Definition: Box.h:123
afw::table::PointKey< int > dimensions
Definition: GaussianPsf.cc:44
bool isEmpty() const
Return true if the box contains no points.
Definition: Box.h:163
bool all(CoordinateExpr< N > const &expr)
Return true if all elements are true.
int getMinX() const
Definition: Box.h:124
void shift(Extent2I const &offset)
Shift the position of the box by the given offset.
Definition: Box.cc:123
CoordinateExpr< N > gt(Point< T, N > const &other) const
Definition: Point.cc:106
T ceil(T... args)
bool contains(Point2D const &point) const
Return true if the box contains the point.
Definition: Box.cc:266
Extent< double, 2 > Extent2D
Definition: Extent.h:383
std::ostream & operator<<(std::ostream &os, lsst::afw::geom::AffineTransform const &transform)
Box2I()
Construct an empty box.
Definition: Box.h:64
T swap(T... args)
T epsilon(T... args)
static double const INVALID
Value used to specify undefined coordinate values.
Definition: Box.h:279
A coordinate class intended to represent offsets and dimensions.
void include(Point2I const &point)
Expand this to ensure that this->contains(point).
Definition: Box.cc:142
bool operator!=(Box2D const &other) const
Compare two boxes for equality.
Definition: Box.cc:380
Extent< int, 2 > Extent2I
Definition: Extent.h:380
double getMaxX() const
Definition: Box.h:343
T floor(T... args)
bool isEmpty() const
Return true if the box contains no points.
Definition: Box.h:374
A coordinate class intended to represent absolute positions.
An integer coordinate rectangle.
Definition: Box.h:55
Extent2D const getDimensions() const
Definition: Box.h:353
Point2I const getMax() const
Definition: Box.h:127
void clip(Box2D const &other)
Shrink this to ensure that other.contains(*this).
Definition: Box.cc:353
CoordinateExpr< N > ge(Point< T, N > const &other) const
Definition: Point.cc:113
CoordinateExpr< N > le(Extent< T, N > const &other) const
Definition: Extent.cc:66
bool any(CoordinateExpr< N > const &expr)
Return true if any elements are true.
T push_back(T... args)
bool overlaps(Box2I const &other) const
Return true if any points in other are also in this.
Definition: Box.cc:111
A base class for image defects.
Definition: cameraGeom.dox:3
Reports when the result of an arithmetic operation is too large for the destination type...
Definition: Runtime.h:124
Point< double, 2 > Point2D
Definition: Point.h:304
void flipTB(float yExtent)
Flip a bounding box about the x-axis given a parent box of extent (yExtent).
Definition: Box.cc:305
double getMaxY() const
Definition: Box.h:344
double getMinX() const
Definition: Box.h:339
void include(Point2D const &point)
Expand this to ensure that this->contains(point).
Definition: Box.cc:317
bool operator==(Box2D const &other) const
Compare two boxes for equality.
Definition: Box.cc:375
bool operator==(Box2I const &other) const
Compare two boxes for equality.
Definition: Box.cc:203
T isfinite(T... args)
static double const EPSILON
Value the maximum coordinate is multiplied by to increase it by the smallest possible amount...
Definition: Box.h:276
bool contains(Point2I const &point) const
Return true if the box contains the point.
Definition: Box.cc:102
int getEndY() const
Definition: Box.h:144
int getBeginX() const
Definition: Box.h:139
void flipLR(int xExtent)
Flip a bounding box about the y-axis given a parent box of extent (xExtent).
Definition: Box.cc:128
CoordinateExpr< N > le(Point< T, N > const &other) const
Definition: Point.cc:99
std::vector< Point2D > getCorners() const
Get the corner points.
Definition: Box.cc:385
ndarray::View< boost::fusion::vector2< ndarray::index::Range, ndarray::index::Range > > getSlices() const
Return slices to extract the box&#39;s region from an ndarray::Array.
Definition: Box.cc:97
Box2D()
Construct an empty box.
Definition: Box.cc:224
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:47
void flipLR(float xExtent)
Flip a bounding box about the y-axis given a parent box of extent (xExtent).
Definition: Box.cc:293
STL class.
std::vector< Point2I > getCorners() const
Get the corner points.
Definition: Box.cc:211
void grow(int buffer)
Increase the size of the box by the given buffer amount in all directions.
Definition: Box.h:188
int getBeginY() const
Definition: Box.h:140
Extent2I const getDimensions() const
Definition: Box.h:153
int getMaxX() const
Definition: Box.h:128
void flipTB(int yExtent)
Flip a bounding box about the x-axis given a parent box of extent (yExtent).
Definition: Box.cc:135
void shift(Extent2D const &offset)
Shift the position of the box by the given offset.
Definition: Box.cc:287
Reports invalid arguments.
Definition: Runtime.h:66
ItemVariant const * other
Definition: Schema.cc:55
bool operator!=(Box2I const &other) const
Compare two boxes for equality.
Definition: Box.cc:207
int getMaxY() const
Definition: Box.h:129
void clip(Box2I const &other)
Shrink this to ensure that other.contains(*this).
Definition: Box.cc:179
T quiet_NaN(T... args)
Point< int, 2 > Point2I
Definition: Point.h:301
A floating-point coordinate rectangle geometry.
Definition: Box.h:266
CoordinateExpr< N > lt(Point< T, N > const &other) const
Definition: Point.cc:92
int getMinY() const
Definition: Box.h:125
int getEndX() const
Definition: Box.h:143
STL class.
std::ostream * os
Definition: Schema.cc:736
double getMinY() const
Definition: Box.h:340
Point2D const getMax() const
Definition: Box.h:342
Point2D const getMin() const
Definition: Box.h:338