Try to work on all triangle collection lengths at the same time

This commit is contained in:
Arne Keller 2019-03-28 22:17:46 +01:00
parent a63749c28b
commit 14cfe1db97

View File

@ -167,113 +167,139 @@ fn main() {
let save_prefix = "world_"; let save_prefix = "world_";
save_counter = 0; save_counter = 0;
let mut counter = 0; let mut counter = 0;
while worlds.peek().map(|x| x.width <= best.width) == Some(true) { let mut bins = Vec::new();
counter += 1; bins.push(worlds);
if counter % 10000 == 0 { let mut progress = true;
println!("{}/∞", counter); while progress {
} progress = false;
let w = worlds.pop().unwrap(); for bin_idx in 0..bins.len() {
//println!("s: {:?}", w); 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 { if save_counter < 1000000 {
display::save_world(&format!("{}a_{}.svg", save_prefix, save_counter), &w); display::save_world(&format!("{}a_{}.svg", save_prefix, save_counter), &w);
} }
*/ */
let save_iterations = false; let save_iterations = false;
let mut new = vec![]; let mut new = vec![];
for (next_idx, next_tri) in left_tris for (next_idx, next_tri) in left_tris
.iter() .iter()
.filter(|(idx1, _tri)| w.tris.iter().all(|(idx2, _tri)| idx1 != idx2)) .filter(|(idx1, _tri)| w.tris.iter().all(|(idx2, _tri)| idx1 != idx2))
{ {
//println!("trying {:?}", next_idx); //println!("trying {:?}", next_idx);
let (last_idx, last_tri) = *w.tris.last().unwrap(); let (last_idx, last_tri) = *w.tris.last().unwrap();
let vertex1 = last_tri.1; let vertex1 = last_tri.1;
let vertex2 = last_tri.2; let vertex2 = last_tri.2;
let free_angle = if vertex1.y > 0.001 && vertex2.y < 0.001 { let free_angle = if vertex1.y > 0.001 && vertex2.y < 0.001 {
PI - (vertex1.y / (vertex2.x - vertex1.x).abs()).atan() PI - (vertex1.y / (vertex2.x - vertex1.x).abs()).atan()
} else if vertex2.y > 0.001 && vertex1.y < 0.001 { } else if vertex2.y > 0.001 && vertex1.y < 0.001 {
PI - (vertex2.y / (vertex2.x - vertex1.x).abs()).atan() PI - (vertex2.y / (vertex2.x - vertex1.x).abs()).atan()
} else { } else {
let angle1 = 0.5 * PI - vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan(); let angle1 =
let angle2 = 0.5 * PI - vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan(); 0.5 * PI - vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan();
min(angle1, angle2) let angle2 =
}; 0.5 * PI - vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan();
min(angle1, angle2)
};
let vertex1 = next_tri.1; let vertex1 = next_tri.1;
let vertex2 = next_tri.2; let vertex2 = next_tri.2;
let next_angle = if vertex1.y > 0.001 && vertex2.y > 0.001 { 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 angle1 =
let angle2 = 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan(); 0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan();
min(angle1, angle2) let angle2 =
} else if vertex1.y < 0.001 { 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan();
0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan() min(angle1, angle2)
} else { } else if vertex1.y < 0.001 {
0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan() 0.5 * PI + vertex2.x.signum() * (vertex2.x.abs() / vertex2.y).atan()
}; } else {
//println!("{:?} -> {:?}: {:?} {:?}", last_idx, next_idx, free_angle.to_degrees(), next_angle.to_degrees()); 0.5 * PI + vertex1.x.signum() * (vertex1.x.abs() / vertex1.y).atan()
let target = (next_angle - PI + free_angle).to_degrees(); };
let step = 40.0; //println!("{:?} -> {:?}: {:?} {:?}", last_idx, next_idx, free_angle.to_degrees(), next_angle.to_degrees());
let as_f32 = |x| x as f32 * step; let target = (next_angle - PI + free_angle).to_degrees();
let range = if target >= 0.0 { let step = 40.0;
(0..=((target - 0.0001) / step) as usize) let as_f32 = |x| x as f32 * step;
.map(as_f32) let range = if target >= 0.0 {
.chain(Some(target)) (0..=((target - 0.0001) / step) as usize)
} else { .map(as_f32)
(0..=((next_angle - 0.0001) / step) as usize) .chain(Some(target))
.map(as_f32) } else {
.chain(None) (0..=((next_angle - 0.0001) / step) as usize)
}; .map(as_f32)
.chain(None)
};
for angle in range { for angle in range {
let radians = angle.to_radians(); //println!("angle {:?}", angle);
let next_angle = next_angle - radians; let radians = angle.to_radians();
let mut tri = rotate(*next_tri, radians); let next_angle = next_angle - radians;
let mut tri = rotate(*next_tri, radians);
// "binary search"-like optimization here // "binary search"-like optimization here
for &delta in &[ 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, /*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 }; let initial_state = last_tri.intersects(&tri);
while last_tri.intersects(&tri) == initial_state { let dx = if initial_state { delta } else { -delta };
tri.0.x += dx; while last_tri.intersects(&tri) == initial_state {
tri.1.x += dx; tri.0.x += dx;
tri.2.x += dx; tri.1.x += dx;
tri.2.x += dx;
}
} }
} let mut w = w.clone();
let mut w = w.clone(); w.tris.push((*next_idx, tri));
w.tris.push((*next_idx, tri)); w.normalize();
w.normalize(); w.calc_width();
w.calc_width(); if save_iterations {
if save_iterations { display::save_world(&format!("{}b_{}.svg", save_prefix, save_counter), &w);
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;
} }
} else if w.width < best.width { if w.tris.len() == count_tris {
w.width -= (2.0 * PI - free_angle - next_angle) * 0.01; if w.width < best.width {
//if (angle > 50 && angle < 55) || (angle > 88 && angle < 92) { println!("[{}] new best: {}", save_counter, w.width);
//println!("{:?} -> {:?}", angle, w.width); //println!("{:?}", w.tris);
//} display::save_world(
new.push(w); &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); println!("best width = {:?}", best.width);
display::save_world("world_best.svg", &best); display::save_world("world_best.svg", &best);