LSST Applications g063fba187b+cac8b7c890,g0f08755f38+6aee506743,g1653933729+a8ce1bb630,g168dd56ebc+a8ce1bb630,g1a2382251a+b4475c5878,g1dcb35cd9c+8f9bc1652e,g20f6ffc8e0+6aee506743,g217e2c1bcf+73dee94bd0,g28da252d5a+1f19c529b9,g2bbee38e9b+3f2625acfc,g2bc492864f+3f2625acfc,g3156d2b45e+6e55a43351,g32e5bea42b+1bb94961c2,g347aa1857d+3f2625acfc,g35bb328faa+a8ce1bb630,g3a166c0a6a+3f2625acfc,g3e281a1b8c+c5dd892a6c,g3e8969e208+a8ce1bb630,g414038480c+5927e1bc1e,g41af890bb2+8a9e676b2a,g7af13505b9+809c143d88,g80478fca09+6ef8b1810f,g82479be7b0+f568feb641,g858d7b2824+6aee506743,g89c8672015+f4add4ffd5,g9125e01d80+a8ce1bb630,ga5288a1d22+2903d499ea,gb58c049af0+d64f4d3760,gc28159a63d+3f2625acfc,gcab2d0539d+b12535109e,gcf0d15dbbd+46a3f46ba9,gda6a2b7d83+46a3f46ba9,gdaeeff99f8+1711a396fd,ge79ae78c31+3f2625acfc,gef2f8181fd+0a71e47438,gf0baf85859+c1f95f4921,gfa517265be+6aee506743,gfa999e8aa5+17cd334064,w.2024.51
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Static Public Attributes | Static Protected Member Functions | List of all members
lsst::sphgeom::Box Class Reference

Box represents a rectangle in spherical coordinate space that contains its boundary. More...

#include <Box.h>

Inheritance diagram for lsst::sphgeom::Box:
lsst::sphgeom::Region

Public Member Functions

 Box ()
 This constructor creates an empty box.
 
 Box (LonLat const &p)
 This constructor creates a box containing a single point.
 
 Box (LonLat const &p1, LonLat const &p2)
 This constructor creates a box spanning the longitude interval [p1.getLon(), p2.getLon()] and latitude interval [p1.getLat(), p2.getLat()].
 
 Box (LonLat const &p, Angle w, Angle h)
 This constructor creates a box with center p, half-width (in longitude angle) w and half-height (in latitude angle) h.
 
 Box (NormalizedAngleInterval const &lon, AngleInterval const &lat)
 This constructor creates a box spanning the given longitude and latitude intervals.
 
bool operator== (Box const &b) const
 Two boxes are equal if they contain the same points.
 
bool operator!= (Box const &b) const
 
bool operator== (LonLat const &p) const
 A box is equal to a point p if it contains only p.
 
bool operator!= (LonLat const &p) const
 
NormalizedAngleInterval const & getLon () const
 getLon returns the longitude interval of this box.
 
AngleInterval const & getLat () const
 getLat returns the latitude interval of this box.
 
bool isEmpty () const override
 isEmpty returns true if this box does not contain any points.
 
bool isFull () const
 isFull returns true if this box contains all points on the unit sphere.
 
LonLat getCenter () const
 getCenter returns the center of this box.
 
NormalizedAngle getWidth () const
 getWidth returns the width in longitude angle of this box.
 
Angle getHeight () const
 getHeight returns the height in latitude angle of this box.
 
BoxclipTo (LonLat const &x)
 clipTo shrinks this box until it contains only x.
 
BoxclipTo (Box const &x)
 x.clipTo(y) sets x to the smallest box containing the intersection of x and y.
 
Box clippedTo (LonLat const &x) const
 clippedTo returns the intersection of this box and x.
 
Box clippedTo (Box const &x) const
 clippedTo returns the smallest box containing the intersection of this box and x.
 
BoxdilateBy (Angle r)
 dilateBy minimally expands this Box to include all points within angular separation r of its boundary.
 
Box dilatedBy (Angle r) const
 
BoxdilateBy (Angle w, Angle h)
 dilateBy morphologically dilates or erodes the longitude interval of this box by w, and the latitude interval of this box by h.
 
Box dilatedBy (Angle w, Angle h) const
 
BoxerodeBy (Angle r)
 
BoxerodeBy (Angle w, Angle h)
 
Box erodedBy (Angle r) const
 
Box erodedBy (Angle w, Angle h) const
 
Relationship relate (LonLat const &p) const
 
double getArea () const
 getArea returns the area of this box in steradians.
 
std::unique_ptr< Regionclone () const override
 clone returns a deep copy of this region.
 
Box getBoundingBox () const override
 getBoundingBox returns a bounding-box for this region.
 
Box3d getBoundingBox3d () const override
 getBoundingBox3d returns a 3-dimensional bounding-box for this region.
 
Circle getBoundingCircle () const override
 getBoundingCircle returns a bounding-circle for this region.
 
bool contains (UnitVector3d const &v) const override
 contains tests whether the given unit vector is inside this region.
 
Relationship relate (Region const &r) const override
 
Relationship relate (Box const &b) const override
 
Relationship relate (Circle const &) const override
 
Relationship relate (ConvexPolygon const &) const override
 
Relationship relate (Ellipse const &) const override
 
TriState overlaps (Region const &other) const override
 
TriState overlaps (Box const &) const override
 
TriState overlaps (Circle const &) const override
 
TriState overlaps (ConvexPolygon const &) const override
 
TriState overlaps (Ellipse const &) const override
 
std::vector< std::uint8_tencode () const override
 encode serializes this region into an opaque byte string.
 
virtual bool contains (UnitVector3d const &) const=0
 contains tests whether the given unit vector is inside this region.
 
bool contains (double x, double y, double z) const
 contains tests whether the unit vector defined by the given (not necessarily normalized) coordinates is inside this region.
 
bool contains (double lon, double lat) const
 contains tests whether the unit vector defined by the given longitude and latitude coordinates (in radians) is inside this region.
 
bool contains (LonLat const &x) const
 
bool contains (Box const &x) const
 
bool isDisjointFrom (LonLat const &x) const
 
bool isDisjointFrom (Box const &x) const
 
bool intersects (LonLat const &x) const
 
bool intersects (Box const &x) const
 
bool isWithin (LonLat const &x) const
 
bool isWithin (Box const &x) const
 
BoxexpandTo (LonLat const &x)
 
BoxexpandTo (Box const &x)
 
Box expandedTo (LonLat const &x) const
 
Box expandedTo (Box const &x) const
 

Static Public Member Functions

static Box fromDegrees (double lon1, double lat1, double lon2, double lat2)
 
static Box fromRadians (double lon1, double lat1, double lon2, double lat2)
 
static Box empty ()
 
static Box full ()
 
static NormalizedAngle halfWidthForCircle (Angle r, Angle lat)
 halfWidthForCircle computes the half-width of bounding boxes for circles with radius r and centers at the given latitude.
 
static NormalizedAngleInterval allLongitudes ()
 allLongitudes returns a normalized angle interval containing all valid longitude angles.
 
static AngleInterval allLatitudes ()
 allLatitudes returns an angle interval containing all valid latitude angles.
 
static std::vector< std::unique_ptr< Region > > getRegions (Region const &region)
 getRegions returns a vector of Region.
 
static std::unique_ptr< Boxdecode (std::vector< std::uint8_t > const &s)
 
static std::unique_ptr< Boxdecode (std::uint8_t const *buffer, size_t n)
 
static std::unique_ptr< RegiondecodeBase64 (std::string const &s)
 
static std::unique_ptr< RegiondecodeBase64 (std::string_view const &s)
 
static TriState decodeOverlapsBase64 (std::string const &s)
 
static TriState decodeOverlapsBase64 (std::string_view const &s)
 

Static Public Attributes

static constexpr std::uint8_t TYPE_CODE = 'b'
 

Static Protected Member Functions

static TriState _relationship_to_overlaps (Relationship r)
 

Detailed Description

Box represents a rectangle in spherical coordinate space that contains its boundary.

A box can be empty or full (equal to the entire unit sphere), and may contain just a single point. Besides the usual rectangular regions, a box can also represent polar caps or annuli (i.e. when the box spans all longitudes).

For any instance b of this class, the following properties hold:

Definition at line 62 of file Box.h.

Constructor & Destructor Documentation

◆ Box() [1/5]

lsst::sphgeom::Box::Box ( )
inline

This constructor creates an empty box.

Definition at line 100 of file Box.h.

100{}

◆ Box() [2/5]

lsst::sphgeom::Box::Box ( LonLat const & p)
inlineexplicit

This constructor creates a box containing a single point.

Definition at line 103 of file Box.h.

103 :
104 _lon(p.getLon()),
105 _lat(p.getLat())
106 {
107 _enforceInvariants();
108 }

◆ Box() [3/5]

lsst::sphgeom::Box::Box ( LonLat const & p1,
LonLat const & p2 )
inline

This constructor creates a box spanning the longitude interval [p1.getLon(), p2.getLon()] and latitude interval [p1.getLat(), p2.getLat()].

Definition at line 113 of file Box.h.

113 :
114 _lon(p1.getLon(), p2.getLon()),
115 _lat(p1.getLat(), p2.getLat())
116 {
117 _enforceInvariants();
118 }

◆ Box() [4/5]

lsst::sphgeom::Box::Box ( LonLat const & p,
Angle w,
Angle h )
inline

This constructor creates a box with center p, half-width (in longitude angle) w and half-height (in latitude angle) h.

Definition at line 122 of file Box.h.

122 :
123 _lon(NormalizedAngleInterval(p.getLon()).dilatedBy(w)),
124 _lat(AngleInterval(p.getLat()).dilatedBy(h))
125 {
126 _enforceInvariants();
127 }
double w
Definition CoaddPsf.cc:70

◆ Box() [5/5]

lsst::sphgeom::Box::Box ( NormalizedAngleInterval const & lon,
AngleInterval const & lat )
inline

This constructor creates a box spanning the given longitude and latitude intervals.

Definition at line 131 of file Box.h.

131 :
132 _lon(lon),
133 _lat(lat)
134 {
135 _enforceInvariants();
136 }

Member Function Documentation

◆ _relationship_to_overlaps()

static TriState lsst::sphgeom::Region::_relationship_to_overlaps ( Relationship r)
inlinestaticprotectedinherited

Definition at line 206 of file Region.h.

206 {
207 // `relate` returns exact relation when specific bit is set, if it is
208 // not then relation may be true or not.
209 if ((r & DISJOINT) == DISJOINT) {
210 return TriState(false);
211 }
212 if ((r & (WITHIN | CONTAINS)).any()) {
213 return TriState(true);
214 }
215 return TriState();
216 }
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.

◆ allLatitudes()

static AngleInterval lsst::sphgeom::Box::allLatitudes ( )
inlinestatic

allLatitudes returns an angle interval containing all valid latitude angles.

Definition at line 95 of file Box.h.

95 {
96 return AngleInterval(Angle(-0.5 * PI), Angle(0.5 * PI));
97 }
constexpr double PI
Definition constants.h:43

◆ allLongitudes()

static NormalizedAngleInterval lsst::sphgeom::Box::allLongitudes ( )
inlinestatic

allLongitudes returns a normalized angle interval containing all valid longitude angles.

Definition at line 89 of file Box.h.

89 {
91 }
static NormalizedAngleInterval full()

◆ clippedTo() [1/2]

Box lsst::sphgeom::Box::clippedTo ( Box const & x) const
inline

clippedTo returns the smallest box containing the intersection of this box and x.

The result is not always unique, and x.clippedTo(y) is not guaranteed to equal y.clippedTo(x).

Definition at line 248 of file Box.h.

248{ return Box(*this).clipTo(x); }
Box()
This constructor creates an empty box.
Definition Box.h:100

◆ clippedTo() [2/2]

Box lsst::sphgeom::Box::clippedTo ( LonLat const & x) const
inline

clippedTo returns the intersection of this box and x.

Definition at line 243 of file Box.h.

243{ return Box(*this).clipTo(x); }

◆ clipTo() [1/2]

Box & lsst::sphgeom::Box::clipTo ( Box const & x)
inline

x.clipTo(y) sets x to the smallest box containing the intersection of x and y.

The result is not always unique, and x.clipTo(y) is not guaranteed to equal y.clipTo(x).

Definition at line 235 of file Box.h.

235 {
236 _lon.clipTo(x.getLon());
237 _lat.clipTo(x.getLat());
238 _enforceInvariants();
239 return *this;
240 }
Interval & clipTo(Scalar x)
Definition Interval.h:166
NormalizedAngleInterval & clipTo(NormalizedAngle x)
clipTo shrinks this interval until all its points are in x.

◆ clipTo() [2/2]

Box & lsst::sphgeom::Box::clipTo ( LonLat const & x)
inline

clipTo shrinks this box until it contains only x.

If this box does not contain x, it is emptied.

Definition at line 225 of file Box.h.

225 {
226 _lon.clipTo(x.getLon());
227 _lat.clipTo(x.getLat());
228 _enforceInvariants();
229 return *this;
230 }

◆ clone()

std::unique_ptr< Region > lsst::sphgeom::Box::clone ( ) const
inlineoverridevirtual

clone returns a deep copy of this region.

Implements lsst::sphgeom::Region.

Definition at line 311 of file Box.h.

311 {
312 return std::unique_ptr<Box>(new Box(*this));
313 }

◆ contains() [1/6]

bool lsst::sphgeom::Box::contains ( Box const & x) const
inline

contains returns true if the intersection of this box and x is equal to x.

Definition at line 186 of file Box.h.

186 {
187 return _lat.contains(x._lat) && _lon.contains(x._lon);
188 }
bool contains(Scalar x) const
Definition Interval.h:105

◆ contains() [2/6]

bool lsst::sphgeom::Region::contains ( double lon,
double lat ) const

contains tests whether the unit vector defined by the given longitude and latitude coordinates (in radians) is inside this region.

Definition at line 117 of file Region.cc.

54 {
55 return contains(UnitVector3d(LonLat::fromRadians(lon, lat)));
56}
bool contains(LonLat const &x) const
Definition Box.h:182
static LonLat fromRadians(double lon, double lat)
Definition LonLat.h:62

◆ contains() [3/6]

bool lsst::sphgeom::Region::contains ( double x,
double y,
double z ) const

contains tests whether the unit vector defined by the given (not necessarily normalized) coordinates is inside this region.

Definition at line 113 of file Region.cc.

50 {
51 return contains(UnitVector3d(x, y, z));
52}
double z
Definition Match.cc:44
int y
Definition SpanSet.cc:48

◆ contains() [4/6]

bool lsst::sphgeom::Box::contains ( LonLat const & x) const
inline

contains returns true if the intersection of this box and x is equal to x.

Definition at line 182 of file Box.h.

182 {
183 return _lat.contains(x.getLat()) && _lon.contains(x.getLon());
184 }

◆ contains() [5/6]

virtual bool lsst::sphgeom::Region::contains ( UnitVector3d const & ) const
virtual

contains tests whether the given unit vector is inside this region.

Implements lsst::sphgeom::Region.

◆ contains() [6/6]

bool lsst::sphgeom::Box::contains ( UnitVector3d const & ) const
inlineoverridevirtual

contains tests whether the given unit vector is inside this region.

Implements lsst::sphgeom::Region.

Definition at line 319 of file Box.h.

319 {
320 return contains(LonLat(v));
321 }

◆ decode() [1/2]

std::unique_ptr< Box > lsst::sphgeom::Box::decode ( std::uint8_t const * buffer,
size_t n )
static

decode deserializes a Box from a byte string produced by encode.

Definition at line 486 of file Box.cc.

486 {
487 if (buffer == nullptr || n != ENCODED_SIZE || *buffer != TYPE_CODE) {
488 throw std::runtime_error("Byte-string is not an encoded Box");
489 }
490 std::unique_ptr<Box> box(new Box);
491 ++buffer;
492 double a = decodeDouble(buffer); buffer += 8;
493 double b = decodeDouble(buffer); buffer += 8;
495 a = decodeDouble(buffer); buffer += 8;
496 b = decodeDouble(buffer); buffer += 8;
497 box->_lat = AngleInterval::fromRadians(a, b);
498 box->_enforceInvariants();
499 return box;
500}
table::Key< int > b
static AngleInterval fromRadians(double x, double y)
static constexpr std::uint8_t TYPE_CODE
Definition Box.h:64
static NormalizedAngleInterval fromRadians(double a, double b)
double decodeDouble(std::uint8_t const *buffer)
decodeDouble extracts an IEEE double from the 8 byte little-endian byte sequence in buffer.
Definition codec.h:77

◆ decode() [2/2]

static std::unique_ptr< Box > lsst::sphgeom::Box::decode ( std::vector< std::uint8_t > const & s)
inlinestatic

decode deserializes a Box from a byte string produced by encode.

Definition at line 356 of file Box.h.

356 {
357 return decode(s.data(), s.size());
358 }
static std::unique_ptr< Box > decode(std::vector< std::uint8_t > const &s)
Definition Box.h:356

◆ decodeBase64() [1/2]

static std::unique_ptr< Region > lsst::sphgeom::Region::decodeBase64 ( std::string const & s)
inlinestaticinherited

decodeBase64 deserializes a Region from an ASCII string produced by encode and then base64-encoding that result.

This method also interprets ':' as a delimiter for the elements of a UnionRegion, to support cases where a union of region is constructed server-side in a database as a concatenation with that delimiter.

Definition at line 176 of file Region.h.

176 {
177 return decodeBase64(s);
178 }
static std::unique_ptr< Region > decodeBase64(std::string const &s)
Definition Region.h:176

◆ decodeBase64() [2/2]

std::unique_ptr< Region > lsst::sphgeom::Region::decodeBase64 ( std::string_view const & s)
staticinherited

decodeBase64 deserializes a Region from an ASCII string produced by encode and then base64-encoding that result.

This method also interprets ':' as a delimiter for the elements of a UnionRegion, to support cases where a union of region is constructed server-side in a database as a concatenation with that delimiter.

Definition at line 93 of file Region.cc.

93 {
94 if (s.empty()) {
95 return std::unique_ptr<UnionRegion>(new UnionRegion({}));
96 }
97 auto region_begin = s.begin();
98 auto region_end = std::find(s.begin(), s.end(), ':');
99 if (region_end != s.end()) {
101 while (region_end != s.end()) {
102 auto bytes = base64::decode_into<std::vector<std::uint8_t>>(region_begin, region_end);
103 union_args.push_back(decode(bytes));
104 region_begin = region_end;
105 ++region_begin;
106 region_end = std::find(region_begin, s.end(), ':');
107 }
108 auto bytes = base64::decode_into<std::vector<std::uint8_t>>(region_begin, region_end);
109 union_args.push_back(decode(bytes));
110 return std::unique_ptr<UnionRegion>(new UnionRegion(std::move(union_args)));
111 } else {
112 auto bytes = base64::decode_into<std::vector<std::uint8_t>>(region_begin, region_end);
113 return decode(bytes);
114 }
115}
table::Key< table::Array< std::uint8_t > > bytes
Definition python.h:135
static std::unique_ptr< Region > decode(std::vector< std::uint8_t > const &s)
Definition Region.h:162
T find(T... args)
T move(T... args)
T push_back(T... args)

◆ decodeOverlapsBase64() [1/2]

static TriState lsst::sphgeom::Region::decodeOverlapsBase64 ( std::string const & s)
inlinestaticinherited

decodeOverlapsBase64 evaluates an encoded overlap expression.

A single overlap expression is formed by concatenating a pair of base64-encoded regions (Region::encode then base64 encoding) with '&' as the delimiter. Multiple such pairwise overlap expressions can then be concatenated with '|' as the delimiter to form the logical OR.

Definition at line 190 of file Region.h.

190 {
191 return decodeOverlapsBase64(s);
192 }
static TriState decodeOverlapsBase64(std::string const &s)
Definition Region.h:190

◆ decodeOverlapsBase64() [2/2]

TriState lsst::sphgeom::Region::decodeOverlapsBase64 ( std::string_view const & s)
staticinherited

decodeOverlapsBase64 evaluates an encoded overlap expression.

A single overlap expression is formed by concatenating a pair of base64-encoded regions (Region::encode then base64 encoding) with '&' as the delimiter. Multiple such pairwise overlap expressions can then be concatenated with '|' as the delimiter to form the logical OR.

Definition at line 117 of file Region.cc.

117 {
118 TriState result(false);
119 if (s.empty()) {
120 // False makes the most sense as the limit of a logical OR of zero
121 // terms (e.g. `any([])` in Python).
122 return result;
123 }
124 auto begin = s.begin();
125 while (result != true) { // if result is known to be true, we're done.
126 auto mid = std::find(begin, s.end(), '&');
127 if (mid == s.end()) {
128 throw std::runtime_error("No '&' found in encoded overlap expression term.");
129 }
130 auto a = Region::decode(base64::decode_into<std::vector<std::uint8_t>>(begin, mid));
131 ++mid;
132 auto end = std::find(mid, s.end(), '|');
133 auto b = Region::decode(base64::decode_into<std::vector<std::uint8_t>>(mid, end));
134 result = result | a->overlaps(*b);
135 if (end == s.end()) {
136 break;
137 } else {
138 begin = end;
139 ++begin;
140 }
141 }
142 return result;
143}
py::object result
Definition _schema.cc:429
int end
T begin(T... args)

◆ dilateBy() [1/2]

Box & lsst::sphgeom::Box::dilateBy ( Angle r)

dilateBy minimally expands this Box to include all points within angular separation r of its boundary.

If this box is empty or full, or if r is non-positive, there is no effect.

Definition at line 85 of file Box.cc.

85 {
86 // The basic idea is to compute the union of the bounding boxes for all
87 // circles of opening angle r with centers inside this box.
88 //
89 // The bounding box for a circle of opening angle r with center latitude
90 // |δ| ≤ π/2 - r has height 2r.
91 //
92 // Given fixed r, the width of the bounding box for the circle centered at
93 // latitude δ grows monotonically with |δ| - for justification, see the
94 // derivation in halfWidthForCircle(). The maximum width is therefore
95 // attained when the circle is centered at one of the latitude angle
96 // boundaries of this box. If max(|δ|) ≥ π/2 - r, it is 2π.
97 //
98 // Dilating the longitude interval of this box by the maximum width and
99 // the latitude interval by r gives the desired result.
100 if (isEmpty() || isFull() || r <= Angle(0.0)) {
101 return *this;
102 }
103 Angle maxAbsLatitude = std::max(abs(_lat.getA()), abs(_lat.getB()));
104 NormalizedAngle w = halfWidthForCircle(r, maxAbsLatitude);
105 return dilateBy(w, r);
106}
static NormalizedAngle halfWidthForCircle(Angle r, Angle lat)
halfWidthForCircle computes the half-width of bounding boxes for circles with radius r and centers at...
Definition Box.cc:50
bool isFull() const
isFull returns true if this box contains all points on the unit sphere.
Definition Box.h:163
bool isEmpty() const override
isEmpty returns true if this box does not contain any points.
Definition Box.h:159
Box & dilateBy(Angle r)
dilateBy minimally expands this Box to include all points within angular separation r of its boundary...
Definition Box.cc:85
Scalar getA() const
getA returns the lower endpoint of this interval.
Definition Interval.h:83
Scalar getB() const
getB returns the upper endpoint of this interval.
Definition Interval.h:87
T max(T... args)
Angle abs(Angle const &a)
Definition Angle.h:113

◆ dilateBy() [2/2]

Box & lsst::sphgeom::Box::dilateBy ( Angle w,
Angle h )

dilateBy morphologically dilates or erodes the longitude interval of this box by w, and the latitude interval of this box by h.

If w is positive, the longitude interval is dilated by [-w,w]. If w is zero, the corresponding interval is not modified, and if it is negative, the longitude interval is eroded by [w,-w]. The action of h on the latitude interval is analogous.

If this box is empty or full, there is no effect. Furthermore, a box containing the north or south pole is not considered to have a latitude boundary there, so that eroding it will not necessarily remove the pole.

If the desired outcome is the bounding box of points within some angular separation r of this box, then dilateBy(r) must be called, not dilateBy(r, r).

Definition at line 108 of file Box.cc.

108 {
109 if (isEmpty() || isFull()) {
110 return *this;
111 }
112 _lon.dilateBy(w);
113 if (!h.isNan()) {
114 Angle a = (_lat.getA() > Angle(-0.5 * PI)) ? _lat.getA() - h : _lat.getA();
115 Angle b = (_lat.getB() < Angle(0.5 * PI)) ? _lat.getB() + h : _lat.getB();
116 _lat = AngleInterval(a, b);
117 }
118 _enforceInvariants();
119 return *this;
120}
NormalizedAngleInterval & dilateBy(Angle x)

◆ dilatedBy() [1/2]

Box lsst::sphgeom::Box::dilatedBy ( Angle r) const
inline

Definition at line 281 of file Box.h.

281{ return Box(*this).dilateBy(r); }

◆ dilatedBy() [2/2]

Box lsst::sphgeom::Box::dilatedBy ( Angle w,
Angle h ) const
inline

Definition at line 299 of file Box.h.

299{ return Box(*this).dilateBy(w, h); }

◆ empty()

static Box lsst::sphgeom::Box::empty ( )
inlinestatic

Definition at line 77 of file Box.h.

77{ return Box(); }

◆ encode()

std::vector< std::uint8_t > lsst::sphgeom::Box::encode ( ) const
overridevirtual

encode serializes this region into an opaque byte string.

Byte strings emitted by encode can be deserialized with decode.

Implements lsst::sphgeom::Region.

Definition at line 474 of file Box.cc.

474 {
477 buffer.reserve(ENCODED_SIZE);
478 buffer.push_back(tc);
479 encodeDouble(_lon.getA().asRadians(), buffer);
480 encodeDouble(_lon.getB().asRadians(), buffer);
481 encodeDouble(_lat.getA().asRadians(), buffer);
482 encodeDouble(_lat.getB().asRadians(), buffer);
483 return buffer;
484}
double asRadians() const
asRadians returns the value of this angle in units of radians.
Definition Angle.h:92
double asRadians() const
asRadians returns the value of this angle in units of radians.
NormalizedAngle getA() const
getA returns the first endpoint of this interval.
NormalizedAngle getB() const
getB returns the second endpoint of this interval.
void encodeDouble(double item, std::vector< std::uint8_t > &buffer)
encodeDouble appends an IEEE double in little-endian byte order to the end of buffer.
Definition codec.h:57
T reserve(T... args)

◆ erodeBy() [1/2]

Box & lsst::sphgeom::Box::erodeBy ( Angle r)
inline

Definition at line 300 of file Box.h.

300{ return dilateBy(-r); }

◆ erodeBy() [2/2]

Box & lsst::sphgeom::Box::erodeBy ( Angle w,
Angle h )
inline

Definition at line 301 of file Box.h.

301{ return dilateBy(-w, -h); }

◆ erodedBy() [1/2]

Box lsst::sphgeom::Box::erodedBy ( Angle r) const
inline

Definition at line 302 of file Box.h.

302{ return dilatedBy(-r); }
Box dilatedBy(Angle r) const
Definition Box.h:281

◆ erodedBy() [2/2]

Box lsst::sphgeom::Box::erodedBy ( Angle w,
Angle h ) const
inline

Definition at line 303 of file Box.h.

303{ return dilatedBy(-w, -h); }

◆ expandedTo() [1/2]

Box lsst::sphgeom::Box::expandedTo ( Box const & x) const
inline

expandedTo returns the smallest box containing the union of this box and x. The result is not always unique, and x.expandedTo(y) is not guaranteed to equal y.expandedTo(x).

Definition at line 272 of file Box.h.

272{ return Box(*this).expandTo(x); }

◆ expandedTo() [2/2]

Box lsst::sphgeom::Box::expandedTo ( LonLat const & x) const
inline

expandedTo returns the smallest box containing the union of this box and x. The result is not always unique, and x.expandedTo(y) is not guaranteed to equal y.expandedTo(x).

Definition at line 271 of file Box.h.

271{ return Box(*this).expandTo(x); }

◆ expandTo() [1/2]

Box & lsst::sphgeom::Box::expandTo ( Box const & x)
inline

expandTo minimally expands this box to contain x. The result is not always unique, and x.expandTo(y) is not guaranteed to equal y.expandTo(x).

Definition at line 260 of file Box.h.

260 {
261 _lon.expandTo(x.getLon());
262 _lat.expandTo(x.getLat());
263 return *this;
264 }
Interval & expandTo(Scalar x)
Definition Interval.h:199
NormalizedAngleInterval & expandTo(NormalizedAngle x)

◆ expandTo() [2/2]

Box & lsst::sphgeom::Box::expandTo ( LonLat const & x)
inline

expandTo minimally expands this box to contain x. The result is not always unique, and x.expandTo(y) is not guaranteed to equal y.expandTo(x).

Definition at line 254 of file Box.h.

254 {
255 _lon.expandTo(x.getLon());
256 _lat.expandTo(x.getLat());
257 return *this;
258 }

◆ fromDegrees()

static Box lsst::sphgeom::Box::fromDegrees ( double lon1,
double lat1,
double lon2,
double lat2 )
inlinestatic

Definition at line 67 of file Box.h.

67 {
69 AngleInterval::fromDegrees(lat1, lat2));
70 }
static AngleInterval fromDegrees(double x, double y)
static NormalizedAngleInterval fromDegrees(double a, double b)

◆ fromRadians()

static Box lsst::sphgeom::Box::fromRadians ( double lon1,
double lat1,
double lon2,
double lat2 )
inlinestatic

Definition at line 72 of file Box.h.

72 {
74 AngleInterval::fromRadians(lat1, lat2));
75 }

◆ full()

static Box lsst::sphgeom::Box::full ( )
inlinestatic

Definition at line 79 of file Box.h.

79{ return Box(allLongitudes(), allLatitudes()); }
static NormalizedAngleInterval allLongitudes()
allLongitudes returns a normalized angle interval containing all valid longitude angles.
Definition Box.h:89
static AngleInterval allLatitudes()
allLatitudes returns an angle interval containing all valid latitude angles.
Definition Box.h:95

◆ getArea()

double lsst::sphgeom::Box::getArea ( ) const

getArea returns the area of this box in steradians.

Definition at line 122 of file Box.cc.

122 {
123 if (isEmpty()) {
124 return 0.0;
125 }
126 // Given a, b ∈ [-π/2, π/2] and a std::sin implementation that is not
127 // correctly rounded, b > a does not imply that std::sin(b) > std::sin(a).
128 // To avoid potentially returning a negative area, defensively take an
129 // absolute value.
130 double dz = sin(_lat.getB()) - sin(_lat.getA());
131 return std::fabs(_lon.getSize().asRadians() * dz);
132}
NormalizedAngle getSize() const
getSize returns the size (length, width) of this interval.
T fabs(T... args)
double sin(Angle const &a)
Definition Angle.h:109

◆ getBoundingBox()

Box lsst::sphgeom::Box::getBoundingBox ( ) const
inlineoverridevirtual

getBoundingBox returns a bounding-box for this region.

Implements lsst::sphgeom::Region.

Definition at line 315 of file Box.h.

315{ return *this; }

◆ getBoundingBox3d()

Box3d lsst::sphgeom::Box::getBoundingBox3d ( ) const
overridevirtual

getBoundingBox3d returns a 3-dimensional bounding-box for this region.

Implements lsst::sphgeom::Region.

Definition at line 134 of file Box.cc.

134 {
135 if (isEmpty()) {
136 return Box3d();
137 }
138 if (isFull()) {
140 }
141 double slata = sin(_lat.getA()), clata = cos(_lat.getA());
142 double slatb = sin(_lat.getB()), clatb = cos(_lat.getB());
143 double slona = sin(_lon.getA()), clona = cos(_lon.getA());
144 double slonb = sin(_lon.getB()), clonb = cos(_lon.getB());
145 // Compute the minimum/maximum x/y values of the box vertices.
146 double xmin = std::min(std::min(clona * clata, clonb * clata),
147 std::min(clona * clatb, clonb * clatb)) - 2.5 * EPSILON;
148 double xmax = std::max(std::max(clona * clata, clonb * clata),
149 std::max(clona * clatb, clonb * clatb)) + 2.5 * EPSILON;
150 double ymin = std::min(std::min(slona * clata, slonb * clata),
151 std::min(slona * clatb, slonb * clatb)) - 2.5 * EPSILON;
152 double ymax = std::max(std::max(slona * clata, slonb * clata),
153 std::max(slona * clatb, slonb * clatb)) + 2.5 * EPSILON;
154 // Compute the maximum latitude cosine of points in the box.
155 double mlc;
156 if (_lat.contains(Angle(0.0))) {
157 mlc = 1.0;
158 // The box intersects the equator - the x or y extrema of the box may be
159 // at the intersection of the box edge meridians with the equator.
160 xmin = std::min(xmin, std::min(clona, clonb) - EPSILON);
161 xmax = std::max(xmax, std::max(clona, clonb) + EPSILON);
162 ymin = std::min(ymin, std::min(slona, slonb) - EPSILON);
163 ymax = std::max(ymax, std::max(slona, slonb) + EPSILON);
164 } else {
165 // Note that clata and clatb are positive.
166 mlc = std::max(clata, clatb) + EPSILON;
167 }
168 // Check for extrema on the box edges parallel to the equator.
169 if (_lon.contains(NormalizedAngle(0.0))) {
170 xmax = std::max(xmax, mlc);
171 }
172 if (_lon.contains(NormalizedAngle(0.5 * PI))) {
173 ymax = std::max(ymax, mlc);
174 }
175 if (_lon.contains(NormalizedAngle(PI))) {
176 xmin = std::min(xmin, -mlc);
177 }
178 if (_lon.contains(NormalizedAngle(1.5 * PI))) {
179 ymin = std::min(ymin, -mlc);
180 }
181 // Clamp x/y extrema to [-1, 1]
182 xmin = std::max(-1.0, xmin);
183 xmax = std::min(1.0, xmax);
184 ymin = std::max(-1.0, ymin);
185 ymax = std::min(1.0, ymax);
186 // Compute z extrema.
187 double zmin = std::max(-1.0, slata - EPSILON);
188 double zmax = std::min(1.0, slatb + EPSILON);
189 return Box3d(Interval1d(xmin, xmax),
190 Interval1d(ymin, ymax),
191 Interval1d(zmin, zmax));
192}
int xmax
Definition SpanSet.cc:48
int xmin
Definition SpanSet.cc:48
static Box3d aroundUnitSphere()
aroundUnitSphere returns a minimal Box3d containing the unit sphere.
Definition Box3d.h:63
T min(T... args)
constexpr double EPSILON
Definition constants.h:61
double cos(Angle const &a)
Definition Angle.h:110

◆ getBoundingCircle()

Circle lsst::sphgeom::Box::getBoundingCircle ( ) const
overridevirtual

getBoundingCircle returns a bounding-circle for this region.

Implements lsst::sphgeom::Region.

Definition at line 194 of file Box.cc.

194 {
195 if (isEmpty()) {
196 return Circle::empty();
197 }
198 if (isFull()) {
199 return Circle::full();
200 }
201 NormalizedAngle w = getWidth();
202 // The minimal bounding circle center p lies on the meridian bisecting
203 // this box. Let δ₁ and δ₂ be the minimum and maximum box latitudes.
204 if (w.asRadians() <= PI) {
205 UnitVector3d p;
206 UnitVector3d boxVerts[4] = {
207 UnitVector3d(_lon.getA(), _lat.getA()),
208 UnitVector3d(_lon.getA(), _lat.getB()),
209 UnitVector3d(_lon.getB(), _lat.getA()),
210 UnitVector3d(_lon.getB(), _lat.getB())
211 };
212 // We take advantage of rotational symmetry to fix the bisecting
213 // meridian at a longitude of zero. The box vertices then have
214 // coordinates (±w/2, δ₁), (±w/2, δ₂), and p = (0, ϕ). Converting
215 // to Cartesian coordinates gives p = (cos ϕ, 0, sin ϕ), and box
216 // vertices at (cos w/2 cos δ₁, ±sin w/2 cos δ₁, sin δ₁) and
217 // (cos w/2 cos δ₂, ±sin w/2 cos δ₂, sin δ₂).
218 //
219 // The point p₁ on the meridian that has minimum angular separation
220 // to the vertices with latitude δ₁ lies on the plane they define.
221 // The sum of the two vertex vectors is on that plane and on the plane
222 // containing the meridian. Normalizing to obtain p₁, we have
223 //
224 // (cos ϕ₁, 0, sin ϕ₁) =
225 // λ ((cos w/2 cos δ₁, sin w/2 cos δ₁, sin δ₁) +
226 // (cos w/2 cos δ₁, -sin w/2 cos δ₁, sin δ₁))
227 //
228 // for some scaling factor λ. Simplifying, we get:
229 //
230 // cos ϕ₁ = λ cos w/2 cos δ₁
231 // sin ϕ₁ = λ sin δ₁
232 //
233 // so that
234 //
235 // tan ϕ₁ = sec w/2 tan δ₁
236 //
237 // Similarly, the point p₂ on the meridian that has minimum angular
238 // separation to the vertices with latitude δ₂ satisfies:
239 //
240 // tan ϕ₂ = sec w/2 tan δ₂
241 //
242 // where ϕ₁ ≤ ϕ₂ (since δ₁ ≤ δ₂). Finally, consider the point p₃
243 // separated from each box vertex by the same angle. The dot
244 // products of p₃ with the box vertices are all identical, so
245 //
246 // cos ϕ₃ cos w/2 cos δ₁ + sin ϕ₃ sin δ₁ =
247 // cos ϕ₃ cos w/2 cos δ₂ + sin ϕ₃ sin δ₂
248 //
249 // Rearranging gives:
250 //
251 // tan ϕ₃ = - cos w/2 (cos δ₁ - cos δ₂)/(sin δ₁ - sin δ₂)
252 //
253 // which can be simplified further using a tangent half-angle identity,
254 // yielding:
255 //
256 // tan ϕ₃ = cos w/2 tan (δ₁ + δ₂)/2
257 //
258 // Consider now the function f₁(ϕ) that gives the angular separation
259 // between p with latitude ϕ and the vertices at latitude δ₁. It has
260 // a line of symmetry at ϕ = ϕ₁, and increases monotonically with
261 // |ϕ - ϕ₁|. Similarly, f₂(ϕ) has a minimum at ϕ₂ and increases
262 // monotonically with |ϕ - ϕ₂|. The two functions cross at ϕ₃. The
263 // opening angle of the bounding circle centered at latitude ϕ is
264 // given by g = max(f₁, f₂), which we seek to minimize.
265 //
266 // If ϕ₁ ≤ ϕ₃ ≤ ϕ₂, then g is minimized at ϕ = ϕ₃. Otherwise, it
267 // is minimized at either ϕ₁ or ϕ₂.
268 double phi1, phi2, phi3;
269 double c = cos(0.5 * w);
270 if (c == 0.0) {
271 // This code should never execute. If it does, the implementation
272 // of std::cos is broken.
273 phi1 = ::copysign(0.5 * PI, _lat.getA().asRadians());
274 phi2 = ::copysign(0.5 * PI, _lat.getB().asRadians());
275 phi3 = 0.0;
276 } else {
277 phi1 = std::atan(tan(_lat.getA()) / c);
278 phi2 = std::atan(tan(_lat.getB()) / c);
279 phi3 = std::atan(c * tan(_lat.getCenter()));
280 }
281 if (phi1 <= phi3 && phi3 <= phi2) {
282 p = UnitVector3d(_lon.getCenter(), Angle(phi3));
283 } else {
284 UnitVector3d p1 = UnitVector3d(_lon.getCenter(), Angle(phi1));
285 UnitVector3d p2 = UnitVector3d(_lon.getCenter(), Angle(phi2));
286 if (p1.dot(boxVerts[0]) > p2.dot(boxVerts[1])) {
287 p = p2;
288 } else {
289 p = p1;
290 }
291 }
292 // Compute the maximum squared chord length between p and the box
293 // vertices, so that each one is guaranteed to lie in the bounding
294 // circle, regardless of numerical error in the above.
295 double cl2 = (p - boxVerts[0]).getSquaredNorm();
296 for (int i = 1; i < 4; ++i) {
297 cl2 = std::max(cl2, (p - boxVerts[i]).getSquaredNorm());
298 }
299 // Add double the maximum squared-chord-length error, so that the
300 // bounding circle we return also reliably CONTAINS this box.
301 return Circle(p, cl2 + 2.0 * MAX_SQUARED_CHORD_LENGTH_ERROR);
302 }
303 // The box spans more than π radians in longitude. First, pick the smaller
304 // of the bounding circles centered at the north and south pole.
305 Angle r;
306 UnitVector3d v;
307 if (abs(_lat.getA()) <= abs(_lat.getB())) {
308 v = UnitVector3d::Z();
309 r = Angle(0.5 * PI) - _lat.getA();
310 } else {
311 v = -UnitVector3d::Z();
312 r = _lat.getB() + Angle(0.5 * PI);
313 }
314 // If the box does not span all longitude angles, we also consider the
315 // equatorial bounding circle with center longitude equal to the longitude
316 // of the box center. The smaller of the polar and equatorial bounding
317 // circles is returned.
318 if (!_lon.isFull() && 0.5 * w < r) {
319 r = 0.5 * w;
320 v = UnitVector3d(_lon.getCenter(), Angle(0.0));
321 }
322 return Circle(v, r + 4.0 * Angle(MAX_ASIN_ERROR));
323}
T atan(T... args)
NormalizedAngle getWidth() const
getWidth returns the width in longitude angle of this box.
Definition Box.h:173
static Circle empty()
Definition Circle.h:58
static Circle full()
Definition Circle.h:60
Scalar getCenter() const
getCenter returns the center of this interval.
Definition Interval.h:96
bool isFull() const
isFull returns true if this interval contains all normalized angles.
NormalizedAngle getCenter() const
getCenter returns the center of this interval.
static UnitVector3d Z()
constexpr double MAX_ASIN_ERROR
Definition constants.h:52
constexpr double MAX_SQUARED_CHORD_LENGTH_ERROR
Definition constants.h:57
double tan(Angle const &a)
Definition Angle.h:111

◆ getCenter()

LonLat lsst::sphgeom::Box::getCenter ( ) const
inline

getCenter returns the center of this box.

It is NaN for empty boxes and arbitrary for full boxes.

Definition at line 167 of file Box.h.

167 {
168 return LonLat(_lon.getCenter(), _lat.getCenter());
169 }

◆ getHeight()

Angle lsst::sphgeom::Box::getHeight ( ) const
inline

getHeight returns the height in latitude angle of this box.

It is negative or NaN for empty boxes.

Definition at line 177 of file Box.h.

177{ return _lat.getSize(); }
Scalar getSize() const
getSize returns the size (length, width) of this interval.
Definition Interval.h:100

◆ getLat()

AngleInterval const & lsst::sphgeom::Box::getLat ( ) const
inline

getLat returns the latitude interval of this box.

Definition at line 156 of file Box.h.

156{ return _lat; }

◆ getLon()

NormalizedAngleInterval const & lsst::sphgeom::Box::getLon ( ) const
inline

getLon returns the longitude interval of this box.

Definition at line 153 of file Box.h.

153{ return _lon; }

◆ getRegions()

std::vector< std::unique_ptr< Region > > lsst::sphgeom::Region::getRegions ( Region const & region)
staticinherited

getRegions returns a vector of Region.

Definition at line 145 of file Region.cc.

145 {
147 if (auto union_region = dynamic_cast<UnionRegion const *>(&region)) {
148 for(unsigned i = 0; i < union_region->nOperands(); ++i) {
149 result.emplace_back(union_region->getOperand(i).clone());
150 }
151 } else if(auto intersection_region = dynamic_cast<IntersectionRegion const *>(&region)) {
152 for(unsigned i = 0; i < intersection_region->nOperands(); ++i) {
153 result.emplace_back(intersection_region->getOperand(i).clone());
154 }
155 } else {
156 result.emplace_back(region.clone());
157 }
158 return result;
159}
T emplace_back(T... args)

◆ getWidth()

NormalizedAngle lsst::sphgeom::Box::getWidth ( ) const
inline

getWidth returns the width in longitude angle of this box.

It is NaN for empty boxes.

Definition at line 173 of file Box.h.

173{ return _lon.getSize(); }

◆ halfWidthForCircle()

NormalizedAngle lsst::sphgeom::Box::halfWidthForCircle ( Angle r,
Angle lat )
static

halfWidthForCircle computes the half-width of bounding boxes for circles with radius r and centers at the given latitude.

If r is non-positive, the result is zero, and if |lat| + r >= PI/2, the result is PI.

Definition at line 50 of file Box.cc.

50 {
51 if (r <= Angle(0.0)) {
52 return NormalizedAngle(0.0);
53 }
54 // If a circle centered at the given latitude contains a pole, then
55 // its bounding box contains all possible longitudes.
56 if (abs(lat) + r >= Angle(0.5 * PI)) {
57 return NormalizedAngle(PI);
58 }
59 // Now, consider the circle with opening angle r > 0 centered at (0,δ)
60 // with r < π/2 and |δ| ≠ π/2. The circle center vector in ℝ³ is
61 // c = (cos δ, 0, sin δ). Its bounding box spans longitudes [-α,α], where
62 // α is the desired half-width. The plane corresponding to longitude α has
63 // normal vector (-sin α, cos α, 0) and is tangent to the circle at point
64 // p. The great circle segment between the center of the circle and the
65 // plane normal passes through p and has arc length π/2 + r, so that
66 //
67 // (cos δ, 0, sin δ) · (-sin α, cos α, 0) = cos (π/2 + r)
68 //
69 // Solving for α gives
70 //
71 // α = arcsin (sin r / cos δ)
72 //
73 // In the actual computation, there is an absolute value and an explicit
74 // arcsin domain check to cope with rounding errors. An alternate way to
75 // compute this is:
76 //
77 // α = arctan (sin r / √(cos(δ - r) cos(δ + r)))
78 double s = std::fabs(sin(r) / cos(lat));
79 if (s >= 1.0) {
80 return NormalizedAngle(0.5 * PI);
81 }
82 return NormalizedAngle(std::asin(s));
83}
T asin(T... args)

◆ intersects() [1/2]

bool lsst::sphgeom::Box::intersects ( Box const & x) const
inline

intersects returns true if the intersection of this box and x is non-empty.

Definition at line 206 of file Box.h.

206 {
207 return _lat.intersects(x._lat) && _lon.intersects(x._lon);
208 }
bool intersects(Scalar x) const
Definition Interval.h:137

◆ intersects() [2/2]

bool lsst::sphgeom::Box::intersects ( LonLat const & x) const
inline

intersects returns true if the intersection of this box and x is non-empty.

Definition at line 202 of file Box.h.

202 {
203 return _lat.intersects(x.getLat()) && _lon.intersects(x.getLon());
204 }

◆ isDisjointFrom() [1/2]

bool lsst::sphgeom::Box::isDisjointFrom ( Box const & x) const
inline

isDisjointFrom returns true if the intersection of this box and x is empty.

Definition at line 196 of file Box.h.

196{ return !intersects(x); }
bool intersects(LonLat const &x) const
Definition Box.h:202

◆ isDisjointFrom() [2/2]

bool lsst::sphgeom::Box::isDisjointFrom ( LonLat const & x) const
inline

isDisjointFrom returns true if the intersection of this box and x is empty.

Definition at line 194 of file Box.h.

194{ return !intersects(x); }

◆ isEmpty()

bool lsst::sphgeom::Box::isEmpty ( ) const
inlineoverridevirtual

isEmpty returns true if this box does not contain any points.

Implements lsst::sphgeom::Region.

Definition at line 159 of file Box.h.

159{ return _lat.isEmpty(); }
bool isEmpty() const
isEmpty returns true if this interval does not contain any points.
Definition Interval.h:90

◆ isFull()

bool lsst::sphgeom::Box::isFull ( ) const
inline

isFull returns true if this box contains all points on the unit sphere.

Definition at line 163 of file Box.h.

163{ return _lon.isFull() && _lat == allLatitudes(); }

◆ isWithin() [1/2]

bool lsst::sphgeom::Box::isWithin ( Box const & x) const
inline

isWithin returns true if the intersection of this box and x is this box.

Definition at line 218 of file Box.h.

218 {
219 return _lat.isWithin(x._lat) && _lon.isWithin(x._lon);
220 }
bool isWithin(Scalar x) const
Definition Interval.h:147

◆ isWithin() [2/2]

bool lsst::sphgeom::Box::isWithin ( LonLat const & x) const
inline

isWithin returns true if the intersection of this box and x is this box.

Definition at line 214 of file Box.h.

214 {
215 return _lat.isWithin(x.getLat()) && _lon.isWithin(x.getLon());
216 }

◆ operator!=() [1/2]

bool lsst::sphgeom::Box::operator!= ( Box const & b) const
inline

Definition at line 143 of file Box.h.

143{ return !(*this == b); }

◆ operator!=() [2/2]

bool lsst::sphgeom::Box::operator!= ( LonLat const & p) const
inline

Definition at line 150 of file Box.h.

150{ return !(*this == p); }

◆ operator==() [1/2]

bool lsst::sphgeom::Box::operator== ( Box const & b) const
inline

Two boxes are equal if they contain the same points.

Definition at line 139 of file Box.h.

139 {
140 return _lon == b._lon && _lat == b._lat;
141 }

◆ operator==() [2/2]

bool lsst::sphgeom::Box::operator== ( LonLat const & p) const
inline

A box is equal to a point p if it contains only p.

Definition at line 146 of file Box.h.

146 {
147 return _lat == p.getLat() && _lon == p.getLon();
148 }

◆ overlaps() [1/5]

TriState lsst::sphgeom::Box::overlaps ( Box const & ) const
overridevirtual

overlaps tests whether two regions overlap. This method returns a TriState object, when the value is true it means that regions definitely overlap, false means they are definitely disjont, and unknown state means that they may or may not overlap.

Implements lsst::sphgeom::Region.

Definition at line 454 of file Box.cc.

454 {
455 // `intersects` returns exact value.
456 return TriState(intersects(b));
457}

◆ overlaps() [2/5]

TriState lsst::sphgeom::Box::overlaps ( Circle const & ) const
overridevirtual

overlaps tests whether two regions overlap. This method returns a TriState object, when the value is true it means that regions definitely overlap, false means they are definitely disjont, and unknown state means that they may or may not overlap.

Implements lsst::sphgeom::Region.

Definition at line 459 of file Box.cc.

459 {
460 // `relate` with Circle returns exact value.
461 return TriState(not (relate(c) & DISJOINT).any());
462}
Relationship relate(LonLat const &p) const
Definition Box.h:305

◆ overlaps() [3/5]

TriState lsst::sphgeom::Box::overlaps ( ConvexPolygon const & ) const
overridevirtual

overlaps tests whether two regions overlap. This method returns a TriState object, when the value is true it means that regions definitely overlap, false means they are definitely disjont, and unknown state means that they may or may not overlap.

Implements lsst::sphgeom::Region.

Definition at line 464 of file Box.cc.

464 {
465 // ConvexPolygon-Box relations are implemented by ConvexPolygon.
466 return p.overlaps(*this);
467}

◆ overlaps() [4/5]

TriState lsst::sphgeom::Box::overlaps ( Ellipse const & ) const
overridevirtual

overlaps tests whether two regions overlap. This method returns a TriState object, when the value is true it means that regions definitely overlap, false means they are definitely disjont, and unknown state means that they may or may not overlap.

Implements lsst::sphgeom::Region.

Definition at line 469 of file Box.cc.

469 {
470 // Ellipse-Box relations are implemented by Ellipse.
471 return e.overlaps(*this);
472}

◆ overlaps() [5/5]

TriState lsst::sphgeom::Box::overlaps ( Region const & other) const
inlineoverridevirtual

overlaps tests whether two regions overlap. This method returns a TriState object, when the value is true it means that regions definitely overlap, false means they are definitely disjont, and unknown state means that they may or may not overlap.

Implements lsst::sphgeom::Region.

Definition at line 344 of file Box.h.

344 {
345 return other.overlaps(*this);
346 }

◆ relate() [1/6]

Relationship lsst::sphgeom::Box::relate ( Box const & ) const
inlineoverridevirtual

relate computes the spatial relationships between this region A and another region B. The return value S is a bitset with the following properties:

  • Bit S & DISJOINT is set only if A and B do not have any points in common.
  • Bit S & CONTAINS is set only if A contains all points in B.
  • Bit S & WITHIN is set only if B contains all points in A.

Said another way: if the CONTAINS, WITHIN or DISJOINT bit is set, then the corresponding spatial relationship between the two regions holds conclusively. If it is not set, the relationship may or may not hold.

These semantics allow for conservative relationship computations. In particular, a Region may choose to implement relate by replacing itself and/or the argument with a simplified bounding region.

Implements lsst::sphgeom::Region.

Definition at line 330 of file Box.h.

330 {
331 Relationship r1 = _lon.relate(b._lon);
332 Relationship r2 = _lat.relate(b._lat);
333 // If the box longitude or latitude intervals are disjoint, then the
334 // boxes are disjoint. The other spatial relationships must hold for
335 // both the longitude and latitude intervals in order to hold for the
336 // boxes.
337 return ((r1 & r2) & (CONTAINS | WITHIN)) | ((r1 | r2) & DISJOINT);
338 }
Relationship relate(Scalar x) const
Definition Interval.h:256
Relationship relate(NormalizedAngle x) const
std::bitset< 3 > Relationship
Relationship describes how two sets are related.

◆ relate() [2/6]

Relationship lsst::sphgeom::Box::relate ( Circle const & ) const
overridevirtual

relate computes the spatial relationships between this region A and another region B. The return value S is a bitset with the following properties:

  • Bit S & DISJOINT is set only if A and B do not have any points in common.
  • Bit S & CONTAINS is set only if A contains all points in B.
  • Bit S & WITHIN is set only if B contains all points in A.

Said another way: if the CONTAINS, WITHIN or DISJOINT bit is set, then the corresponding spatial relationship between the two regions holds conclusively. If it is not set, the relationship may or may not hold.

These semantics allow for conservative relationship computations. In particular, a Region may choose to implement relate by replacing itself and/or the argument with a simplified bounding region.

Implements lsst::sphgeom::Region.

Definition at line 325 of file Box.cc.

325 {
326 if (isEmpty()) {
327 if (c.isEmpty()) {
328 return CONTAINS | DISJOINT | WITHIN;
329 }
330 return DISJOINT | WITHIN;
331 } else if (c.isEmpty()) {
332 return CONTAINS | DISJOINT;
333 }
334 if (isFull()) {
335 if (c.isFull()) {
336 return CONTAINS | WITHIN;
337 }
338 return CONTAINS;
339 } else if (c.isFull()) {
340 return WITHIN;
341 }
342 // Neither region is empty or full. We now determine whether or not the
343 // circle and box boundaries intersect.
344 //
345 // If the box vertices are not all inside or all outside of c, then the
346 // boundaries cross.
347 LonLat vertLonLat[4] = {
348 LonLat(_lon.getA(), _lat.getA()),
349 LonLat(_lon.getA(), _lat.getB()),
350 LonLat(_lon.getB(), _lat.getA()),
351 LonLat(_lon.getB(), _lat.getB())
352 };
353 UnitVector3d verts[4];
354 bool inside = false;
355 for (int i = 0; i < 4; ++i) {
356 verts[i] = UnitVector3d(vertLonLat[i]);
357 double d = (verts[i] - c.getCenter()).getSquaredNorm();
358 if (std::fabs(d - c.getSquaredChordLength()) <
360 // A box vertex is close to the circle boundary.
361 return INTERSECTS;
362 }
363 bool b = d < c.getSquaredChordLength();
364 if (i == 0) {
365 inside = b;
366 } else if (inside != b) {
367 // There are box vertices both inside and outside of c.
368 return INTERSECTS;
369 }
370 }
371 UnitVector3d norms[2] = {
374 };
375 if (inside) {
376 // All box vertices are inside c. Look for points in the box edge
377 // interiors that are outside c.
378 for (int i = 0; i < 2; ++i) {
379 double d = getMaxSquaredChordLength(
380 c.getCenter(), verts[2 * i + 1], verts[2 * i], norms[i]);
381 if (d > c.getSquaredChordLength() -
383 return INTERSECTS;
384 }
385 }
386 LonLat cc(-c.getCenter());
387 if (_lon.contains(cc.getLon())) {
388 // The points furthest from the center of c on the small circles
389 // defined by the box edges with constant latitude are in the box
390 // edge interiors. Find the largest squared chord length to either.
391 Angle a = std::min(getMinAngleToCircle(cc.getLat(), _lat.getA()),
392 getMinAngleToCircle(cc.getLat(), _lat.getB()));
393 double d = Circle::squaredChordLengthFor(Angle(PI) - a);
394 if (d > c.getSquaredChordLength() -
396 return INTERSECTS;
397 }
398 }
399 // The box boundary is completely inside c. However, the box is not
400 // necessarily within c: consider a circle with opening angle equal to
401 // π - ε. If a box contains the complement of such a circle, then
402 // intersecting it with that circle will punch a hole in the box. In
403 // this case each region contains the boundary of the other, but
404 // neither region contains the other.
405 //
406 // To handle this case, check that the box does not contain the
407 // complement of c - since the boundaries do not intersect, this is the
408 // case iff the box contains the center of the complement of c.
409 if (contains(cc)) {
410 return INTERSECTS;
411 }
412 return WITHIN;
413 }
414 // All box vertices are outside c. Look for points in the box edge
415 // interiors that are inside c.
416 for (int i = 0; i < 2; ++i) {
417 double d = getMinSquaredChordLength(
418 c.getCenter(), verts[2 * i + 1], verts[2 * i], norms[i]);
419 if (d < c.getSquaredChordLength() + MAX_SQUARED_CHORD_LENGTH_ERROR) {
420 return INTERSECTS;
421 }
422 }
423 LonLat cc(c.getCenter());
424 if (_lon.contains(cc.getLon())) {
425 // The points closest to the center of c on the small circles
426 // defined by the box edges with constant latitude are in the box
427 // edge interiors. Find the smallest squared chord length to either.
428 Angle a = std::min(getMinAngleToCircle(cc.getLat(), _lat.getA()),
429 getMinAngleToCircle(cc.getLat(), _lat.getB()));
430 double d = Circle::squaredChordLengthFor(a);
431 if (d < c.getSquaredChordLength() + MAX_SQUARED_CHORD_LENGTH_ERROR) {
432 return INTERSECTS;
433 }
434 }
435 // The box boundary is completely outside of c. If the box contains the
436 // circle center, then the box contains c. Otherwise, the box and circle
437 // are disjoint.
438 if (contains(cc)) {
439 return CONTAINS;
440 }
441 return DISJOINT;
442}
static double squaredChordLengthFor(Angle openingAngle)
squaredChordLengthFor computes and returns the squared chord length between points in S² that are sep...
Definition Circle.cc:48
static UnitVector3d orthogonalTo(Vector3d const &v)
orthogonalTo returns an arbitrary unit vector that is orthogonal to v.
Angle getMinAngleToCircle(Angle x, Angle c)
getMinAngleToCircle returns the minimum angular separation between a point at latitude x and the poin...
Definition utils.h:69
double getMaxSquaredChordLength(Vector3d const &v, Vector3d const &a, Vector3d const &b, Vector3d const &n)
Let p be the unit vector furthest from v that lies on the plane with normal n in the direction of the...
Definition utils.cc:65
double getMinSquaredChordLength(Vector3d const &v, Vector3d const &a, Vector3d const &b, Vector3d const &n)
Let p be the unit vector closest to v that lies on the plane with normal n in the direction of the cr...
Definition utils.cc:43

◆ relate() [3/6]

Relationship lsst::sphgeom::Box::relate ( ConvexPolygon const & ) const
overridevirtual

relate computes the spatial relationships between this region A and another region B. The return value S is a bitset with the following properties:

  • Bit S & DISJOINT is set only if A and B do not have any points in common.
  • Bit S & CONTAINS is set only if A contains all points in B.
  • Bit S & WITHIN is set only if B contains all points in A.

Said another way: if the CONTAINS, WITHIN or DISJOINT bit is set, then the corresponding spatial relationship between the two regions holds conclusively. If it is not set, the relationship may or may not hold.

These semantics allow for conservative relationship computations. In particular, a Region may choose to implement relate by replacing itself and/or the argument with a simplified bounding region.

Implements lsst::sphgeom::Region.

Definition at line 444 of file Box.cc.

444 {
445 // ConvexPolygon-Box relations are implemented by ConvexPolygon.
446 return invert(p.relate(*this));
447}
Relationship invert(Relationship r)
Given the relationship between two sets A and B (i.e.

◆ relate() [4/6]

Relationship lsst::sphgeom::Box::relate ( Ellipse const & ) const
overridevirtual

relate computes the spatial relationships between this region A and another region B. The return value S is a bitset with the following properties:

  • Bit S & DISJOINT is set only if A and B do not have any points in common.
  • Bit S & CONTAINS is set only if A contains all points in B.
  • Bit S & WITHIN is set only if B contains all points in A.

Said another way: if the CONTAINS, WITHIN or DISJOINT bit is set, then the corresponding spatial relationship between the two regions holds conclusively. If it is not set, the relationship may or may not hold.

These semantics allow for conservative relationship computations. In particular, a Region may choose to implement relate by replacing itself and/or the argument with a simplified bounding region.

Implements lsst::sphgeom::Region.

Definition at line 449 of file Box.cc.

449 {
450 // Ellipse-Box relations are implemented by Ellipse.
451 return invert(e.relate(*this));
452}

◆ relate() [5/6]

Relationship lsst::sphgeom::Box::relate ( LonLat const & p) const
inline

Definition at line 305 of file Box.h.

305{ return relate(Box(p)); }

◆ relate() [6/6]

Relationship lsst::sphgeom::Box::relate ( Region const & ) const
inlineoverridevirtual

relate computes the spatial relationships between this region A and another region B. The return value S is a bitset with the following properties:

  • Bit S & DISJOINT is set only if A and B do not have any points in common.
  • Bit S & CONTAINS is set only if A contains all points in B.
  • Bit S & WITHIN is set only if B contains all points in A.

Said another way: if the CONTAINS, WITHIN or DISJOINT bit is set, then the corresponding spatial relationship between the two regions holds conclusively. If it is not set, the relationship may or may not hold.

These semantics allow for conservative relationship computations. In particular, a Region may choose to implement relate by replacing itself and/or the argument with a simplified bounding region.

Implements lsst::sphgeom::Region.

Definition at line 325 of file Box.h.

325 {
326 // Dispatch on the type of r.
327 return invert(r.relate(*this));
328 }

Member Data Documentation

◆ TYPE_CODE

constexpr std::uint8_t lsst::sphgeom::Box::TYPE_CODE = 'b'
staticconstexpr

Definition at line 64 of file Box.h.


The documentation for this class was generated from the following files: