1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
use std::ops::{Range, Sub};
use crate::{TwoComponent, Vec2};
fn max<T: PartialOrd>(a: T, b: T) -> T {
if b > a { b } else { a }
}
fn min<T: PartialOrd>(a: T, b: T) -> T {
if a > b { b } else { a }
}
/// Trait for types that can represent range.
pub trait RangeExt: Sized + TwoComponent {
/// If the second component is smaller than the first, it returns range
/// where is the first component twice.
fn valid_range_or_empty(self) -> Self
where
Self::Val: PartialOrd + Clone,
{
let (a, b) = self.to_components();
if a > b {
Self::from_components(a.clone(), a)
} else {
Self::from_components(a, b)
}
}
/// Get the size of the range. (how much values it spans)
fn size(self) -> Self::Val
where
Self::Val: Sub<Output = Self::Val>,
{
let (a, b) = self.to_components();
b - a
}
/// Checks whether the given value is in range.
fn contains(&self, v: &Self::Val) -> bool
where
Self::Val: PartialOrd,
{
v >= self.comp1() && v < self.comp2()
}
/// Calculates intersection of the two ranges. If the intersection is empty
/// the resulting range will be of self closer to other.
fn intersect(self, other: impl Into<Self>) -> Self
where
Self::Val: PartialOrd + Clone,
{
let (s1, e1) = self.to_components();
let (s2, e2) = other.into().to_components();
if s1 >= s2 {
if e1 <= e2 {
Self::from_components(s1, e1)
} else if e2 >= s1 {
Self::from_components(s1, e2)
} else {
Self::from_components(s1.clone(), s1)
}
} else if e2 <= e1 {
Self::from_components(s2, e2)
} else if e1 >= s2 {
Self::from_components(s2, e1)
} else {
Self::from_components(e1.clone(), e1)
}
}
/// Checks whether the two ranges intersect.
fn intersects(&self, other: impl Into<Self>) -> bool
where
Self::Val: PartialOrd,
{
let other = other.into();
self.comp1() < other.comp2() && self.comp2() > other.comp1()
}
/// Checks whether the two ranges can be joined into single range.
fn touches(&self, other: impl Into<Self>) -> bool
where
Self::Val: PartialOrd,
{
let other = other.into();
self.comp1() <= other.comp2() && self.comp2() >= other.comp1()
}
/// Join the two ranges. If they cannot be joined, they are so (smaller
/// range is first).
fn join(self, other: impl Into<Self>) -> (Self, Option<Self>)
where
Self::Val: PartialOrd,
{
let (s1, e1) = self.to_components();
let (s2, e2) = other.into().to_components();
if s1 < s2 {
if e1 < s2 {
// Ranges don't touch
(
Self::from_components(s1, e1),
Some(Self::from_components(s2, e2)),
)
} else {
// Ranges touch
(Self::from_components(s1, max(e1, e2)), None)
}
} else if e2 < s1 {
// Ranges don't touch
(
Self::from_components(s2, e2),
Some(Self::from_components(s1, e1)),
)
} else {
(Self::from_components(s2, max(e1, e2)), None)
}
}
/// Join the two ranges. If they cannot be joined the resulting range will
/// also cover the gap.
fn join_gap(self, other: impl Into<Self>) -> Self
where
Self::Val: PartialOrd,
{
let (s1, e1) = self.to_components();
let (s2, e2) = other.into().to_components();
Self::from_components(min(s1, s2), max(e1, e2))
}
/// Subtract the given range from this range.
///
/// If the other range encapsulates this range, the result is range with
/// the end of the inner range in both components.
///
/// The resulting ranges are always ordered.
fn sub_range(self, other: impl Into<Self>) -> (Self, Option<Self>)
where
Self::Val: PartialOrd + Clone,
{
let (s1, e1) = self.to_components();
let (s2, e2) = other.into().to_components();
if s1 < s2 {
// self is before or over
if s2 < e1 {
// ranges overlap
if e2 < e1 {
// self is over
(
Self::from_components(s1, s2),
Some(Self::from_components(e2, e1)),
)
} else {
// self is before with overlap
(Self::from_components(s1, s2), None)
}
} else {
// Self is before without overlap
(Self::from_components(s1, e1), None)
}
} else if e1 >= e2 {
// Self is after
if s1 > e2 {
// No overlap
(Self::from_components(s1, e2), None)
} else {
// Overlap
(Self::from_components(e2, e1), None)
}
} else {
// Self is inside
(Self::from_components(e1.clone(), e1), None)
}
}
/// Subtract the given range from this range. If the other range is fully
/// inside this range, return this range.
fn sub_range_gap(self, other: impl Into<Self>) -> Self
where
Self::Val: PartialOrd + Clone,
{
let (s1, e1) = self.to_components();
let (s2, e2) = other.into().to_components();
if s1 < s2 {
// self is before or over
if s2 < e1 {
// ranges overlap
if e2 < e1 {
// self is over
Self::from_components(s1, e1)
} else {
// self is before with overlap
Self::from_components(s1, s2)
}
} else {
// Self is before without overlap
Self::from_components(s1, e1)
}
} else if e1 >= e2 {
// Self is after
if s1 > e2 {
// No overlap
Self::from_components(s1, e2)
} else {
// Overlap
Self::from_components(e2, e1)
}
} else {
// Self is inside
Self::from_components(e1.clone(), e1)
}
}
/// Calculate symetric subtraction of the two ranges.
///
/// The resulting ranges are always ordered.
fn sym_sub_range(self, other: impl Into<Self>) -> (Self, Self)
where
Self::Val: PartialOrd,
{
let (s1, e1) = self.to_components();
let (s2, e2) = other.into().to_components();
if s1 < s2 {
if s2 >= e1 {
(Self::from_components(s1, e1), Self::from_components(s2, e2))
} else if e1 < e2 {
(Self::from_components(s1, s2), Self::from_components(e1, e2))
} else {
(Self::from_components(s1, s2), Self::from_components(e2, e1))
}
} else if s1 >= e2 {
(Self::from_components(s2, e2), Self::from_components(s1, e1))
} else if e1 > e2 {
(Self::from_components(s2, s1), Self::from_components(e2, e1))
} else {
(Self::from_components(s2, s1), Self::from_components(e1, e2))
}
}
/// Check whether this range fully encloses the other range.
fn encloses(&self, other: impl Into<Self>) -> bool
where
Self::Val: PartialOrd,
{
let o = other.into();
self.comp1() <= o.comp1() && self.comp2() >= o.comp2()
}
/// Clamp the value to be in the range. Note that this may return the upper
/// bound.
fn clamp(&self, v: Self::Val) -> Self::Val
where
Self::Val: PartialOrd + Copy,
{
if v < *self.comp1() {
*self.comp1()
} else if v > *self.comp2() {
*self.comp2()
} else {
v
}
}
}
impl<T> RangeExt for Vec2<T> {}
impl<T> RangeExt for Range<T> {}