From 2c3b6eb310797583a2e22c5eb1d9c401a6a4f7da Mon Sep 17 00:00:00 2001 From: Zixuan Chen Date: Tue, 7 Jun 2022 20:58:51 +0800 Subject: [PATCH] fix: symmetric bug --- .../tidy-tree/src/layout/tidy_layout.rs | 26 +++---------------- rust/crates/tidy-tree/src/node.rs | 8 ++++++ .../crates/tidy-tree/tests/aesthetic_rules.rs | 19 +++++++------- rust/crates/tidy-tree/tests/layout_test.rs | 26 +++++++++++++++++-- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/rust/crates/tidy-tree/src/layout/tidy_layout.rs b/rust/crates/tidy-tree/src/layout/tidy_layout.rs index ef31ba7..44982aa 100644 --- a/rust/crates/tidy-tree/src/layout/tidy_layout.rs +++ b/rust/crates/tidy-tree/src/layout/tidy_layout.rs @@ -151,6 +151,9 @@ impl Node { let last = self.children.last().unwrap(); let last_child_pos = last.relative_x + last.tidy().modifier_to_subtree; self.relative_x = (first_child_pos + last_child_pos) / 2.; + // make modifier_to_subtree + relative_x = 0. so that + // there will always be collision in `separation()`'s first loop + self.tidy_mut().modifier_to_subtree = -self.relative_x; } fn add_child_spacing(&mut self) { @@ -289,27 +292,6 @@ impl TidyLayout { self.first_walk(node.children.first_mut().unwrap()); let mut y_list = LinkedYList::new(0, node.children[0].extreme_right().bottom()); - // if node.children[0] - // .extreme_right() - // .tidy() - // .thread_right - // .is_some() - // { - // println!("HHHHHHHH"); - // println!("{:#?}", node.children[0]); - // println!("Extreme right"); - // println!("{:#?}", node.children[0].extreme_right()); - // println!("RIGHT"); - // println!("{:#?}", unsafe { - // node.children[0] - // .extreme_right() - // .tidy() - // .thread_right - // .unwrap() - // .as_ref() - // }); - // panic!(); - // } for i in 1..node.children.len() { let current_child = node.children.get_mut(i).unwrap(); self.first_walk(current_child); @@ -353,7 +335,7 @@ impl Layout for TidyLayout { }); self.set_y(root); self.first_walk(root); - self.second_walk(root, -root.relative_x); + self.second_walk(root, 0.); } fn partial_layout( diff --git a/rust/crates/tidy-tree/src/node.rs b/rust/crates/tidy-tree/src/node.rs index 2ee3c3c..06e05ef 100644 --- a/rust/crates/tidy-tree/src/node.rs +++ b/rust/crates/tidy-tree/src/node.rs @@ -128,6 +128,14 @@ impl Node { node } + pub fn new_with_children(id: usize, width: Coord, height: Coord, children: Vec) -> Self { + let mut node = Node::new(id, width, height); + for child in children { + node.append_child(child); + } + node + } + pub fn intersects(&self, other: &Self) -> bool { self.x - self.width / 2. < other.x + other.width / 2. && self.x + self.width / 2. > other.x - other.width / 2. diff --git a/rust/crates/tidy-tree/tests/aesthetic_rules.rs b/rust/crates/tidy-tree/tests/aesthetic_rules.rs index fb1b952..f38d504 100644 --- a/rust/crates/tidy-tree/tests/aesthetic_rules.rs +++ b/rust/crates/tidy-tree/tests/aesthetic_rules.rs @@ -50,7 +50,7 @@ pub fn assert_no_crossed_lines(root: &Node) { let line = Line { from: Point { x: node.x, - y: node.y, + y: node.y + node.height, }, to: Point { x: child.x, @@ -88,17 +88,14 @@ pub fn assert_symmetric(root: &Node, layout: &mut dyn Layout) { pre_order_traversal_rev(&mirrored, |node| { point_mirrored.push(node.x); }); - println!("{}", root.str()); - println!("{}", mirrored.str()); assert_eq!(point_origin.len(), point_mirrored.len()); for i in 0..point_origin.len() { - assert!( - (point_origin[i] + point_mirrored[i]).abs() <= 1e-6, - "{} != {}", - point_origin[i], - -point_mirrored[i] - ) + if (point_origin[i] + point_mirrored[i]).abs() > 1e-6 { + println!("{}", root.str()); + println!("{}", mirrored.str()); + panic!("{} != {}", point_origin[i], point_mirrored[i]); + } } fn pre_order_traversal_rev(node: &Node, mut f: F) @@ -119,6 +116,10 @@ pub fn assert_symmetric(root: &Node, layout: &mut dyn Layout) { fn mirror(root: &Node) -> Node { let mut root = root.clone(); root.post_order_traversal_mut(|node| { + node.x = 0.; + node.y = 0.; + node.relative_x = 0.; + node.relative_y = 0.; let n = node.children.len(); for i in 0..n / 2 { node.children.swap(i, n - i - 1); diff --git a/rust/crates/tidy-tree/tests/layout_test.rs b/rust/crates/tidy-tree/tests/layout_test.rs index b6e74fb..af56de0 100644 --- a/rust/crates/tidy-tree/tests/layout_test.rs +++ b/rust/crates/tidy-tree/tests/layout_test.rs @@ -7,14 +7,14 @@ use tidy_tree::{geometry::Coord, BasicLayout, Layout, Node, TidyLayout}; pub fn test_layout(layout: &mut dyn Layout) { let mut rng = StdRng::seed_from_u64(1001); for _ in 0..100 { - let mut tree = gen_tree(&mut rng, 200); + let mut tree = gen_tree(&mut rng, 500); layout.layout(&mut tree); - // aesthetic_rules::assert_symmetric(&tree, layout); aesthetic_rules::assert_no_overlap_nodes(&tree); aesthetic_rules::assert_no_crossed_lines(&tree); aesthetic_rules::check_nodes_order(&tree); aesthetic_rules::check_y_position_in_same_level(&tree); aesthetic_rules::assert_parent_centered(&tree); + aesthetic_rules::assert_symmetric(&tree, layout); } } @@ -88,3 +88,25 @@ fn test_tidy_layout2() { // println!("{}", root.str()); aesthetic_rules::assert_symmetric(&root, &mut tidy); } + +#[test] +fn test_tidy_layout3() { + let mut tidy = TidyLayout::new(1., 1.); + let mut root = Node::new(0, 8., 7.); + root.append_child(Node::new_with_children( + 1, + 3., + 9., + vec![ + Node::new(10, 3., 8.), + Node::new(10, 5., 5.), + Node::new(10, 6., 8.), + ], + )); + root.append_child(Node::new(3, 1., 1.)); + + tidy.layout(&mut root); + // println!("{}", root.str()); + aesthetic_rules::assert_no_overlap_nodes(&root); + aesthetic_rules::assert_symmetric(&root, &mut tidy); +}