-
Notifications
You must be signed in to change notification settings - Fork 4
/
interval.cpp
79 lines (63 loc) · 2.45 KB
/
interval.cpp
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
#include "interval.h"
#include "fmt/core.h"
namespace pivid {
IntervalSet::iterator IntervalSet::insert(Interval add) {
if (add.begin >= add.end) return ranges.end();
auto next_contact = ranges.upper_bound(add);
if (next_contact != ranges.begin()) {
auto const at_or_before = std::prev(next_contact);
if (at_or_before->end >= add.end) return next_contact;
if (at_or_before->end >= add.begin) {
next_contact = at_or_before;
add.begin = at_or_before->begin;
}
}
while (next_contact != ranges.end() && next_contact->begin <= add.end) {
if (next_contact->end > add.end) add.end = next_contact->end;
next_contact = ranges.erase(next_contact);
}
return ranges.insert(add).first;
}
IntervalSet::iterator IntervalSet::erase(Interval remove) {
if (remove.begin >= remove.end) return ranges.end();
auto next_overlap = ranges.upper_bound(remove);
if (next_overlap != ranges.begin()) {
auto const at_or_before = std::prev(next_overlap);
if (at_or_before->end > remove.begin) next_overlap = at_or_before;
}
while (next_overlap != ranges.end() && next_overlap->begin < remove.end) {
auto const overlap = *next_overlap;
next_overlap = ranges.erase(next_overlap);
if (overlap.begin < remove.begin)
ranges.insert({overlap.begin, remove.begin});
if (overlap.end > remove.end)
ranges.insert({remove.end, overlap.end});
}
return next_overlap;
}
IntervalSet::iterator IntervalSet::overlap_begin(double value) const {
auto const next_after = ranges.upper_bound({value, {}});
if (next_after == ranges.begin()) return next_after;
auto const at_or_before = std::prev(next_after);
return (at_or_before->end > value) ? at_or_before : next_after;
}
bool IntervalSet::contains(double value) const {
auto const iter = overlap_begin(value);
return iter != ranges.end() && iter->begin <= value;
}
Interval IntervalSet::bounds() const {
if (empty()) return {};
return {ranges.begin()->begin, ranges.rbegin()->end};
}
std::string debug(Interval interval) {
return fmt::format("{:.3f}~{:.3f}s", interval.begin, interval.end);
}
std::string debug(IntervalSet const& interval_set) {
std::string out = "{";
for (auto const& interval : interval_set) {
if (out.size() > 1) out += ", ";
out += pivid::debug(interval);
}
return out + "}";
}
} // namespace pivid