-
Notifications
You must be signed in to change notification settings - Fork 13
/
TileIndex.h
163 lines (129 loc) · 4.2 KB
/
TileIndex.h
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
#ifndef INCLUDE_TILE_INDEX_H
#define INCLUDE_TILE_INDEX_H
// System
#include <assert.h>
#include <limits.h>
#include <limits>
#include <math.h>
// Local
#include "Range.h"
#include "utils.h"
#include "sizes.h"
struct TileIndex {
int32 level;
int64 offset;
TileIndex(int level_init, long long offset_init) :
level(level_init), offset(offset_init) {}
TileIndex() : level(0), offset(-1LL) {}
static TileIndex nonnegative_all() {
return TileIndex(INT_MAX, 0);
}
static TileIndex negative_all() {
return TileIndex(INT_MAX, -1);
}
static TileIndex null() {
return TileIndex(INT_MIN, 0);
}
static int32_t lowest_level() {
return INT_MIN;
}
bool is_nonnegative_all() const {
return level == INT_MAX && offset == 0;
}
bool is_negative_all() const {
return level == INT_MAX && offset == -1;
}
bool is_all() const {
return level == INT_MAX;
}
bool is_null() const {
return level == INT_MIN && offset == 0;
}
double start_time() const {
if (is_null()) return std::numeric_limits<double>::max();
if (is_negative_all()) return -std::numeric_limits<double>::max();
if (is_nonnegative_all()) return 0;
return duration()*offset;
}
double end_time() const {
if (is_null()) return -std::numeric_limits<double>::max();
if (is_negative_all()) return 0;
if (is_nonnegative_all()) return std::numeric_limits<double>::max();
return duration()*(offset+1);
}
bool contains_time(double time) const {
return start_time() <= time && time < end_time();
}
double position(double time) const {
return (time - start_time()) / duration();
}
double duration() const {
return level_to_duration(level);
}
static double level_to_duration(int level) {
return pow(2.0, level);
}
static double duration_to_level(double duration) {
return log2(duration);
}
static double level_to_bin_secs(int level) {
assert(0);
}
std::string to_string() const {
if (is_null()) return "[null]";
if (is_nonnegative_all()) return "[nonnegative_all]";
if (is_negative_all()) return "[negative_all]";
return string_printf("%d.%lld", level, offset);
}
static TileIndex index_at_level_containing(int level, double time) {
return TileIndex(level, (long long)floor(time / level_to_duration(level)));
}
/// Select level according to max_time-min_time, selecting tile that contains min_time, then move to parents until max_time is contained
/// Only works if min and max times are both negative, or nonnegative
static TileIndex index_containing(Range times) {
assert(times.min < times.max);
assert(times.min >= 0 || times.max < 0);
int level = (int)floor(log2(times.max - times.min));
TileIndex ret = index_at_level_containing(level, times.min);
while (!ret.contains_time(times.max)) ret = ret.parent();
//fprintf(stderr, "index_containing(%g, %g)=%s\n", times.min, times.max, ret.to_string().c_str());
return ret;
}
bool operator==(const TileIndex &rhs) const {
return level == rhs.level && offset == rhs.offset;
}
bool operator!=(const TileIndex &rhs) const {
return !(*this == rhs);
}
/// Less than. Tiles are ordered first by level, then by offset
bool operator<(const TileIndex &rhs) const {
return level == rhs.level ? offset < rhs.offset : level < rhs.level;
}
// Is TileIndex ancestor of child?
// \return true if TileIndex is parent of child, or a higher ancestor. false if not. false if identical to child
bool is_ancestor_of(const TileIndex &child) const {
return (level > child.level) && (offset == (child.offset >> (unsigned)(level-child.level)));
}
/// Return parent
/// \return parent of TileIndex
TileIndex parent() const {
if (is_all()) return null();
return TileIndex(level+1, offset>>1);
}
/// Return left child
/// \return left child of TileIndex
TileIndex left_child() const {
if (is_all()) return null();
return TileIndex(level-1, offset*2);
}
/// Return right child
/// \return right child of TileIndex
TileIndex right_child() const {
if (is_all()) return null();
return TileIndex(level-1, offset*2+1);
}
TileIndex sibling() const {
return TileIndex(level, offset ^ 1);
}
};
#endif