From 14cfe1db971bc77b2d4f943339469e07118dac3b Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Thu, 28 Mar 2019 22:17:46 +0100 Subject: [PATCH] Try to work on all triangle collection lengths at the same time --- src/main.rs | 214 +++++++++++++++++++++++++++++----------------------- 1 file changed, 120 insertions(+), 94 deletions(-) diff --git a/src/main.rs b/src/main.rs index ebe4489..4770790 100644 --- a/src/main.rs +++ b/src/main.rs @@ -167,113 +167,139 @@ fn main() { let save_prefix = "world_"; save_counter = 0; let mut counter = 0; - while worlds.peek().map(|x| x.width <= best.width) == Some(true) { - counter += 1; - if counter % 10000 == 0 { - println!("{}/∞", counter); - } - let w = worlds.pop().unwrap(); - //println!("s: {:?}", w); + let mut bins = Vec::new(); + bins.push(worlds); + let mut progress = true; + while progress { + progress = false; + for bin_idx in 0..bins.len() { + counter += 1; + if counter % 10000 == 0 { + println!("{}/∞", counter); + } + if bins[bin_idx].is_empty() { + continue; + } + let w = bins[bin_idx].pop().unwrap(); + //println!("working"); + if w.width >= best.width { + continue; + } + //println!("s: {:?}", w); - /* - if save_counter < 1000000 { - display::save_world(&format!("{}a_{}.svg", save_prefix, save_counter), &w); - } - */ - let save_iterations = false; + /* + if save_counter < 1000000 { + display::save_world(&format!("{}a_{}.svg", save_prefix, save_counter), &w); + } + */ + let save_iterations = false; - let mut new = vec![]; - for (next_idx, next_tri) in left_tris - .iter() - .filter(|(idx1, _tri)| w.tris.iter().all(|(idx2, _tri)| idx1 != idx2)) - { - //println!("trying {:?}", next_idx); - let (last_idx, last_tri) = *w.tris.last().unwrap(); + let mut new = vec![]; + for (next_idx, next_tri) in left_tris + .iter() + .filter(|(idx1, _tri)| w.tris.iter().all(|(idx2, _tri)| idx1 != idx2)) + { + //println!("trying {:?}", next_idx); + let (last_idx, last_tri) = *w.tris.last().unwrap(); - let vertex1 = last_tri.1; - let vertex2 = last_tri.2; + let vertex1 = last_tri.1; + let vertex2 = last_tri.2; - let free_angle = if vertex1.y > 0.001 && vertex2.y < 0.001 { - PI - (vertex1.y / (vertex2.x - vertex1.x).abs()).atan() - } else if vertex2.y > 0.001 && vertex1.y < 0.001 { - PI - (vertex2.y / (vertex2.x - vertex1.x).abs()).atan() - } else { - let angle1 = 0.5 * PI - vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan(); - let angle2 = 0.5 * PI - vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan(); - min(angle1, angle2) - }; + let free_angle = if vertex1.y > 0.001 && vertex2.y < 0.001 { + PI - (vertex1.y / (vertex2.x - vertex1.x).abs()).atan() + } else if vertex2.y > 0.001 && vertex1.y < 0.001 { + PI - (vertex2.y / (vertex2.x - vertex1.x).abs()).atan() + } else { + let angle1 = + 0.5 * PI - vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan(); + let angle2 = + 0.5 * PI - vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan(); + min(angle1, angle2) + }; - let vertex1 = next_tri.1; - let vertex2 = next_tri.2; + let vertex1 = next_tri.1; + let vertex2 = next_tri.2; - let next_angle = if vertex1.y > 0.001 && vertex2.y > 0.001 { - let angle1 = 0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan(); - let angle2 = 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan(); - min(angle1, angle2) - } else if vertex1.y < 0.001 { - 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan() - } else { - 0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan() - }; - //println!("{:?} -> {:?}: {:?} {:?}", last_idx, next_idx, free_angle.to_degrees(), next_angle.to_degrees()); - let target = (next_angle - PI + free_angle).to_degrees(); - let step = 40.0; - let as_f32 = |x| x as f32 * step; - let range = if target >= 0.0 { - (0..=((target - 0.0001) / step) as usize) - .map(as_f32) - .chain(Some(target)) - } else { - (0..=((next_angle - 0.0001) / step) as usize) - .map(as_f32) - .chain(None) - }; + let next_angle = if vertex1.y > 0.001 && vertex2.y > 0.001 { + let angle1 = + 0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan(); + let angle2 = + 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan(); + min(angle1, angle2) + } else if vertex1.y < 0.001 { + 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan() + } else { + 0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan() + }; + //println!("{:?} -> {:?}: {:?} {:?}", last_idx, next_idx, free_angle.to_degrees(), next_angle.to_degrees()); + let target = (next_angle - PI + free_angle).to_degrees(); + let step = 40.0; + let as_f32 = |x| x as f32 * step; + let range = if target >= 0.0 { + (0..=((target - 0.0001) / step) as usize) + .map(as_f32) + .chain(Some(target)) + } else { + (0..=((next_angle - 0.0001) / step) as usize) + .map(as_f32) + .chain(None) + }; - for angle in range { - let radians = angle.to_radians(); - let next_angle = next_angle - radians; - let mut tri = rotate(*next_tri, radians); + for angle in range { + //println!("angle {:?}", angle); + let radians = angle.to_radians(); + let next_angle = next_angle - radians; + let mut tri = rotate(*next_tri, radians); - // "binary search"-like optimization here - for &delta in &[ - 80.0, 30.0, 10.0, 5.0, 1.0, 0.6, 0.32, 0.18, 0.1, 0.06, 0.03, 0.01, 0.003, - ] { - let initial_state = last_tri.intersects(&tri); - let dx = if initial_state { delta } else { -delta }; - while last_tri.intersects(&tri) == initial_state { - tri.0.x += dx; - tri.1.x += dx; - tri.2.x += dx; + // "binary search"-like optimization here + for &delta in &[ + /*80.0, 30.0, 10.0, 5.0,*/ 1.0, 0.6, 0.32, 0.18, 0.1, 0.06, 0.03, + 0.01, 0.003, + ] { + let initial_state = last_tri.intersects(&tri); + let dx = if initial_state { delta } else { -delta }; + while last_tri.intersects(&tri) == initial_state { + tri.0.x += dx; + tri.1.x += dx; + tri.2.x += dx; + } } - } - let mut w = w.clone(); - w.tris.push((*next_idx, tri)); - w.normalize(); - w.calc_width(); - if save_iterations { - display::save_world(&format!("{}b_{}.svg", save_prefix, save_counter), &w); - } - if w.tris.len() == count_tris { - if w.width < best.width { - println!("[{}] new best: {}", save_counter, w.width); - //println!("{:?}", w.tris); - display::save_world( - &format!("{}best_{}.svg", save_prefix, save_counter), - &w, - ); - best = w; + let mut w = w.clone(); + w.tris.push((*next_idx, tri)); + w.normalize(); + w.calc_width(); + if save_iterations { + display::save_world(&format!("{}b_{}.svg", save_prefix, save_counter), &w); } - } else if w.width < best.width { - w.width -= (2.0 * PI - free_angle - next_angle) * 0.01; - //if (angle > 50 && angle < 55) || (angle > 88 && angle < 92) { - //println!("{:?} -> {:?}", angle, w.width); - //} - new.push(w); + if w.tris.len() == count_tris { + if w.width < best.width { + println!("[{}] new best: {}", save_counter, w.width); + //println!("{:?}", w.tris); + display::save_world( + &format!("{}best_{}.svg", save_prefix, save_counter), + &w, + ); + best = w; + } + } else if w.width < best.width { + w.width -= (2.0 * PI - free_angle - next_angle) * 0.01; + //if (angle > 50 && angle < 55) || (angle > 88 && angle < 92) { + //println!("{:?} -> {:?}", angle, w.width); + //} + new.push(w); + } + save_counter += 1; } - save_counter += 1; + } + progress = true; + if bin_idx + 1 == bins.len() { + let mut new_bin = BinaryHeap::new(); + new_bin.extend(new); + bins.push(new_bin); + } else { + bins[bin_idx + 1].extend(new); } } - worlds.extend(new); } println!("best width = {:?}", best.width); display::save_world("world_best.svg", &best);