docvortex_core/
note_index.rs1#[derive(Clone, Copy, Default)]
4struct Node {
5 left: usize,
6 right: usize,
7 count: usize,
8}
9
10pub struct HeightIndex {
11 nodes: Vec<Node>,
12 roots: Vec<usize>,
13 centers: Vec<f64>,
14 heights: Vec<f64>,
15}
16
17impl HeightIndex {
18 pub fn new(items: &[(i64, f64, f64)]) -> Self {
20 let mut order: Vec<usize> = (0..items.len()).collect();
21 order.sort_by(|&a, &b| items[a].2.partial_cmp(&items[b].2).unwrap());
22 let mut ranks = vec![0; items.len()];
23 let heights = order.iter().map(|&i| items[i].2).collect();
24 for (rank, &index) in order.iter().enumerate() {
25 ranks[index] = rank;
26 }
27 order.sort_by(|&a, &b| items[a].1.partial_cmp(&items[b].1).unwrap());
28 let mut result = Self {
29 nodes: vec![Node::default()],
30 roots: vec![0],
31 centers: Vec::new(),
32 heights,
33 };
34 for index in order {
35 let root = result.insert(*result.roots.last().unwrap(), 0, items.len(), ranks[index]);
36 result.roots.push(root);
37 result.centers.push(items[index].1);
38 }
39 result
40 }
41
42 fn insert(&mut self, previous: usize, low: usize, high: usize, rank: usize) -> usize {
44 let mut node = self.nodes[previous];
45 node.count += 1;
46 if high - low > 1 {
47 let middle = (low + high) / 2;
48 if rank < middle {
49 node.left = self.insert(node.left, low, middle, rank);
50 } else {
51 node.right = self.insert(node.right, middle, high, rank);
52 }
53 }
54 self.nodes.push(node);
55 self.nodes.len() - 1
56 }
57
58 fn select(&self, mut left: usize, mut total: usize, mut right: usize, mut rank: usize) -> f64 {
60 let (mut low, mut high) = (0, self.heights.len());
61 while high - low > 1 {
62 let a = self.nodes[left];
63 let b = self.nodes[total];
64 let c = self.nodes[right];
65 let count =
66 self.nodes[a.left].count + self.nodes[b.left].count - self.nodes[c.left].count;
67 let middle = (low + high) / 2;
68 if rank < count {
69 left = a.left;
70 total = b.left;
71 right = c.left;
72 high = middle;
73 } else {
74 rank -= count;
75 left = a.right;
76 total = b.right;
77 right = c.right;
78 low = middle;
79 }
80 }
81 self.heights[low]
82 }
83
84 pub fn height(&self, top: f64, bottom: f64, fallback: f64) -> Option<f64> {
86 if !top.is_finite() || !bottom.is_finite() || top > bottom || !fallback.is_finite() {
87 return None;
88 }
89 let left = self.centers.partition_point(|&y| y < top);
90 let right = self.centers.partition_point(|&y| y <= bottom);
91 let n = left + self.centers.len() - right;
92 if n < 4 {
93 return Some(fallback);
94 }
95 let count = n.div_ceil(4);
96 let rank = n - count + count / 2;
97 let a = self.select(
98 self.roots[left],
99 *self.roots.last().unwrap(),
100 self.roots[right],
101 rank,
102 );
103 let result = if count % 2 == 1 {
104 a
105 } else {
106 let b = self.select(
107 self.roots[left],
108 *self.roots.last().unwrap(),
109 self.roots[right],
110 rank - 1,
111 );
112 (b + a) / 2.0
113 };
114 result.is_finite().then_some(result)
115 }
116}
117
118pub struct CoreRows {
119 pub members: Vec<Vec<i64>>,
120 size: usize,
121 extents: Vec<(f64, f64)>,
122}
123
124impl CoreRows {
125 pub fn new(
127 members: Vec<Vec<i64>>,
128 extents: &std::collections::HashMap<i64, (f64, f64)>,
129 ) -> Self {
130 let size = members.len().max(1).next_power_of_two();
131 let mut tree = vec![(f64::INFINITY, f64::NEG_INFINITY); size * 2];
132 for (row, ids) in members.iter().enumerate() {
133 for id in ids {
134 if let Some(&(a, b)) = extents.get(id) {
135 tree[size + row].0 = tree[size + row].0.min(a);
136 tree[size + row].1 = tree[size + row].1.max(b);
137 }
138 }
139 }
140 for i in (1..size).rev() {
141 tree[i] = (
142 tree[i * 2].0.min(tree[i * 2 + 1].0),
143 tree[i * 2].1.max(tree[i * 2 + 1].1),
144 );
145 }
146 Self {
147 members,
148 size,
149 extents: tree,
150 }
151 }
152
153 pub fn contained(&self, start: usize, end: usize, top: f64, bottom: f64) -> bool {
155 let (mut l, mut r) = (start + self.size, end + self.size);
156 while l < r {
157 if l % 2 == 1 {
158 if self.extents[l].0 < top || self.extents[l].1 > bottom {
159 return false;
160 }
161 l += 1;
162 }
163 if r % 2 == 1 {
164 r -= 1;
165 if self.extents[r].0 < top || self.extents[r].1 > bottom {
166 return false;
167 }
168 }
169 l /= 2;
170 r /= 2;
171 }
172 true
173 }
174}