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
NormalizedAngleInterval.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2014-2015 AURA/LSST.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <https://www.lsstcorp.org/LegalNotices/>.
21  */
22 
25 
27 
28 #include <ostream>
29 #include <stdexcept>
30 
31 
32 namespace lsst {
33 namespace sphgeom {
34 
36  if (x.isNan() || y.isNan()) {
37  *this = empty();
38  return;
39  }
40  if (!x.isNormalized() || !y.isNormalized()) {
41  if (x > y) {
43  "invalid NormalizedAngleInterval endpoints");
44  }
45  if (y - x >= Angle(2.0 * PI)) {
46  *this = full();
47  return;
48  }
49  }
50  _a = NormalizedAngle(x);
51  _b = NormalizedAngle(y);
52 }
53 
55  NormalizedAngleInterval const & x) const
56 {
57  if (x.isEmpty()) {
58  return true;
59  }
60  if (isEmpty()) {
61  return false;
62  }
63  if (x.wraps()) {
64  if (!wraps()) {
65  return isFull();
66  }
67  } else if (wraps()) {
68  return x._a >= _a || x._b <= _b;
69  }
70  return x._a >= _a && x._b <= _b;
71 }
72 
74  NormalizedAngleInterval const & x) const
75 {
76  if (x.isEmpty() || isEmpty()) {
77  return true;
78  }
79  if (x.wraps()) {
80  return wraps() ? false : (x._a > _b && x._b < _a);
81  }
82  if (wraps()) {
83  return _a > x._b && _b < x._a;
84  }
85  return x._b < _a || x._a > _b;
86 }
87 
89  if (isEmpty()) {
90  if (x.isNan()) {
91  return CONTAINS | DISJOINT | WITHIN;
92  }
93  return DISJOINT | WITHIN;
94  }
95  if (x.isNan()) {
96  return CONTAINS | DISJOINT;
97  }
98  if (_a == x && _b == x) {
99  return CONTAINS | WITHIN;
100  }
101  if (intersects(x)) {
102  return CONTAINS;
103  }
104  return DISJOINT;
105 }
106 
108  NormalizedAngleInterval const & x) const
109 {
110  if (isEmpty()) {
111  if (x.isEmpty()) {
112  return CONTAINS | DISJOINT | WITHIN;
113  }
114  return DISJOINT | WITHIN;
115  }
116  if (x.isEmpty()) {
117  return CONTAINS | DISJOINT;
118  }
119  if (_a == x._a && _b == x._b) {
120  return CONTAINS | WITHIN;
121  }
122  // The intervals are not the same, and neither is empty.
123  if (wraps()) {
124  if (x.wraps()) {
125  // Both intervals wrap.
126  if (_a <= x._a && _b >= x._b) {
127  return CONTAINS;
128  }
129  if (_a >= x._a && _b <= x._b) {
130  return WITHIN;
131  }
132  return INTERSECTS;
133  }
134  // x does not wrap.
135  if (x.isFull()) {
136  return WITHIN;
137  }
138  if (_a <= x._a || _b >= x._b) {
139  return CONTAINS;
140  }
141  return (_a > x._b && _b < x._a) ? DISJOINT : INTERSECTS;
142  }
143  if (x.wraps()) {
144  // This interval does not wrap.
145  if (isFull()) {
146  return CONTAINS;
147  }
148  if (x._a <= _a || x._b >= _b) {
149  return WITHIN;
150  }
151  return (x._a > _b && x._b < _a) ? DISJOINT : INTERSECTS;
152  }
153  // Neither interval wraps.
154  if (_a <= x._a && _b >= x._b) {
155  return CONTAINS;
156  }
157  if (_a >= x._a && _b <= x._b) {
158  return WITHIN;
159  }
160  return (_a <= x._b && _b >= x._a) ? INTERSECTS : DISJOINT;
161 }
162 
164  NormalizedAngleInterval const & x)
165 {
166  if (x.isEmpty()) {
167  *this = empty();
168  } else if (contains(x._a)) {
169  if (contains(x._b)) {
170  // Both endpoints of x are in this interval. This interval
171  // either contains x, in which case x is the exact intersection,
172  // or the intersection consists of [_a,x._b] ⋃ [x._a,_b].
173  // In both cases, the envelope of the intersection is the shorter
174  // of the two intervals.
175  if (getSize() >= x.getSize()) {
176  *this = x;
177  }
178  } else {
179  _a = x._a;
180  }
181  } else if (contains(x._b)) {
182  _b = x._b;
183  } else if (x.isDisjointFrom(_a)) {
184  *this = empty();
185  }
186  return *this;
187 }
188 
191 {
192  if (isEmpty()) {
193  *this = NormalizedAngleInterval(x);
194  } else if (!contains(x)) {
195  if (x.getAngleTo(_a) > _b.getAngleTo(x)) {
196  _b = x;
197  } else {
198  _a = x;
199  }
200  }
201  return *this;
202 }
203 
205  NormalizedAngleInterval const & x)
206 {
207  if (!x.isEmpty()) {
208  if (contains(x._a)) {
209  if (contains(x._b)) {
210  // Both endpoints of x are in this interval. This interval
211  // either contains x, in which case this interval is the
212  // desired union, or the union is the full interval.
213  if (wraps() != x.wraps()) {
214  *this = full();
215  }
216  } else {
217  _b = x._b;
218  }
219  } else if (contains(x._b)) {
220  _a = x._a;
221  } else if (isEmpty() || x.contains(_a)) {
222  *this = x;
223  } else if (_b.getAngleTo(x._a) < x._b.getAngleTo(_a)) {
224  _b = x._b;
225  } else {
226  _a = x._a;
227  }
228  }
229  return *this;
230 }
231 
233  if (isEmpty() || isFull() || x == Angle(0.0) || x.isNan()) {
234  return *this;
235  }
236  Angle a = _a - x;
237  Angle b = _b + x;
238  if (x > Angle(0.0)) {
239  // x is a dilation.
240  if (x >= Angle(PI)) { return full(); }
241  if (wraps()) {
242  // The undilated interval wraps. If the dilated one does not,
243  // then decreasing a from _a and increasing b from _b has
244  // caused b and a to cross.
245  if (a <= b) { return full(); }
246  } else {
247  // The undilated interval does not wrap. If either a or b
248  // is not normalized then the dilated interval must either
249  // wrap or be full.
250  if (a < Angle(0.0)) {
251  a = a + Angle(2.0 * PI);
252  if (a <= b) { return full(); }
253  }
254  if (b > Angle(2.0 * PI)) {
255  b = b - Angle(2.0 * PI);
256  if (a <= b) { return full(); }
257  }
258  }
259  } else {
260  // x is an erosion.
261  if (x <= Angle(-PI)) { return empty(); }
262  if (wraps()) {
263  // The uneroded interval wraps. If either a or b is not
264  // normalized, then either the eroded interval does not wrap,
265  // or it is empty.
266  if (a > Angle(2.0 * PI)) {
267  a = a - Angle(2.0 * PI);
268  if (a > b) { return empty(); }
269  }
270  if (b < Angle(0.0)) {
271  b = b + Angle(2.0 * PI);
272  if (a > b) { return empty(); }
273  }
274  } else {
275  // The uneroded interval does not wrap. If the eroded one does,
276  // then increasing a from _a and decreasing b from _b has
277  // caused a and b to cross.
278  if (a > b) { return empty(); }
279  }
280  }
281  return NormalizedAngleInterval(a, b);
282 }
283 
285  NormalizedAngleInterval const & i)
286 {
287  return os << '[' << i.getA() << ", " << i.getB() << ']';
288 }
289 
290 }} // namespace lsst::sphgeom
double x
This file declares a class representing closed intervals of normalized angles, i.e.
std::ostream * os
Definition: Schema.cc:557
int y
Definition: SpanSet.cc:48
table::Key< int > b
table::Key< int > a
Angle represents an angle in radians.
Definition: Angle.h:43
NormalizedAngle is an angle that lies in the range [0, 2π), with one exception - a NormalizedAngle ca...
NormalizedAngle getAngleTo(NormalizedAngle const &a) const
getAngleTo computes the angle α ∈ [0, 2π) such that adding α to this angle and then normalizing the r...
NormalizedAngleInterval represents closed intervals of normalized angles, i.e.
static NormalizedAngleInterval empty()
NormalizedAngleInterval & clipTo(NormalizedAngle x)
clipTo shrinks this interval until all its points are in x.
bool isFull() const
isFull returns true if this interval contains all normalized angles.
bool isDisjointFrom(NormalizedAngle x) const
NormalizedAngleInterval()
This constructor creates an empty interval.
bool wraps() const
wraps returns true if the interval "wraps" around the 0/2π angle discontinuity, i....
NormalizedAngle getA() const
getA returns the first endpoint of this interval.
NormalizedAngleInterval dilatedBy(Angle x) const
For positive x, dilatedBy returns the morphological dilation of this interval by [-x,...
Relationship relate(NormalizedAngle x) const
NormalizedAngle getSize() const
getSize returns the size (length, width) of this interval.
NormalizedAngleInterval & expandTo(NormalizedAngle x)
NormalizedAngle getB() const
getB returns the second endpoint of this interval.
static NormalizedAngleInterval full()
bool isEmpty() const
isEmpty returns true if this interval does not contain any normalized angles.
lsst::geom::Angle Angle
Definition: misc.h:33
std::ostream & operator<<(std::ostream &, Angle const &)
Definition: Angle.cc:34
constexpr double PI
Definition: constants.h:36
A base class for image defects.