lsst.sphgeom gbd998247f1+585e252eca
Loading...
Searching...
No Matches
Box.h
Go to the documentation of this file.
1/*
2 * This file is part of sphgeom.
3 *
4 * Developed for the LSST Data Management System.
5 * This product includes software developed by the LSST Project
6 * (http://www.lsst.org).
7 * See the COPYRIGHT file at the top-level directory of this distribution
8 * for details of code ownership.
9 *
10 * This software is dual licensed under the GNU General Public License and also
11 * under a 3-clause BSD license. Recipients may choose which of these licenses
12 * to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
13 * respectively. If you choose the GPL option then the following text applies
14 * (but note that there is still no warranty even if you opt for BSD instead):
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29
30#ifndef LSST_SPHGEOM_BOX_H_
31#define LSST_SPHGEOM_BOX_H_
32
36
37#include <iosfwd>
38
39#include "AngleInterval.h"
40#include "LonLat.h"
42#include "Region.h"
43#include "UnitVector3d.h"
44
45
46namespace lsst {
47namespace sphgeom {
48
61class Box : public Region {
62public:
63 static constexpr uint8_t TYPE_CODE = 'b';
64
65 // Factory functions
66 static Box fromDegrees(double lon1, double lat1, double lon2, double lat2) {
67 return Box(NormalizedAngleInterval::fromDegrees(lon1, lon2),
68 AngleInterval::fromDegrees(lat1, lat2));
69 }
70
71 static Box fromRadians(double lon1, double lat1, double lon2, double lat2) {
72 return Box(NormalizedAngleInterval::fromRadians(lon1, lon2),
73 AngleInterval::fromRadians(lat1, lat2));
74 }
75
76 static Box empty() { return Box(); }
77
78 static Box full() { return Box(allLongitudes(), allLatitudes()); }
79
85
89 return NormalizedAngleInterval::full();
90 }
91
95 return AngleInterval(Angle(-0.5 * PI), Angle(0.5 * PI));
96 }
97
99 Box() {}
100
102 explicit Box(LonLat const & p) :
103 _lon(p.getLon()),
104 _lat(p.getLat())
105 {
106 _enforceInvariants();
107 }
108
112 Box(LonLat const & p1, LonLat const & p2) :
113 _lon(p1.getLon(), p2.getLon()),
114 _lat(p1.getLat(), p2.getLat())
115 {
116 _enforceInvariants();
117 }
118
121 Box(LonLat const & p, Angle w, Angle h) :
122 _lon(NormalizedAngleInterval(p.getLon()).dilatedBy(w)),
123 _lat(AngleInterval(p.getLat()).dilatedBy(h))
124 {
125 _enforceInvariants();
126 }
127
130 Box(NormalizedAngleInterval const & lon, AngleInterval const & lat) :
131 _lon(lon),
132 _lat(lat)
133 {
134 _enforceInvariants();
135 }
136
138 bool operator==(Box const & b) const {
139 return _lon == b._lon && _lat == b._lat;
140 }
141
142 bool operator!=(Box const & b) const { return !(*this == b); }
143
145 bool operator==(LonLat const & p) const {
146 return _lat == p.getLat() && _lon == p.getLon();
147 }
148
149 bool operator!=(LonLat const & p) const { return !(*this == p); }
150
152 NormalizedAngleInterval const & getLon() const { return _lon; }
153
155 AngleInterval const & getLat() const { return _lat; }
156
158 bool isEmpty() const { return _lat.isEmpty(); }
159
162 bool isFull() const { return _lon.isFull() && _lat == allLatitudes(); }
163
167 return LonLat(_lon.getCenter(), _lat.getCenter());
168 }
169
172 NormalizedAngle getWidth() const { return _lon.getSize(); }
173
176 Angle getHeight() const { return _lat.getSize(); }
177
181 bool contains(LonLat const & x) const {
182 return _lat.contains(x.getLat()) && _lon.contains(x.getLon());
183 }
184
185 bool contains(Box const & x) const {
186 return _lat.contains(x._lat) && _lon.contains(x._lon);
187 }
189
193 bool isDisjointFrom(LonLat const & x) const { return !intersects(x); }
194
195 bool isDisjointFrom(Box const & x) const { return !intersects(x); }
197
201 bool intersects(LonLat const & x) const {
202 return _lat.intersects(x.getLat()) && _lon.intersects(x.getLon());
203 }
204
205 bool intersects(Box const & x) const {
206 return _lat.intersects(x._lat) && _lon.intersects(x._lon);
207 }
209
213 bool isWithin(LonLat const & x) const {
214 return _lat.isWithin(x.getLat()) && _lon.isWithin(x.getLon());
215 }
216
217 bool isWithin(Box const & x) const {
218 return _lat.isWithin(x._lat) && _lon.isWithin(x._lon);
219 }
221
224 Box & clipTo(LonLat const & x) {
225 _lon.clipTo(x.getLon());
226 _lat.clipTo(x.getLat());
227 _enforceInvariants();
228 return *this;
229 }
230
234 Box & clipTo(Box const & x) {
235 _lon.clipTo(x.getLon());
236 _lat.clipTo(x.getLat());
237 _enforceInvariants();
238 return *this;
239 }
240
242 Box clippedTo(LonLat const & x) const { return Box(*this).clipTo(x); }
243
247 Box clippedTo(Box const & x) const { return Box(*this).clipTo(x); }
248
253 Box & expandTo(LonLat const & x) {
254 _lon.expandTo(x.getLon());
255 _lat.expandTo(x.getLat());
256 return *this;
257 }
258
259 Box & expandTo(Box const & x) {
260 _lon.expandTo(x.getLon());
261 _lat.expandTo(x.getLat());
262 return *this;
263 }
265
270 Box expandedTo(LonLat const & x) const { return Box(*this).expandTo(x); }
271 Box expandedTo(Box const & x) const { return Box(*this).expandTo(x); }
273
279 Box & dilateBy(Angle r);
280 Box dilatedBy(Angle r) const { return Box(*this).dilateBy(r); }
281
297 Box & dilateBy(Angle w, Angle h);
298 Box dilatedBy(Angle w, Angle h) const { return Box(*this).dilateBy(w, h); }
299 Box & erodeBy(Angle r) { return dilateBy(-r); }
300 Box & erodeBy(Angle w, Angle h) { return dilateBy(-w, -h); }
301 Box erodedBy(Angle r) const { return dilatedBy(-r); }
302 Box erodedBy(Angle w, Angle h) const { return dilatedBy(-w, -h); }
303
304 Relationship relate(LonLat const & p) const { return relate(Box(p)); }
305
307 double getArea() const;
308
309 // Region interface
310 std::unique_ptr<Region> clone() const override {
311 return std::unique_ptr<Box>(new Box(*this));
312 }
313
314 Box getBoundingBox() const override { return *this; }
315 Box3d getBoundingBox3d() const override;
316 Circle getBoundingCircle() const override;
317
318 bool contains(UnitVector3d const & v) const override {
319 return contains(LonLat(v));
320 }
321
322 using Region::contains;
323
324 Relationship relate(Region const & r) const override {
325 // Dispatch on the type of r.
326 return invert(r.relate(*this));
327 }
328
329 Relationship relate(Box const & b) const override {
330 Relationship r1 = _lon.relate(b._lon);
331 Relationship r2 = _lat.relate(b._lat);
332 // If the box longitude or latitude intervals are disjoint, then the
333 // boxes are disjoint. The other spatial relationships must hold for
334 // both the longitude and latitude intervals in order to hold for the
335 // boxes.
336 return ((r1 & r2) & (CONTAINS | WITHIN)) | ((r1 | r2) & DISJOINT);
337 }
338
339 Relationship relate(Circle const &) const override;
340 Relationship relate(ConvexPolygon const &) const override;
341 Relationship relate(Ellipse const &) const override;
342
343 std::vector<uint8_t> encode() const override;
344
347 static std::unique_ptr<Box> decode(std::vector<uint8_t> const & s) {
348 return decode(s.data(), s.size());
349 }
350 static std::unique_ptr<Box> decode(uint8_t const * buffer, size_t n);
352
353private:
354 static constexpr size_t ENCODED_SIZE = 33;
355
356 void _enforceInvariants() {
357 // Make sure that _lat ⊆ [-π/2, π/2].
358 _lat.clipTo(allLatitudes());
359 // Make sure that both longitude and latitude intervals are
360 // empty, or neither is. This simplifies the implementation
361 // of the spatial relation tests.
362 if (_lat.isEmpty()) {
364 } else if (_lon.isEmpty()) {
365 _lat = AngleInterval();
366 }
367 }
368
369 NormalizedAngleInterval _lon;
370 AngleInterval _lat;
371};
372
373std::ostream & operator<<(std::ostream &, Box const &);
374
375}} // namespace lsst::sphgeom
376
377#endif // LSST_SPHGEOM_BOX_H_
This file defines a class for representing angle intervals.
This file contains a class representing spherical coordinates.
This file declares a class representing closed intervals of normalized angles, i.e....
This file defines an interface for spherical regions.
This file declares a class for representing unit vectors in ℝ³.
Definition Angle.h:50
AngleInterval represents closed intervals of arbitrary angles.
Definition AngleInterval.h:47
Definition Box3d.h:49
Definition Box.h:61
Box clippedTo(LonLat const &x) const
clippedTo returns the intersection of this box and x.
Definition Box.h:242
Box getBoundingBox() const override
getBoundingBox returns a bounding-box for this region.
Definition Box.h:314
bool operator==(LonLat const &p) const
A box is equal to a point p if it contains only p.
Definition Box.h:145
AngleInterval const & getLat() const
getLat returns the latitude interval of this box.
Definition Box.h:155
static NormalizedAngle halfWidthForCircle(Angle r, Angle lat)
Definition Box.cc:50
Box()
This constructor creates an empty box.
Definition Box.h:99
std::vector< uint8_t > encode() const override
Definition Box.cc:454
NormalizedAngle getWidth() const
Definition Box.h:172
double getArea() const
getArea returns the area of this box in steradians.
Definition Box.cc:122
Box3d getBoundingBox3d() const override
getBoundingBox3d returns a 3-dimensional bounding-box for this region.
Definition Box.cc:134
Box expandedTo(LonLat const &x) const
Definition Box.h:270
bool operator==(Box const &b) const
Two boxes are equal if they contain the same points.
Definition Box.h:138
Box(LonLat const &p1, LonLat const &p2)
Definition Box.h:112
NormalizedAngleInterval const & getLon() const
getLon returns the longitude interval of this box.
Definition Box.h:152
bool contains(UnitVector3d const &v) const override
contains tests whether the given unit vector is inside this region.
Definition Box.h:318
static std::unique_ptr< Box > decode(std::vector< uint8_t > const &s)
Definition Box.h:347
bool isDisjointFrom(LonLat const &x) const
Definition Box.h:193
Box(LonLat const &p)
This constructor creates a box containing a single point.
Definition Box.h:102
bool isFull() const
Definition Box.h:162
Box & dilateBy(Angle r)
Definition Box.cc:85
Angle getHeight() const
Definition Box.h:176
LonLat getCenter() const
Definition Box.h:166
Box(LonLat const &p, Angle w, Angle h)
Definition Box.h:121
std::unique_ptr< Region > clone() const override
clone returns a deep copy of this region.
Definition Box.h:310
static NormalizedAngleInterval allLongitudes()
Definition Box.h:88
Box & clipTo(Box const &x)
Definition Box.h:234
Box(NormalizedAngleInterval const &lon, AngleInterval const &lat)
Definition Box.h:130
bool isWithin(LonLat const &x) const
Definition Box.h:213
Relationship relate(Region const &r) const override
Definition Box.h:324
Box clippedTo(Box const &x) const
Definition Box.h:247
Box & expandTo(LonLat const &x)
Definition Box.h:253
static AngleInterval allLatitudes()
Definition Box.h:94
bool contains(LonLat const &x) const
Definition Box.h:181
bool isEmpty() const
isEmpty returns true if this box does not contain any points.
Definition Box.h:158
Box & clipTo(LonLat const &x)
Definition Box.h:224
bool intersects(LonLat const &x) const
Definition Box.h:201
Circle getBoundingCircle() const override
getBoundingCircle returns a bounding-circle for this region.
Definition Box.cc:194
Definition Circle.h:53
bool isWithin(Scalar x) const
Definition Interval.h:147
Scalar getSize() const
Definition Interval.h:100
Interval & clipTo(Scalar x)
Definition Interval.h:166
bool isEmpty() const
isEmpty returns true if this interval does not contain any points.
Definition Interval.h:90
Relationship relate(Scalar x) const
Definition Interval.h:256
bool intersects(Scalar x) const
Definition Interval.h:137
Scalar getCenter() const
Definition Interval.h:96
Interval & expandTo(Scalar x)
Definition Interval.h:199
bool contains(Scalar x) const
Definition Interval.h:105
Definition LonLat.h:55
Definition NormalizedAngle.h:50
Definition NormalizedAngleInterval.h:64
bool isFull() const
isFull returns true if this interval contains all normalized angles.
Definition NormalizedAngleInterval.h:136
NormalizedAngleInterval & clipTo(NormalizedAngle x)
clipTo shrinks this interval until all its points are in x.
Definition NormalizedAngleInterval.h:210
NormalizedAngle getCenter() const
Definition NormalizedAngleInterval.h:146
Relationship relate(NormalizedAngle x) const
Definition NormalizedAngleInterval.cc:95
NormalizedAngle getSize() const
Definition NormalizedAngleInterval.h:152
NormalizedAngleInterval & expandTo(NormalizedAngle x)
Definition NormalizedAngleInterval.cc:196
bool intersects(NormalizedAngle x) const
Definition NormalizedAngleInterval.h:180
bool isWithin(NormalizedAngle x) const
Definition NormalizedAngleInterval.h:192
bool contains(NormalizedAngle x) const
Definition NormalizedAngleInterval.h:157
bool isEmpty() const
Definition NormalizedAngleInterval.h:133
Definition Region.h:86
virtual Relationship relate(Region const &) const =0
virtual bool contains(UnitVector3d const &) const =0
contains tests whether the given unit vector is inside this region.
Definition UnitVector3d.h:62
Relationship invert(Relationship r)
Definition Relationship.h:62
std::bitset< 3 > Relationship
Relationship describes how two sets are related.
Definition Relationship.h:42