1use crate::path_index::IndexBuilder;
2use crate::{Layer, PathDataTrait, Point};
3
4impl Layer {
5 pub fn sort(&mut self, flip: bool) {
10 self.sort_with_builder(IndexBuilder::default().flip(flip));
11 }
12
13 #[allow(clippy::missing_panics_doc)]
14 pub fn sort_with_builder(&mut self, builder: IndexBuilder) {
15 if self.paths.len() <= 1 {
16 return;
17 }
18
19 let mut new_paths = Vec::with_capacity(self.paths.len());
20 let mut index = builder.build(&self.paths);
21
22 let mut pos = Point::ZERO;
23 while let Some((path_item, reverse)) = index.pop_nearest(&pos) {
24 new_paths.push((*path_item.path).clone());
25 if reverse {
26 pos = path_item.start.unwrap_or(pos);
27 new_paths.last_mut().expect("just inserted").data.flip();
28 } else {
29 pos = path_item.end.unwrap_or(pos);
30 }
31 }
32
33 while let Some(path_item) = index.pop_first() {
35 new_paths.push((*path_item.path).clone());
36 }
37
38 self.paths = new_paths;
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::{test_file, Document, DocumentTrait, FlattenedLayer, FlattenedPath, LayerTrait};
46
47 #[test]
48 fn test_sort() {
49 let mut layer = FlattenedLayer::default();
50
51 let p1 = FlattenedPath::from(vec![Point::new(10.0, 10.1), Point::new(0.0, 0.0)]);
52 let p2 = FlattenedPath::from(vec![Point::new(3.0, 2.3), Point::new(10.0, 10.0)]);
53 let p3 = FlattenedPath::from(vec![Point::new(1.0, 0.0), Point::new(0.0, 0.0)]);
54 let p4 = FlattenedPath::from(vec![Point::new(2.0, 1.0), Point::new(1.0, 0.1)]);
55
56 layer.paths.push(p1.clone());
57 layer.paths.push(p2.clone());
58 layer.paths.push(p3.clone());
59 layer.paths.push(p4.clone());
60
61 layer.sort(false);
62
63 assert_eq!(layer.paths[0], p3);
64 assert_eq!(layer.paths[1], p4);
65 assert_eq!(layer.paths[2], p2);
66 assert_eq!(layer.paths[3], p1);
67 }
68
69 #[test]
70 fn test_sort_bidir() {
71 let mut layer = FlattenedLayer::default();
72
73 let p1 = FlattenedPath::from(vec![Point::new(10.0, 10.1), Point::new(20.0, 20.0)]);
74 let p2 = FlattenedPath::from(vec![Point::new(3.0, 2.3), Point::new(10.0, 10.0)]);
75 let mut p3 = FlattenedPath::from(vec![Point::new(1.0, 0.0), Point::new(0.0, 0.0)]);
76 let mut p4 = FlattenedPath::from(vec![Point::new(3.0, 2.0), Point::new(1.0, 0.1)]);
77
78 layer.paths.push(p1.clone());
79 layer.paths.push(p2.clone());
80 layer.paths.push(p3.clone());
81 layer.paths.push(p4.clone());
82
83 layer.sort(true);
84
85 p3.data.flip();
86 assert_eq!(layer.paths[0], p3);
87 p4.data.flip();
88 assert_eq!(layer.paths[1], p4);
89 assert_eq!(layer.paths[2], p2);
90 assert_eq!(layer.paths[3], p1);
91 }
92
93 #[test]
94 fn test_sort_problematic_case() {
95 let mut doc = Document::from_svg(test_file!("random_100_sort.svg"), false).unwrap();
96 doc.get_mut(1).sort(true);
97 }
98}