use std::collections::BTreeMap;
use itertools::Itertools as _;
use re_log_types::{TimeInt, TimeRange, TimeType};
#[derive(Clone, Debug)]
pub(crate) struct TimelineAxis {
pub ranges: vec1::Vec1<TimeRange>,
}
impl TimelineAxis {
pub fn new<T>(time_type: TimeType, times: &BTreeMap<TimeInt, T>) -> Self {
crate::profile_function!();
assert!(!times.is_empty());
let time_abs_diff = |a: TimeInt, b: TimeInt| -> u64 { a.as_i64().abs_diff(b.as_i64()) };
let min_gap_size: u64 = match time_type {
TimeType::Sequence => 9,
TimeType::Time => 1_000_000_000, };
let mut gap_sizes = {
crate::profile_scope!("collect_gaps");
times
.keys()
.tuple_windows()
.map(|(a, b)| time_abs_diff(*a, *b))
.filter(|&gap_size| gap_size > min_gap_size)
.collect_vec()
};
gap_sizes.sort_unstable();
let mut gap_threshold = min_gap_size;
for gap in gap_sizes {
if gap >= gap_threshold * 2 {
break; } else if gap > gap_threshold {
gap_threshold *= 2;
}
}
crate::profile_scope!("create_ranges");
let mut values_it = times.keys();
let mut ranges = vec1::vec1![TimeRange::point(*values_it.next().unwrap())];
for &new_value in values_it {
let last_max = &mut ranges.last_mut().max;
if time_abs_diff(*last_max, new_value) <= gap_threshold {
*last_max = new_value; } else {
ranges.push(TimeRange::point(new_value)); }
}
Self { ranges }
}
pub fn sum_time_lengths(&self) -> TimeInt {
self.ranges.iter().map(|t| t.length()).sum()
}
pub fn min(&self) -> TimeInt {
self.ranges.first().min
}
}