LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Public Member Functions | Static Public Member Functions | Static Public Attributes | 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. More...
 
 Box (LonLat const &p)
 This constructor creates a box containing a single point. More...
 
 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()]. More...
 
 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. More...
 
 Box (NormalizedAngleInterval const &lon, AngleInterval const &lat)
 This constructor creates a box spanning the given longitude and latitude intervals. More...
 
bool operator== (Box const &b) const
 Two boxes are equal if they contain the same points. More...
 
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. More...
 
bool operator!= (LonLat const &p) const
 
NormalizedAngleInterval const & getLon () const
 getLon returns the longitude interval of this box. More...
 
AngleInterval const & getLat () const
 getLat returns the latitude interval of this box. More...
 
bool isEmpty () const
 isEmpty returns true if this box does not contain any points. More...
 
bool isFull () const
 isFull returns true if this box contains all points on the unit sphere. More...
 
LonLat getCenter () const
 getCenter returns the center of this box. More...
 
NormalizedAngle getWidth () const
 getWidth returns the width in longitude angle of this box. More...
 
Angle getHeight () const
 getHeight returns the height in latitude angle of this box. More...
 
BoxclipTo (LonLat const &x)
 clipTo shrinks this box until it contains only x. More...
 
BoxclipTo (Box const &x)
 x.clipTo(y) sets x to the smallest box containing the intersection of x and y. More...
 
Box clippedTo (LonLat const &x) const
 clippedTo returns the intersection of this box and x. More...
 
Box clippedTo (Box const &x) const
 clippedTo returns the smallest box containing the intersection of this box and x. More...
 
BoxdilateBy (Angle r)
 dilateBy minimally expands this Box to include all points within angular separation r of its boundary. More...
 
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. More...
 
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. More...
 
std::unique_ptr< Regionclone () const override
 clone returns a deep copy of this region. More...
 
Box getBoundingBox () const override
 getBoundingBox returns a bounding-box for this region. More...
 
Box3d getBoundingBox3d () const override
 getBoundingBox3d returns a 3-dimensional bounding-box for this region. More...
 
Circle getBoundingCircle () const override
 getBoundingCircle returns a bounding-circle for this region. More...
 
bool contains (UnitVector3d const &v) const override
 contains tests whether the given unit vector is inside this region. More...
 
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
 
std::vector< uint8_t > encode () const override
 encode serializes this region into an opaque byte string. More...
 
virtual bool contains (UnitVector3d const &) const=0
 contains tests whether the given unit vector is inside this region. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
static NormalizedAngleInterval allLongitudes ()
 allLongitudes returns a normalized angle interval containing all valid longitude angles. More...
 
static AngleInterval allLatitudes ()
 allLatitudes returns an angle interval containing all valid latitude angles. More...
 
static std::unique_ptr< Boxdecode (std::vector< uint8_t > const &s)
 
static std::unique_ptr< Boxdecode (uint8_t const *buffer, size_t n)
 

Static Public Attributes

static constexpr uint8_t TYPE_CODE = 'b'
 

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 54 of file Box.h.

Constructor & Destructor Documentation

◆ Box() [1/5]

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

This constructor creates an empty box.

Definition at line 92 of file Box.h.

92 {}

◆ Box() [2/5]

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

This constructor creates a box containing a single point.

Definition at line 95 of file Box.h.

95  :
96  _lon(p.getLon()),
97  _lat(p.getLat())
98  {
99  _enforceInvariants();
100  }

◆ 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 105 of file Box.h.

105  :
106  _lon(p1.getLon(), p2.getLon()),
107  _lat(p1.getLat(), p2.getLat())
108  {
109  _enforceInvariants();
110  }

◆ 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 114 of file Box.h.

114  :
115  _lon(NormalizedAngleInterval(p.getLon()).dilatedBy(w)),
116  _lat(AngleInterval(p.getLat()).dilatedBy(h))
117  {
118  _enforceInvariants();
119  }
double w
Definition: CoaddPsf.cc:69

◆ 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 123 of file Box.h.

123  :
124  _lon(lon),
125  _lat(lat)
126  {
127  _enforceInvariants();
128  }

Member Function Documentation

◆ allLatitudes()

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

allLatitudes returns an angle interval containing all valid latitude angles.

Definition at line 87 of file Box.h.

87  {
88  return AngleInterval(Angle(-0.5 * PI), Angle(0.5 * PI));
89  }
lsst::geom::Angle Angle
Definition: misc.h:33
constexpr double PI
Definition: constants.h:36

◆ allLongitudes()

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

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

Definition at line 81 of file Box.h.

81  {
83  }
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 240 of file Box.h.

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

◆ 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 235 of file Box.h.

235 { 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 227 of file Box.h.

227  {
228  _lon.clipTo(x.getLon());
229  _lat.clipTo(x.getLat());
230  _enforceInvariants();
231  return *this;
232  }
Interval & clipTo(Scalar x)
Definition: Interval.h:159
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 217 of file Box.h.

217  {
218  _lon.clipTo(x.getLon());
219  _lat.clipTo(x.getLat());
220  _enforceInvariants();
221  return *this;
222  }

◆ 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 303 of file Box.h.

303  {
304  return std::unique_ptr<Box>(new Box(*this));
305  }

◆ contains() [1/8]

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 178 of file Box.h.

178  {
179  return _lat.contains(x._lat) && _lon.contains(x._lon);
180  }
bool contains(Scalar x) const
Definition: Interval.h:98

◆ contains() [2/8]

bool lsst::sphgeom::Region::contains

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

Definition at line 104 of file Region.cc.

43  {
44  return contains(UnitVector3d(LonLat::fromRadians(lon, lat)));
45 }
virtual bool contains(UnitVector3d const &) const=0
contains tests whether the given unit vector is inside this region.
static LonLat fromRadians(double lon, double lat)
Definition: LonLat.h:55

◆ contains() [3/8]

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

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

Definition at line 43 of file Region.cc.

43  {
44  return contains(UnitVector3d(LonLat::fromRadians(lon, lat)));
45 }
virtual bool contains(UnitVector3d const &) const =0
contains tests whether the given unit vector is inside this region.

◆ contains() [4/8]

bool lsst::sphgeom::Region::contains

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

Definition at line 100 of file Region.cc.

39  {
40  return contains(UnitVector3d(x, y, z));
41 }
double z
Definition: Match.cc:44
int y
Definition: SpanSet.cc:48

◆ contains() [5/8]

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

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

Definition at line 39 of file Region.cc.

39  {
40  return contains(UnitVector3d(x, y, z));
41 }

◆ contains() [6/8]

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 174 of file Box.h.

174  {
175  return _lat.contains(x.getLat()) && _lon.contains(x.getLon());
176  }

◆ contains() [7/8]

virtual bool lsst::sphgeom::Region::contains

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

◆ contains() [8/8]

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 311 of file Box.h.

311  {
312  return contains(LonLat(v));
313  }

◆ decode() [1/2]

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

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

Definition at line 340 of file Box.h.

340  {
341  return decode(s.data(), s.size());
342  }
static std::unique_ptr< Box > decode(std::vector< uint8_t > const &s)
Definition: Box.h:340
T data(T... args)
T size(T... args)

◆ decode() [2/2]

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

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

Definition at line 459 of file Box.cc.

459  {
460  if (buffer == nullptr || n != ENCODED_SIZE || *buffer != TYPE_CODE) {
461  throw std::runtime_error("Byte-string is not an encoded Box");
462  }
463  std::unique_ptr<Box> box(new Box);
464  ++buffer;
465  double a = decodeDouble(buffer); buffer += 8;
466  double b = decodeDouble(buffer); buffer += 8;
468  a = decodeDouble(buffer); buffer += 8;
469  b = decodeDouble(buffer); buffer += 8;
470  box->_lat = AngleInterval::fromRadians(a, b);
471  box->_enforceInvariants();
472  return box;
473 }
table::Key< int > b
table::Key< int > a
static AngleInterval fromRadians(double x, double y)
Definition: AngleInterval.h:49
static constexpr uint8_t TYPE_CODE
Definition: Box.h:56
static NormalizedAngleInterval fromRadians(double a, double b)
double decodeDouble(uint8_t const *buffer)
decode extracts an IEEE double from the 8 byte little-endian byte sequence in buffer.
Definition: codec.h:66

◆ 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 78 of file Box.cc.

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

◆ 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 101 of file Box.cc.

101  {
102  if (isEmpty() || isFull()) {
103  return *this;
104  }
105  _lon.dilateBy(w);
106  if (!h.isNan()) {
107  Angle a = (_lat.getA() > Angle(-0.5 * PI)) ? _lat.getA() - h : _lat.getA();
108  Angle b = (_lat.getB() < Angle(0.5 * PI)) ? _lat.getB() + h : _lat.getB();
109  _lat = AngleInterval(a, b);
110  }
111  _enforceInvariants();
112  return *this;
113 }
NormalizedAngleInterval & dilateBy(Angle x)

◆ dilatedBy() [1/2]

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

Definition at line 273 of file Box.h.

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

◆ dilatedBy() [2/2]

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

Definition at line 291 of file Box.h.

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

◆ empty()

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

Definition at line 69 of file Box.h.

69 { return Box(); }

◆ encode()

std::vector< 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 447 of file Box.cc.

447  {
448  std::vector<uint8_t> buffer;
449  uint8_t tc = TYPE_CODE;
450  buffer.reserve(ENCODED_SIZE);
451  buffer.push_back(tc);
452  encodeDouble(_lon.getA().asRadians(), buffer);
453  encodeDouble(_lon.getB().asRadians(), buffer);
454  encodeDouble(_lat.getA().asRadians(), buffer);
455  encodeDouble(_lat.getB().asRadians(), buffer);
456  return buffer;
457 }
double asRadians() const
asRadians returns the value of this angle in units of radians.
Definition: Angle.h:85
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< uint8_t > &buffer)
encode appends an IEEE double in little-endian byte order to the end of buffer.
Definition: codec.h:46
T push_back(T... args)
T reserve(T... args)

◆ erodeBy() [1/2]

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

Definition at line 292 of file Box.h.

292 { return dilateBy(-r); }

◆ erodeBy() [2/2]

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

Definition at line 293 of file Box.h.

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

◆ erodedBy() [1/2]

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

Definition at line 294 of file Box.h.

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

◆ erodedBy() [2/2]

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

Definition at line 295 of file Box.h.

295 { 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 264 of file Box.h.

264 { 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 263 of file Box.h.

263 { 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 252 of file Box.h.

252  {
253  _lon.expandTo(x.getLon());
254  _lat.expandTo(x.getLat());
255  return *this;
256  }
Interval & expandTo(Scalar x)
Definition: Interval.h:192
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 246 of file Box.h.

246  {
247  _lon.expandTo(x.getLon());
248  _lat.expandTo(x.getLat());
249  return *this;
250  }

◆ fromDegrees()

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

Definition at line 59 of file Box.h.

59  {
60  return Box(NormalizedAngleInterval::fromDegrees(lon1, lon2),
61  AngleInterval::fromDegrees(lat1, lat2));
62  }
static AngleInterval fromDegrees(double x, double y)
Definition: AngleInterval.h:44
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 64 of file Box.h.

64  {
65  return Box(NormalizedAngleInterval::fromRadians(lon1, lon2),
66  AngleInterval::fromRadians(lat1, lat2));
67  }

◆ full()

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

Definition at line 71 of file Box.h.

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

◆ getArea()

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

getArea returns the area of this box in steradians.

Definition at line 115 of file Box.cc.

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

◆ getBoundingBox()

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

getBoundingBox returns a bounding-box for this region.

Implements lsst::sphgeom::Region.

Definition at line 307 of file Box.h.

307 { 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 127 of file Box.cc.

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

◆ getBoundingCircle()

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

getBoundingCircle returns a bounding-circle for this region.

Implements lsst::sphgeom::Region.

Definition at line 187 of file Box.cc.

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

◆ 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 159 of file Box.h.

159  {
160  return LonLat(_lon.getCenter(), _lat.getCenter());
161  }

◆ 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 169 of file Box.h.

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

◆ getLat()

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

getLat returns the latitude interval of this box.

Definition at line 148 of file Box.h.

148 { return _lat; }

◆ getLon()

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

getLon returns the longitude interval of this box.

Definition at line 145 of file Box.h.

145 { return _lon; }

◆ 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 165 of file Box.h.

165 { 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 43 of file Box.cc.

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

198  {
199  return _lat.intersects(x._lat) && _lon.intersects(x._lon);
200  }
bool intersects(Scalar x) const
Definition: Interval.h:130

◆ 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 194 of file Box.h.

194  {
195  return _lat.intersects(x.getLat()) && _lon.intersects(x.getLon());
196  }

◆ 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 188 of file Box.h.

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

◆ 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 186 of file Box.h.

186 { return !intersects(x); }

◆ isEmpty()

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

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

Definition at line 151 of file Box.h.

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

◆ isFull()

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

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

Definition at line 155 of file Box.h.

155 { 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 210 of file Box.h.

210  {
211  return _lat.isWithin(x._lat) && _lon.isWithin(x._lon);
212  }
bool isWithin(Scalar x) const
Definition: Interval.h:140

◆ 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 206 of file Box.h.

206  {
207  return _lat.isWithin(x.getLat()) && _lon.isWithin(x.getLon());
208  }

◆ operator!=() [1/2]

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

Definition at line 135 of file Box.h.

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

◆ operator!=() [2/2]

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

Definition at line 142 of file Box.h.

142 { 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 131 of file Box.h.

131  {
132  return _lon == b._lon && _lat == b._lat;
133  }

◆ 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 138 of file Box.h.

138  {
139  return _lat == p.getLat() && _lon == p.getLon();
140  }

◆ 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 322 of file Box.h.

322  {
323  Relationship r1 = _lon.relate(b._lon);
324  Relationship r2 = _lat.relate(b._lat);
325  // If the box longitude or latitude intervals are disjoint, then the
326  // boxes are disjoint. The other spatial relationships must hold for
327  // both the longitude and latitude intervals in order to hold for the
328  // boxes.
329  return ((r1 & r2) & (CONTAINS | WITHIN)) | ((r1 | r2) & DISJOINT);
330  }
Relationship relate(Scalar x) const
Definition: Interval.h:249
Relationship relate(NormalizedAngle x) const
std::bitset< 3 > Relationship
Relationship describes how two sets are related.
Definition: Relationship.h:35

◆ 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 318 of file Box.cc.

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

◆ 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 437 of file Box.cc.

437  {
438  // ConvexPolygon-Box relations are implemented by ConvexPolygon.
439  return invert(p.relate(*this));
440 }
Relationship invert(Relationship r)
Given the relationship between two sets A and B (i.e.
Definition: Relationship.h:55

◆ 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 442 of file Box.cc.

442  {
443  // Ellipse-Box relations are implemented by Ellipse.
444  return invert(e.relate(*this));
445 }

◆ relate() [5/6]

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

Definition at line 297 of file Box.h.

297 { return relate(Box(p)); }
Relationship relate(LonLat const &p) const
Definition: Box.h:297

◆ 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 317 of file Box.h.

317  {
318  // Dispatch on the type of r.
319  return invert(r.relate(*this));
320  }

Member Data Documentation

◆ TYPE_CODE

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

Definition at line 56 of file Box.h.


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