docvortex_core/
annotation_geometry.rs1use crate::geometry::Box4;
3use std::collections::{HashMap, HashSet};
4
5pub type Fragment = (usize, Box4, Box4);
6pub type Output = (Vec<(usize, [usize; 4], usize)>, Option<[usize; 4]>);
7
8pub struct AnnotationGeometry {
9 fragments: Vec<Fragment>,
10}
11
12impl AnnotationGeometry {
13 pub fn new(fragments: Vec<Fragment>) -> Option<Self> {
15 if fragments.iter().any(|f| {
16 f.1.iter()
17 .chain(f.2.iter())
18 .any(|v| !v.is_finite() || v.abs() > 1e100)
19 }) {
20 return None;
21 }
22 Some(Self { fragments })
23 }
24
25 fn combine(&self, a: [usize; 4], b: [usize; 4]) -> [usize; 4] {
27 let mut result = a;
28 for k in 0..4 {
29 let av = self.fragments[a[k]].1[k];
30 let bv = self.fragments[b[k]].1[k];
31 if (k < 2 && bv < av) || (k >= 2 && bv > av) {
32 result[k] = b[k];
33 }
34 }
35 result
36 }
37
38 pub fn aggregate(
40 &self,
41 selected: Vec<usize>,
42 excluded: Vec<usize>,
43 local: Option<Box4>,
44 ) -> Option<Output> {
45 if selected.iter().any(|i| *i >= self.fragments.len())
46 || local.is_some_and(|b| b.iter().any(|v| !v.is_finite() || v.abs() > 1e100))
47 {
48 return None;
49 }
50 let excluded: HashSet<_> = excluded.into_iter().collect();
51 let mut positions = HashMap::new();
52 let mut lines: Vec<(usize, [usize; 4], usize)> = Vec::new();
53 for i in selected {
54 let (source, _, b) = self.fragments[i];
55 if excluded.contains(&source) {
56 continue;
57 }
58 if let Some(region) = local {
59 let smaller = (b[2] - b[0]).min(region[2] - region[0]);
60 let overlap = 0.0_f64.max(b[2].min(region[2]) - b[0].max(region[0]));
61 let ratio = if smaller > 0.0 {
62 overlap / smaller
63 } else {
64 0.0
65 };
66 if b[3] > region[1] && ratio >= 0.05 {
67 continue;
68 }
69 }
70 if let Some(&position) = positions.get(&source) {
71 let line: &mut (usize, [usize; 4], usize) = &mut lines[position];
72 line.1 = self.combine(line.1, [i; 4]);
73 line.2 += 1;
74 } else {
75 positions.insert(source, lines.len());
76 lines.push((source, [i; 4], 1));
77 }
78 }
79 let union = lines.iter().map(|v| v.1).reduce(|a, b| self.combine(a, b));
80 Some((lines, union))
81 }
82}