lsst.sphgeom  21.0.0+4fcf437b75
Box.h
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2014-2015 AURA/LSST.
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 <https://www.lsstcorp.org/LegalNotices/>.
21  */
22 
23 #ifndef LSST_SPHGEOM_BOX_H_
24 #define LSST_SPHGEOM_BOX_H_
25 
29 
30 #include <iosfwd>
31 
32 #include "AngleInterval.h"
33 #include "LonLat.h"
35 #include "Region.h"
36 #include "UnitVector3d.h"
37 
38 
39 namespace lsst {
40 namespace sphgeom {
41 
54 class Box : public Region {
55 public:
56  static constexpr uint8_t TYPE_CODE = 'b';
57 
58  // Factory functions
59  static Box fromDegrees(double lon1, double lat1, double lon2, double lat2) {
60  return Box(NormalizedAngleInterval::fromDegrees(lon1, lon2),
61  AngleInterval::fromDegrees(lat1, lat2));
62  }
63 
64  static Box fromRadians(double lon1, double lat1, double lon2, double lat2) {
65  return Box(NormalizedAngleInterval::fromRadians(lon1, lon2),
66  AngleInterval::fromRadians(lat1, lat2));
67  }
68 
69  static Box empty() { return Box(); }
70 
71  static Box full() { return Box(allLongitudes(), allLatitudes()); }
72 
78 
82  return NormalizedAngleInterval::full();
83  }
84 
88  return AngleInterval(Angle(-0.5 * PI), Angle(0.5 * PI));
89  }
90 
92  Box() {}
93 
95  explicit Box(LonLat const & p) :
96  _lon(p.getLon()),
97  _lat(p.getLat())
98  {
99  _enforceInvariants();
100  }
101 
105  Box(LonLat const & p1, LonLat const & p2) :
106  _lon(p1.getLon(), p2.getLon()),
107  _lat(p1.getLat(), p2.getLat())
108  {
109  _enforceInvariants();
110  }
111 
114  Box(LonLat const & p, Angle w, Angle h) :
115  _lon(NormalizedAngleInterval(p.getLon()).dilatedBy(w)),
116  _lat(AngleInterval(p.getLat()).dilatedBy(h))
117  {
118  _enforceInvariants();
119  }
120 
123  Box(NormalizedAngleInterval const & lon, AngleInterval const & lat) :
124  _lon(lon),
125  _lat(lat)
126  {
127  _enforceInvariants();
128  }
129 
131  bool operator==(Box const & b) const {
132  return _lon == b._lon && _lat == b._lat;
133  }
134 
135  bool operator!=(Box const & b) const { return !(*this == b); }
136 
138  bool operator==(LonLat const & p) const {
139  return _lat == p.getLat() && _lon == p.getLon();
140  }
141 
142  bool operator!=(LonLat const & p) const { return !(*this == p); }
143 
145  NormalizedAngleInterval const & getLon() const { return _lon; }
146 
148  AngleInterval const & getLat() const { return _lat; }
149 
151  bool isEmpty() const { return _lat.isEmpty(); }
152 
155  bool isFull() const { return _lon.isFull() && _lat == allLatitudes(); }
156 
159  LonLat getCenter() const {
160  return LonLat(_lon.getCenter(), _lat.getCenter());
161  }
162 
165  NormalizedAngle getWidth() const { return _lon.getSize(); }
166 
169  Angle getHeight() const { return _lat.getSize(); }
170 
174  bool contains(LonLat const & x) const {
175  return _lat.contains(x.getLat()) && _lon.contains(x.getLon());
176  }
177 
178  bool contains(Box const & x) const {
179  return _lat.contains(x._lat) && _lon.contains(x._lon);
180  }
182 
186  bool isDisjointFrom(LonLat const & x) const { return !intersects(x); }
187 
188  bool isDisjointFrom(Box const & x) const { return !intersects(x); }
190 
194  bool intersects(LonLat const & x) const {
195  return _lat.intersects(x.getLat()) && _lon.intersects(x.getLon());
196  }
197 
198  bool intersects(Box const & x) const {
199  return _lat.intersects(x._lat) && _lon.intersects(x._lon);
200  }
202 
206  bool isWithin(LonLat const & x) const {
207  return _lat.isWithin(x.getLat()) && _lon.isWithin(x.getLon());
208  }
209 
210  bool isWithin(Box const & x) const {
211  return _lat.isWithin(x._lat) && _lon.isWithin(x._lon);
212  }
214 
217  Box & clipTo(LonLat const & x) {
218  _lon.clipTo(x.getLon());
219  _lat.clipTo(x.getLat());
220  _enforceInvariants();
221  return *this;
222  }
223 
227  Box & clipTo(Box const & x) {
228  _lon.clipTo(x.getLon());
229  _lat.clipTo(x.getLat());
230  _enforceInvariants();
231  return *this;
232  }
233 
235  Box clippedTo(LonLat const & x) const { return Box(*this).clipTo(x); }
236 
240  Box clippedTo(Box const & x) const { return Box(*this).clipTo(x); }
241 
246  Box & expandTo(LonLat const & x) {
247  _lon.expandTo(x.getLon());
248  _lat.expandTo(x.getLat());
249  return *this;
250  }
251 
252  Box & expandTo(Box const & x) {
253  _lon.expandTo(x.getLon());
254  _lat.expandTo(x.getLat());
255  return *this;
256  }
258 
263  Box expandedTo(LonLat const & x) const { return Box(*this).expandTo(x); }
264  Box expandedTo(Box const & x) const { return Box(*this).expandTo(x); }
266 
272  Box & dilateBy(Angle r);
273  Box dilatedBy(Angle r) const { return Box(*this).dilateBy(r); }
274 
290  Box & dilateBy(Angle w, Angle h);
291  Box dilatedBy(Angle w, Angle h) const { return Box(*this).dilateBy(w, h); }
292  Box & erodeBy(Angle r) { return dilateBy(-r); }
293  Box & erodeBy(Angle w, Angle h) { return dilateBy(-w, -h); }
294  Box erodedBy(Angle r) const { return dilatedBy(-r); }
295  Box erodedBy(Angle w, Angle h) const { return dilatedBy(-w, -h); }
296 
297  Relationship relate(LonLat const & p) const { return relate(Box(p)); }
298 
300  double getArea() const;
301 
302  // Region interface
303  std::unique_ptr<Region> clone() const override {
304  return std::unique_ptr<Box>(new Box(*this));
305  }
306 
307  Box getBoundingBox() const override { return *this; }
308  Box3d getBoundingBox3d() const override;
309  Circle getBoundingCircle() const override;
310 
311  bool contains(UnitVector3d const & v) const override {
312  return contains(LonLat(v));
313  }
314 
315  Relationship relate(Region const & r) const override {
316  // Dispatch on the type of r.
317  return invert(r.relate(*this));
318  }
319 
320  Relationship relate(Box const & b) const override {
321  Relationship r1 = _lon.relate(b._lon);
322  Relationship r2 = _lat.relate(b._lat);
323  // If the box longitude or latitude intervals are disjoint, then the
324  // boxes are disjoint. The other spatial relationships must hold for
325  // both the longitude and latitude intervals in order to hold for the
326  // boxes.
327  return ((r1 & r2) & (CONTAINS | WITHIN)) | ((r1 | r2) & DISJOINT);
328  }
329 
330  Relationship relate(Circle const &) const override;
331  Relationship relate(ConvexPolygon const &) const override;
332  Relationship relate(Ellipse const &) const override;
333 
334  std::vector<uint8_t> encode() const override;
335 
338  static std::unique_ptr<Box> decode(std::vector<uint8_t> const & s) {
339  return decode(s.data(), s.size());
340  }
341  static std::unique_ptr<Box> decode(uint8_t const * buffer, size_t n);
343 
344 private:
345  static constexpr size_t ENCODED_SIZE = 33;
346 
347  void _enforceInvariants() {
348  // Make sure that _lat ⊆ [-π/2, π/2].
349  _lat.clipTo(allLatitudes());
350  // Make sure that both longitude and latitude intervals are
351  // empty, or neither is. This simplifies the implementation
352  // of the spatial relation tests.
353  if (_lat.isEmpty()) {
354  _lon = NormalizedAngleInterval();
355  } else if (_lon.isEmpty()) {
356  _lat = AngleInterval();
357  }
358  }
359 
360  NormalizedAngleInterval _lon;
361  AngleInterval _lat;
362 };
363 
364 std::ostream & operator<<(std::ostream &, Box const &);
365 
366 }} // namespace lsst::sphgeom
367 
368 #endif // LSST_SPHGEOM_BOX_H_
lsst::sphgeom::Box
Definition: Box.h:54
lsst::sphgeom::Box::getBoundingBox3d
Box3d getBoundingBox3d() const override
getBoundingBox3d returns a 3-dimensional bounding-box for this region.
Definition: Box.cc:127
lsst::sphgeom::Box::clippedTo
Box clippedTo(LonLat const &x) const
clippedTo returns the intersection of this box and x.
Definition: Box.h:235
lsst::sphgeom::Circle
Definition: Circle.h:46
lsst::sphgeom::NormalizedAngleInterval
Definition: NormalizedAngleInterval.h:57
lsst::sphgeom::NormalizedAngleInterval::intersects
bool intersects(NormalizedAngle x) const
Definition: NormalizedAngleInterval.h:173
lsst::sphgeom::Interval::intersects
bool intersects(Scalar x) const
Definition: Interval.h:130
lsst::sphgeom::NormalizedAngleInterval::getSize
NormalizedAngle getSize() const
Definition: NormalizedAngleInterval.h:145
lsst::sphgeom::AngleInterval
AngleInterval represents closed intervals of arbitrary angles.
Definition: AngleInterval.h:39
lsst::sphgeom::Box::clippedTo
Box clippedTo(Box const &x) const
Definition: Box.h:240
lsst::sphgeom::Box::clipTo
Box & clipTo(Box const &x)
Definition: Box.h:227
lsst::sphgeom::NormalizedAngleInterval::getCenter
NormalizedAngle getCenter() const
Definition: NormalizedAngleInterval.h:139
lsst::sphgeom::invert
Relationship invert(Relationship r)
Definition: Relationship.h:55
lsst::sphgeom::NormalizedAngleInterval::clipTo
NormalizedAngleInterval & clipTo(NormalizedAngle x)
clipTo shrinks this interval until all its points are in x.
Definition: NormalizedAngleInterval.h:203
lsst::sphgeom::Box::getArea
double getArea() const
getArea returns the area of this box in steradians.
Definition: Box.cc:115
lsst::sphgeom::Box::relate
Relationship relate(Region const &r) const override
Definition: Box.h:315
lsst::sphgeom::Box::encode
std::vector< uint8_t > encode() const override
Definition: Box.cc:447
lsst::sphgeom::Box::allLatitudes
static AngleInterval allLatitudes()
Definition: Box.h:87
LonLat.h
This file contains a class representing spherical coordinates.
lsst::sphgeom::Box::isWithin
bool isWithin(LonLat const &x) const
Definition: Box.h:206
lsst::sphgeom::Box::Box
Box(NormalizedAngleInterval const &lon, AngleInterval const &lat)
Definition: Box.h:123
lsst::sphgeom::Relationship
std::bitset< 3 > Relationship
Relationship describes how two sets are related.
Definition: Relationship.h:35
lsst::sphgeom::NormalizedAngleInterval::relate
Relationship relate(NormalizedAngle x) const
Definition: NormalizedAngleInterval.cc:88
UnitVector3d.h
This file declares a class for representing unit vectors in ℝ³.
lsst::sphgeom::Box::decode
static std::unique_ptr< Box > decode(std::vector< uint8_t > const &s)
Definition: Box.h:338
AngleInterval.h
This file defines a class for representing angle intervals.
lsst::sphgeom::Interval::getSize
Scalar getSize() const
Definition: Interval.h:93
lsst::sphgeom::Interval::getCenter
Scalar getCenter() const
Definition: Interval.h:89
lsst::sphgeom::Box::operator==
bool operator==(Box const &b) const
Two boxes are equal if they contain the same points.
Definition: Box.h:131
lsst::sphgeom::Box::isEmpty
bool isEmpty() const
isEmpty returns true if this box does not contain any points.
Definition: Box.h:151
lsst::sphgeom::Box::clipTo
Box & clipTo(LonLat const &x)
Definition: Box.h:217
lsst::sphgeom::Box::allLongitudes
static NormalizedAngleInterval allLongitudes()
Definition: Box.h:81
Region.h
This file defines an interface for spherical regions.
lsst::sphgeom::Box::getBoundingBox
Box getBoundingBox() const override
getBoundingBox returns a bounding-box for this region.
Definition: Box.h:307
lsst::sphgeom::Box::getLat
AngleInterval const & getLat() const
getLat returns the latitude interval of this box.
Definition: Box.h:148
lsst::sphgeom::Angle
Definition: Angle.h:43
lsst::sphgeom::Box::operator==
bool operator==(LonLat const &p) const
A box is equal to a point p if it contains only p.
Definition: Box.h:138
lsst::sphgeom::NormalizedAngleInterval::isWithin
bool isWithin(NormalizedAngle x) const
Definition: NormalizedAngleInterval.h:185
lsst::sphgeom::NormalizedAngleInterval::expandTo
NormalizedAngleInterval & expandTo(NormalizedAngle x)
Definition: NormalizedAngleInterval.cc:189
lsst::sphgeom::Interval::relate
Relationship relate(Scalar x) const
Definition: Interval.h:249
lsst::sphgeom::Box::Box
Box()
This constructor creates an empty box.
Definition: Box.h:92
lsst::sphgeom::Box::getHeight
Angle getHeight() const
Definition: Box.h:169
lsst::sphgeom::Box::expandTo
Box & expandTo(LonLat const &x)
Definition: Box.h:246
lsst::sphgeom::LonLat
Definition: LonLat.h:48
lsst::sphgeom::Box::Box
Box(LonLat const &p1, LonLat const &p2)
Definition: Box.h:105
lsst::sphgeom::NormalizedAngleInterval::isFull
bool isFull() const
isFull returns true if this interval contains all normalized angles.
Definition: NormalizedAngleInterval.h:129
lsst::sphgeom::NormalizedAngle
Definition: NormalizedAngle.h:41
lsst::sphgeom::Box::clone
std::unique_ptr< Region > clone() const override
clone returns a deep copy of this region.
Definition: Box.h:303
lsst::sphgeom::Box::dilateBy
Box & dilateBy(Angle r)
Definition: Box.cc:78
NormalizedAngleInterval.h
This file declares a class representing closed intervals of normalized angles, i.e....
lsst::sphgeom::Region::relate
virtual Relationship relate(Region const &) const =0
lsst::sphgeom::Box::getLon
NormalizedAngleInterval const & getLon() const
getLon returns the longitude interval of this box.
Definition: Box.h:145
lsst::sphgeom::Box::getBoundingCircle
Circle getBoundingCircle() const override
getBoundingCircle returns a bounding-circle for this region.
Definition: Box.cc:187
lsst::sphgeom::Interval::contains
bool contains(Scalar x) const
Definition: Interval.h:98
lsst::sphgeom::Box::getCenter
LonLat getCenter() const
Definition: Box.h:159
lsst::sphgeom::Box::expandedTo
Box expandedTo(LonLat const &x) const
Definition: Box.h:263
lsst::sphgeom::UnitVector3d
Definition: UnitVector3d.h:55
lsst::sphgeom::Interval::expandTo
Interval & expandTo(Scalar x)
Definition: Interval.h:192
lsst::sphgeom::Box::contains
bool contains(LonLat const &x) const
Definition: Box.h:174
lsst::sphgeom::Interval::isEmpty
bool isEmpty() const
isEmpty returns true if this interval does not contain any points.
Definition: Interval.h:83
lsst::sphgeom::Box::Box
Box(LonLat const &p)
This constructor creates a box containing a single point.
Definition: Box.h:95
lsst::sphgeom::Region
Definition: Region.h:79
lsst::sphgeom::NormalizedAngleInterval::contains
bool contains(NormalizedAngle x) const
Definition: NormalizedAngleInterval.h:150
lsst::sphgeom::Box::Box
Box(LonLat const &p, Angle w, Angle h)
Definition: Box.h:114
lsst::sphgeom::Box::getWidth
NormalizedAngle getWidth() const
Definition: Box.h:165
lsst::sphgeom::Box::halfWidthForCircle
static NormalizedAngle halfWidthForCircle(Angle r, Angle lat)
Definition: Box.cc:43
lsst::sphgeom::Interval::isWithin
bool isWithin(Scalar x) const
Definition: Interval.h:140
lsst::sphgeom::Box::isDisjointFrom
bool isDisjointFrom(LonLat const &x) const
Definition: Box.h:186
lsst::sphgeom::Box::contains
bool contains(UnitVector3d const &v) const override
contains tests whether the given unit vector is inside this region.
Definition: Box.h:311
lsst::sphgeom::Box3d
Definition: Box3d.h:42
lsst::sphgeom::Box::isFull
bool isFull() const
Definition: Box.h:155
lsst::sphgeom::NormalizedAngleInterval::isEmpty
bool isEmpty() const
Definition: NormalizedAngleInterval.h:126
lsst::sphgeom::Box::intersects
bool intersects(LonLat const &x) const
Definition: Box.h:194
lsst::sphgeom::Interval::clipTo
Interval & clipTo(Scalar x)
Definition: Interval.h:159