LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
NormalizedAngleInterval.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
34
35#include <ostream>
36#include <stdexcept>
37
38
39namespace lsst {
40namespace sphgeom {
41
43 if (x.isNan() || y.isNan()) {
44 *this = empty();
45 return;
46 }
47 if (!x.isNormalized() || !y.isNormalized()) {
48 if (x > y) {
50 "invalid NormalizedAngleInterval endpoints");
51 }
52 if (y - x >= Angle(2.0 * PI)) {
53 *this = full();
54 return;
55 }
56 }
57 _a = NormalizedAngle(x);
58 _b = NormalizedAngle(y);
59}
60
62 NormalizedAngleInterval const & x) const
63{
64 if (x.isEmpty()) {
65 return true;
66 }
67 if (isEmpty()) {
68 return false;
69 }
70 if (x.wraps()) {
71 if (!wraps()) {
72 return isFull();
73 }
74 } else if (wraps()) {
75 return x._a >= _a || x._b <= _b;
76 }
77 return x._a >= _a && x._b <= _b;
78}
79
81 NormalizedAngleInterval const & x) const
82{
83 if (x.isEmpty() || isEmpty()) {
84 return true;
85 }
86 if (x.wraps()) {
87 return wraps() ? false : (x._a > _b && x._b < _a);
88 }
89 if (wraps()) {
90 return _a > x._b && _b < x._a;
91 }
92 return x._b < _a || x._a > _b;
93}
94
96 if (isEmpty()) {
97 if (x.isNan()) {
98 return CONTAINS | DISJOINT | WITHIN;
99 }
100 return DISJOINT | WITHIN;
101 }
102 if (x.isNan()) {
103 return CONTAINS | DISJOINT;
104 }
105 if (_a == x && _b == x) {
106 return CONTAINS | WITHIN;
107 }
108 if (intersects(x)) {
109 return CONTAINS;
110 }
111 return DISJOINT;
112}
113
115 NormalizedAngleInterval const & x) const
116{
117 if (isEmpty()) {
118 if (x.isEmpty()) {
119 return CONTAINS | DISJOINT | WITHIN;
120 }
121 return DISJOINT | WITHIN;
122 }
123 if (x.isEmpty()) {
124 return CONTAINS | DISJOINT;
125 }
126 if (_a == x._a && _b == x._b) {
127 return CONTAINS | WITHIN;
128 }
129 // The intervals are not the same, and neither is empty.
130 if (wraps()) {
131 if (x.wraps()) {
132 // Both intervals wrap.
133 if (_a <= x._a && _b >= x._b) {
134 return CONTAINS;
135 }
136 if (_a >= x._a && _b <= x._b) {
137 return WITHIN;
138 }
139 return INTERSECTS;
140 }
141 // x does not wrap.
142 if (x.isFull()) {
143 return WITHIN;
144 }
145 if (_a <= x._a || _b >= x._b) {
146 return CONTAINS;
147 }
148 return (_a > x._b && _b < x._a) ? DISJOINT : INTERSECTS;
149 }
150 if (x.wraps()) {
151 // This interval does not wrap.
152 if (isFull()) {
153 return CONTAINS;
154 }
155 if (x._a <= _a || x._b >= _b) {
156 return WITHIN;
157 }
158 return (x._a > _b && x._b < _a) ? DISJOINT : INTERSECTS;
159 }
160 // Neither interval wraps.
161 if (_a <= x._a && _b >= x._b) {
162 return CONTAINS;
163 }
164 if (_a >= x._a && _b <= x._b) {
165 return WITHIN;
166 }
167 return (_a <= x._b && _b >= x._a) ? INTERSECTS : DISJOINT;
168}
169
172{
173 if (x.isEmpty()) {
174 *this = empty();
175 } else if (contains(x._a)) {
176 if (contains(x._b)) {
177 // Both endpoints of x are in this interval. This interval
178 // either contains x, in which case x is the exact intersection,
179 // or the intersection consists of [_a,x._b] ⋃ [x._a,_b].
180 // In both cases, the envelope of the intersection is the shorter
181 // of the two intervals.
182 if (getSize() >= x.getSize()) {
183 *this = x;
184 }
185 } else {
186 _a = x._a;
187 }
188 } else if (contains(x._b)) {
189 _b = x._b;
190 } else if (x.isDisjointFrom(_a)) {
191 *this = empty();
192 }
193 return *this;
194}
195
198{
199 if (isEmpty()) {
200 *this = NormalizedAngleInterval(x);
201 } else if (!contains(x)) {
202 if (x.getAngleTo(_a) > _b.getAngleTo(x)) {
203 _b = x;
204 } else {
205 _a = x;
206 }
207 }
208 return *this;
209}
210
213{
214 if (!x.isEmpty()) {
215 if (contains(x._a)) {
216 if (contains(x._b)) {
217 // Both endpoints of x are in this interval. This interval
218 // either contains x, in which case this interval is the
219 // desired union, or the union is the full interval.
220 if (wraps() != x.wraps()) {
221 *this = full();
222 }
223 } else {
224 _b = x._b;
225 }
226 } else if (contains(x._b)) {
227 _a = x._a;
228 } else if (isEmpty() || x.contains(_a)) {
229 *this = x;
230 } else if (_b.getAngleTo(x._a) < x._b.getAngleTo(_a)) {
231 _b = x._b;
232 } else {
233 _a = x._a;
234 }
235 }
236 return *this;
237}
238
240 if (isEmpty() || isFull() || x == Angle(0.0) || x.isNan()) {
241 return *this;
242 }
243 Angle a = _a - x;
244 Angle b = _b + x;
245 if (x > Angle(0.0)) {
246 // x is a dilation.
247 if (x >= Angle(PI)) { return full(); }
248 if (wraps()) {
249 // The undilated interval wraps. If the dilated one does not,
250 // then decreasing a from _a and increasing b from _b has
251 // caused b and a to cross.
252 if (a <= b) { return full(); }
253 } else {
254 // The undilated interval does not wrap. If either a or b
255 // is not normalized then the dilated interval must either
256 // wrap or be full.
257 if (a < Angle(0.0)) {
258 a = a + Angle(2.0 * PI);
259 if (a <= b) { return full(); }
260 }
261 if (b > Angle(2.0 * PI)) {
262 b = b - Angle(2.0 * PI);
263 if (a <= b) { return full(); }
264 }
265 }
266 } else {
267 // x is an erosion.
268 if (x <= Angle(-PI)) { return empty(); }
269 if (wraps()) {
270 // The uneroded interval wraps. If either a or b is not
271 // normalized, then either the eroded interval does not wrap,
272 // or it is empty.
273 if (a > Angle(2.0 * PI)) {
274 a = a - Angle(2.0 * PI);
275 if (a > b) { return empty(); }
276 }
277 if (b < Angle(0.0)) {
278 b = b + Angle(2.0 * PI);
279 if (a > b) { return empty(); }
280 }
281 } else {
282 // The uneroded interval does not wrap. If the eroded one does,
283 // then increasing a from _a and decreasing b from _b has
284 // caused a and b to cross.
285 if (a > b) { return empty(); }
286 }
287 }
288 return NormalizedAngleInterval(a, b);
289}
290
292 NormalizedAngleInterval const & i)
293{
294 return os << '[' << i.getA() << ", " << i.getB() << ']';
295}
296
297}} // namespace lsst::sphgeom
This file declares a class representing closed intervals of normalized angles, i.e.
int y
Definition SpanSet.cc:48
table::Key< int > b
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
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()
bool isFull() const
isFull returns true if this interval contains all normalized angles.
NormalizedAngleInterval()
This constructor creates an empty interval.
bool wraps() const
wraps returns true if the interval "wraps" around the 0/2π angle discontinuity, i....
NormalizedAngleInterval & clipTo(NormalizedAngle x)
clipTo shrinks this interval until all its points are in x.
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.
std::ostream & operator<<(std::ostream &, Angle const &)
Definition Angle.cc:41
constexpr double PI
Definition constants.h:43