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
Box.cc
Go to the documentation of this file.
1/*
2 * This file is part of sphgeom.
3 *
4 * Developed for the LSST Data Management System.
5 * This product includes software developed by the LSST Project
6 * (http://www.lsst.org).
7 * See the COPYRIGHT file at the top-level directory of this distribution
8 * for details of code ownership.
9 *
10 * This software is dual licensed under the GNU General Public License and also
11 * under a 3-clause BSD license. Recipients may choose which of these licenses
12 * to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
13 * respectively. If you choose the GPL option then the following text applies
14 * (but note that there is still no warranty even if you opt for BSD instead):
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29
32
33#include "lsst/sphgeom/Box.h"
34
35#include <cmath>
36#include <ostream>
37#include <stdexcept>
38
39#include "lsst/sphgeom/Box3d.h"
40#include "lsst/sphgeom/Circle.h"
43#include "lsst/sphgeom/codec.h"
44#include "lsst/sphgeom/utils.h"
45
46
47namespace lsst {
48namespace sphgeom {
49
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}
84
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}
107
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}
121
122double Box::getArea() const {
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}
133
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}
193
195 if (isEmpty()) {
196 return Circle::empty();
197 }
198 if (isFull()) {
199 return Circle::full();
200 }
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}
324
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]);
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);
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}
443
445 // ConvexPolygon-Box relations are implemented by ConvexPolygon.
446 return invert(p.relate(*this));
447}
448
450 // Ellipse-Box relations are implemented by Ellipse.
451 return invert(e.relate(*this));
452}
453
455 // `intersects` returns exact value.
456 return TriState(intersects(b));
457}
458
460 // `relate` with Circle returns exact value.
461 return TriState(not (relate(c) & DISJOINT).any());
462}
463
465 // ConvexPolygon-Box relations are implemented by ConvexPolygon.
466 return p.overlaps(*this);
467}
468
470 // Ellipse-Box relations are implemented by Ellipse.
471 return e.overlaps(*this);
472}
473
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}
485
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}
501
503 return os << "{\"Box\": [" << b.getLon() << ", " << b.getLat() << "]}";
504}
505
506}} // namespace lsst::sphgeom
This file declares a class for representing axis-aligned bounding boxes in ℝ³.
This file declares a class for representing circular regions on the unit sphere.
This file declares a class for representing convex polygons with great circle edges on the unit spher...
int xmax
Definition SpanSet.cc:48
int xmin
Definition SpanSet.cc:48
table::Key< int > b
T asin(T... args)
T atan(T... args)
Angle represents an angle in radians.
Definition Angle.h:50
bool isNan() const
isNan returns true if the angle value is NaN.
Definition Angle.h:98
double asRadians() const
asRadians returns the value of this angle in units of radians.
Definition Angle.h:92
AngleInterval represents closed intervals of arbitrary angles.
static AngleInterval fromRadians(double x, double y)
Box3d represents a box in ℝ³.
Definition Box3d.h:49
static Box3d aroundUnitSphere()
aroundUnitSphere returns a minimal Box3d containing the unit sphere.
Definition Box3d.h:63
Box represents a rectangle in spherical coordinate space that contains its boundary.
Definition Box.h:62
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
NormalizedAngle getWidth() const
getWidth returns the width in longitude angle of this box.
Definition Box.h:173
double getArea() const
getArea returns the area of this box in steradians.
Definition Box.cc:122
Box3d getBoundingBox3d() const override
getBoundingBox3d returns a 3-dimensional bounding-box for this region.
Definition Box.cc:134
Relationship relate(LonLat const &p) const
Definition Box.h:305
static std::unique_ptr< Box > decode(std::vector< std::uint8_t > const &s)
Definition Box.h:356
static constexpr std::uint8_t TYPE_CODE
Definition Box.h:64
bool isFull() const
isFull returns true if this box contains all points on the unit sphere.
Definition Box.h:163
std::vector< std::uint8_t > encode() const override
encode serializes this region into an opaque byte string.
Definition Box.cc:474
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
TriState overlaps(Region const &other) const override
Definition Box.h:344
bool contains(LonLat const &x) const
Definition Box.h:182
bool intersects(LonLat const &x) const
Definition Box.h:202
Circle getBoundingCircle() const override
getBoundingCircle returns a bounding-circle for this region.
Definition Box.cc:194
Circle is a circular region on the unit sphere that contains its boundary.
Definition Circle.h:54
static Circle empty()
Definition Circle.h:58
static Circle full()
Definition Circle.h:60
bool isFull() const
Definition Circle.h:122
double getSquaredChordLength() const
getSquaredChordLength returns the squared length of chords between the circle center and points on th...
Definition Circle.h:131
UnitVector3d const & getCenter() const
getCenter returns the center of this circle as a unit vector.
Definition Circle.h:126
static double squaredChordLengthFor(Angle openingAngle)
squaredChordLengthFor computes and returns the squared chord length between points in S² that are sep...
Definition Circle.cc:48
bool isEmpty() const override
isEmpty returns true when a region does not contain any points.
Definition Circle.h:117
ConvexPolygon is a closed convex polygon on the unit sphere.
TriState overlaps(Region const &other) const override
Relationship relate(Region const &r) const override
Ellipse is an elliptical region on the sphere.
Definition Ellipse.h:177
Relationship relate(Region const &r) const override
Definition Ellipse.h:296
TriState overlaps(Region const &other) const override
Definition Ellipse.h:306
Interval1d represents closed intervals of ℝ.
Definition Interval1d.h:47
Scalar getCenter() const
getCenter returns the center of this interval.
Definition Interval.h:96
Scalar getA() const
getA returns the lower endpoint of this interval.
Definition Interval.h:83
bool contains(Scalar x) const
Definition Interval.h:105
Scalar getB() const
getB returns the upper endpoint of this interval.
Definition Interval.h:87
LonLat represents a spherical coordinate (longitude/latitude angle) pair.
Definition LonLat.h:55
Angle getLat() const
Definition LonLat.h:97
NormalizedAngle getLon() const
Definition LonLat.h:95
NormalizedAngle is an angle that lies in the range [0, 2π), with one exception - a NormalizedAngle ca...
double asRadians() const
asRadians returns the value of this angle in units of radians.
bool isFull() const
isFull returns true if this interval contains all normalized angles.
NormalizedAngle getA() const
getA returns the first endpoint of this interval.
NormalizedAngle getCenter() const
getCenter returns the center of this interval.
NormalizedAngleInterval & dilateBy(Angle x)
NormalizedAngle getSize() const
getSize returns the size (length, width) of this interval.
NormalizedAngle getB() const
getB returns the second endpoint of this interval.
static NormalizedAngleInterval fromRadians(double a, double b)
TriState represents a boolean value with additional unknown state.
Definition TriState.h:46
UnitVector3d is a unit vector in ℝ³ with components stored in double precision.
static UnitVector3d Z()
double dot(Vector3d const &v) const
dot returns the inner product of this unit vector and v.
static UnitVector3d orthogonalTo(Vector3d const &v)
orthogonalTo returns an arbitrary unit vector that is orthogonal to v.
This file contains simple helper functions for encoding and decoding primitive types to/from byte str...
T fabs(T... args)
T max(T... args)
T min(T... args)
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
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
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
constexpr double MAX_ASIN_ERROR
Definition constants.h:52
Angle abs(Angle const &a)
Definition Angle.h:113
std::ostream & operator<<(std::ostream &, Angle const &)
Definition Angle.cc:41
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
double sin(Angle const &a)
Definition Angle.h:109
constexpr double MAX_SQUARED_CHORD_LENGTH_ERROR
Definition constants.h:57
double tan(Angle const &a)
Definition Angle.h:111
constexpr double EPSILON
Definition constants.h:61
double cos(Angle const &a)
Definition Angle.h:110
constexpr double PI
Definition constants.h:43
Relationship invert(Relationship r)
Given the relationship between two sets A and B (i.e.
T push_back(T... args)
T reserve(T... args)
This file declares a class for representing longitude/latitude angle boxes on the unit sphere.
This file declares a class for representing elliptical regions on the unit sphere.
This file declares miscellaneous utility functions.
double w
Definition CoaddPsf.cc:70