docvortex_core/
extraction.rs1use crate::geometry::{Box4, Size};
4pub type RawGeometry = (Box4, Option<Box4>, Option<Box4>, Option<Size>);
5pub type VisualGeometry = (Box4, Option<Box4>, Option<Box4>, Option<Size>);
6
7fn minimum(a: f64, b: f64) -> f64 {
9 if b < a {
10 b
11 } else {
12 a
13 }
14}
15fn maximum(a: f64, b: f64) -> f64 {
17 if b > a {
18 b
19 } else {
20 a
21 }
22}
23
24fn point(p: Size, frame: Box4, angle: i32) -> Size {
26 let w = (frame[2] - frame[0]).abs();
27 let h = (frame[3] - frame[1]).abs();
28 let x = p[0] - minimum(frame[0], frame[2]);
29 let y = maximum(frame[1], frame[3]) - p[1];
30 match angle.rem_euclid(360) {
31 90 => [h - y, x],
32 180 => [w - x, h - y],
33 270 => [y, w - x],
34 _ => [x, y],
35 }
36}
37
38fn visual(raw: Option<Box4>, frame: Box4, angle: i32) -> Option<Box4> {
40 let b = raw?;
41 let points =
42 [[b[0], b[1]], [b[0], b[3]], [b[2], b[1]], [b[2], b[3]]].map(|p| point(p, frame, angle));
43 let mut out = [points[0][0], points[0][1], points[0][0], points[0][1]];
44 for p in &points[1..] {
45 out = [
46 minimum(out[0], p[0]),
47 minimum(out[1], p[1]),
48 maximum(out[2], p[0]),
49 maximum(out[3], p[1]),
50 ];
51 }
52 if out.iter().all(|v| v.is_finite()) && out[2] > out[0] && out[3] > out[1] {
53 Some(out)
54 } else {
55 None
56 }
57}
58
59pub fn materialize(
61 rows: Vec<RawGeometry>,
62 frame: Box4,
63 rounded: Size,
64 angle: i32,
65) -> Vec<VisualGeometry> {
66 rows.into_iter()
67 .map(|(selected, loose, tight, origin)| {
68 let y0 = rounded[1] - (selected[1] - frame[1]);
69 let y1 = rounded[1] - (selected[3] - frame[1]);
70 let mut layout = [
71 minimum(selected[0], selected[2]) - frame[0],
72 minimum(y0, y1),
73 maximum(selected[0], selected[2]) - frame[0],
74 maximum(y0, y1),
75 ];
76 if angle != 0 {
77 layout = crate::geometry::rotate(layout, rounded, (360 - angle).rem_euclid(360));
78 layout = [
79 minimum(layout[0], layout[2]),
80 minimum(layout[1], layout[3]),
81 maximum(layout[0], layout[2]),
82 maximum(layout[1], layout[3]),
83 ];
84 }
85 let origin = origin
86 .map(|p| point(p, frame, angle))
87 .filter(|p| p.iter().all(|v| v.is_finite()));
88 (
89 layout,
90 visual(loose, frame, angle),
91 visual(tight, frame, angle),
92 origin,
93 )
94 })
95 .collect()
96}