1mod tree;
2
3use std::collections::HashMap;
4
5pub type SmallVec<T> = smallvec::SmallVec<[T; 4]>;
6type MediumVec<T> = smallvec::SmallVec<[T; 16]>;
7
8#[derive(Clone, Copy, Debug)]
9pub struct Dimensions {
10 pub top: f64,
11 pub right: f64,
12 pub bottom: f64,
13 pub left: f64,
14}
15
16impl Dimensions {
17 pub fn all(size: f64) -> Dimensions {
18 Dimensions {
19 top: size,
20 right: size,
21 bottom: size,
22 left: size,
23 }
24 }
25}
26
27pub trait NodeInfo<N>
107where
108 Self::Key: std::cmp::Eq + std::hash::Hash,
109 N: Copy,
110{
111 type Key;
112
113 fn key(&self, node: N) -> Self::Key;
115
116 fn children(&self, node: N) -> SmallVec<N>;
118
119 fn dimensions(&self, _node: N) -> Dimensions {
136 Dimensions::all(0.0)
137 }
138
139 fn border(&self, _node: N) -> Dimensions {
147 Dimensions::all(0.5)
148 }
149}
150
151#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
152pub struct Coordinate {
153 pub x: f64,
159 pub y: f64,
165}
166
167#[derive(Clone, Debug)]
168struct Data<K> {
169 key: K,
170
171 x: f64,
172 y: f64,
173 mod_: f64,
174
175 dimensions: Dimensions,
176 border: Dimensions,
177}
178
179impl<K> Data<K> {
180 fn top_space(&self) -> f64 {
181 self.dimensions.top + self.border.top
182 }
183
184 #[allow(dead_code)]
185 fn top(&self) -> f64 {
186 self.y - self.top_space()
187 }
188
189 fn bottom_space(&self) -> f64 {
190 self.dimensions.bottom + self.border.bottom
191 }
192
193 fn bottom(&self) -> f64 {
194 self.y + self.bottom_space()
195 }
196
197 fn left_space(&self) -> f64 {
198 self.dimensions.left + self.border.left
199 }
200
201 fn left(&self) -> f64 {
202 self.x - self.left_space()
203 }
204
205 fn right_space(&self) -> f64 {
206 self.dimensions.right + self.border.right
207 }
208
209 fn right(&self) -> f64 {
210 self.x + self.right_space()
211 }
212}
213
214pub fn layout<N, T>(tree: &T, root: N) -> HashMap<T::Key, Coordinate>
227where
228 N: Copy,
229 T: NodeInfo<N>,
230{
231 let mut tree = tree::Tree::new(tree, root, |t, n| Data {
232 key: t.key(n),
233
234 x: 0.0,
235 y: 0.0,
236 mod_: 0.0,
237
238 dimensions: t.dimensions(n),
239 border: t.border(n),
240 });
241
242 if let Some(root) = tree.root() {
243 initialise_y(&mut tree, root);
244
245 initialise_x(&mut tree, root);
246 ensure_positive_x(&mut tree, root);
247 finalise_x(&mut tree, root);
248
249 tree.0
250 .into_iter()
251 .map(|tree::Node { data: d, .. }| (d.key, Coordinate { x: d.x, y: d.y }))
252 .collect()
253 } else {
254 HashMap::new()
255 }
256}
257
258fn initialise_y<K>(tree: &mut tree::Tree<Data<K>>, root: usize) {
259 let mut next_row = MediumVec::from_elem(root, 1);
260
261 while !next_row.is_empty() {
262 let row = next_row;
263 next_row = MediumVec::new();
264
265 let mut max = -std::f64::INFINITY;
266 for node in &row {
267 let node = *node;
268
269 tree[node].data.y = if let Some(parent) = tree[node].parent {
270 tree[parent].data.bottom()
271 } else {
272 0.0
273 } + tree[node].data.top_space();
274
275 if tree[node].data.y > max {
276 max = tree[node].data.y;
277 }
278
279 next_row.extend_from_slice(&tree[node].children);
280 }
281
282 for node in &row {
283 tree[*node].data.y = max;
284 }
285 }
286}
287
288fn initialise_x<K>(tree: &mut tree::Tree<Data<K>>, root: usize) {
289 for node in tree.post_order(root) {
290 if tree[node].is_leaf() {
291 tree[node].data.x = if let Some(sibling) = tree.previous_sibling(node) {
292 tree[sibling].data.right()
293 } else {
294 0.0
295 } + tree[node].data.left_space();
296 } else {
297 let mid = {
298 let first = tree[*tree[node]
299 .children
300 .first()
301 .expect("Only leaf nodes have no children.")]
302 .data
303 .x;
304 let last = tree[*tree[node]
305 .children
306 .last()
307 .expect("Only leaf nodes have no children.")]
308 .data
309 .x;
310
311 (first + last) / 2.0
312 };
313
314 if let Some(sibling) = tree.previous_sibling(node) {
315 tree[node].data.x = tree[sibling].data.right() + tree[node].data.left_space();
316 tree[node].data.mod_ = tree[node].data.x - mid;
317 } else {
318 tree[node].data.x = mid;
319 }
320
321 fix_overlaps(tree, node);
322 }
323 }
324}
325
326fn fix_overlaps<K>(tree: &mut tree::Tree<Data<K>>, right: usize) {
327 fn max_depth(l: &HashMap<usize, f64>, r: &HashMap<usize, f64>) -> usize {
328 if let Some(l) = l.keys().max() {
329 if let Some(r) = r.keys().max() {
330 return std::cmp::min(*l, *r);
331 }
332 }
333
334 0
335 }
336
337 let right_node_contour = left_contour(tree, right);
338
339 for left in tree.left_siblings(right) {
340 let left_node_contour = right_contour(tree, left);
341 let mut shift = 0.0;
342
343 for depth in tree[right].depth..=max_depth(&right_node_contour, &left_node_contour) {
344 let gap = right_node_contour[&depth] - left_node_contour[&depth];
345 if gap + shift < 0.0 {
346 shift = -gap;
347 }
348 }
349
350 tree[right].data.x += shift;
351 tree[right].data.mod_ += shift;
352
353 centre_nodes_between(tree, left, right);
354 }
355}
356
357fn left_contour<K>(tree: &tree::Tree<Data<K>>, node: usize) -> HashMap<usize, f64> {
358 contour(tree, node, min, |n| n.data.left())
359}
360
361fn right_contour<K>(tree: &tree::Tree<Data<K>>, node: usize) -> HashMap<usize, f64> {
362 contour(tree, node, max, |n| n.data.right())
363}
364
365fn min<T: std::cmp::PartialOrd>(l: T, r: T) -> T {
366 if l < r {
367 l
368 } else {
369 r
370 }
371}
372
373fn max<T: std::cmp::PartialOrd>(l: T, r: T) -> T {
374 if l > r {
375 l
376 } else {
377 r
378 }
379}
380
381fn contour<C, E, K>(tree: &tree::Tree<Data<K>>, node: usize, cmp: C, edge: E) -> HashMap<usize, f64>
382where
383 C: Fn(f64, f64) -> f64,
384 E: Fn(&tree::Node<Data<K>>) -> f64,
385{
386 let mut stack = MediumVec::from_elem((0.0, node), 1);
387 let mut contour = HashMap::new();
388
389 while let Some((mod_, node)) = stack.pop() {
390 let depth = tree[node].depth;
391 let shifted = edge(&tree[node]) + mod_;
392 let new = if let Some(current) = contour.get(&depth) {
393 cmp(*current, shifted)
394 } else {
395 shifted
396 };
397 let mod_ = mod_ + tree[node].data.mod_;
398
399 contour.insert(depth, new);
400 stack.extend(tree[node].children.iter().map(|c| (mod_, *c)));
401 }
402
403 contour
404}
405
406fn centre_nodes_between<K>(tree: &mut tree::Tree<Data<K>>, left: usize, right: usize) {
407 let num_gaps = tree[right].order - tree[left].order;
408
409 let space_per_gap = (tree[right].data.left() - tree[left].data.right()) / (num_gaps as f64);
410
411 for (i, sibling) in tree.siblings_between(left, right).into_iter().enumerate() {
412 let i = i + 1;
413
414 let old_x = tree[sibling].data.x;
415 let new_x = max(old_x, tree[left].data.right() + space_per_gap * (i as f64));
419 let diff = new_x - old_x;
420
421 tree[sibling].data.x = new_x;
422 tree[sibling].data.mod_ += diff;
423 }
424}
425
426fn ensure_positive_x<K>(tree: &mut tree::Tree<Data<K>>, root: usize) {
427 let contour = left_contour(tree, root);
428 let shift = -contour
429 .values()
430 .fold(None, |acc, curr| {
431 let acc = acc.unwrap_or(std::f64::INFINITY);
432 let curr = *curr;
433 Some(if curr < acc { curr } else { acc })
434 })
435 .unwrap_or(0.0);
436
437 tree[root].data.x += shift;
438 tree[root].data.mod_ += shift;
439}
440
441fn finalise_x<K>(tree: &mut tree::Tree<Data<K>>, root: usize) {
442 for node in tree.breadth_first(root) {
443 let shift = if let Some(parent) = tree[node].parent {
444 tree[parent].data.mod_
445 } else {
446 0.0
447 };
448
449 tree[node].data.x += shift;
450 tree[node].data.mod_ += shift;
451 }
452}