Comments, bug fixes and optimizations

This commit is contained in:
arnekeller 2019-04-02 19:18:06 +02:00
parent 5e7ba7e7eb
commit 22b262c292

View File

@ -202,7 +202,7 @@ fn main() {
total_distance,
},
);
// Verbesserung anzeigen und evtl. speichern
// Verbesserung anzeigen
eprintln!(
"Verbesserung: {:?} ({:?}+ Möglichkeiten verbleiben)",
calc_time(total_distance, line.end.y),
@ -212,6 +212,7 @@ fn main() {
best.reverse();
best_bus = bus;
if opt.save_intermediates {
// Zwischenlösung als SVG speichern
display::save_svg(
opt,
&format!("{}{}.svg", save_prefix, save_counter),
@ -219,18 +220,24 @@ fn main() {
&polys,
&best,
);
save_counter += 1;
}
save_counter += 1;
}
}
// neu gefundene Routen speichern
// -> automatisch im BinaryHeap einsortiert
states.extend(all);
let end = Instant::now();
total_time += end - start;
iterations += 1;
}
if opt.debug {
eprintln!("DEBUG: {}us/iteration", total_time.as_micros() / iterations);
// Performanz-Schätzung anzeigen
eprintln!(
"DEBUG: {}μs/Iteration mit {} Iterationen",
total_time.as_micros() / iterations,
iterations
);
}
// beste Lösung ausgeben
eprintln!("Finale Lösung:");
@ -263,36 +270,56 @@ fn main() {
eprintln!("x={:.02} y={:.02}", s.pos.x(), s.pos.y());
}
eprintln!("Länge: {:.0}m", last.total_distance);
let seconds = last.total_distance / (15.0 / 3.6);
let seconds = last.total_distance / lisa_speed;
eprintln!("Dauer: {:02.0}:{:02.0}", seconds / 60.0, seconds % 60.0);
// beste Route grafisch ausgeben
if opt.tkz {
// als LaTeX-kompatibler Code
display::dump_latex_code(&route, &polys);
} else {
// oder als animiertes SVG
display::dump_route(opt, house, &polys, &route);
}
// Prozess direkt beenden, ohne Variablen zu löschen
// (ca. 20% der Laufzeit..)
std::process::exit(0);
}
// "Globale" und bei Bedarf initialisierte Variablen
lazy_static! {
// R*-Baum zur Beschleunigung der Routenabschnitt-Hindernis-Überprüfungen
static ref RTREE: RwLock<RTree<Polygon>> = RwLock::new(RTree::new());
// Cache für die Funktion none_intersect
static ref COLLISIONS: RwLock<HashMap<[i16; 4], bool>> = RwLock::new(HashMap::new());
}
/// Schneidet die Linie keines der Polygone?
/// (Berührungen erlaubt)
fn none_intersect(mut line: Line) -> bool {
// Linie normalisieren
if line.start.y > line.end.y || (line.start.y == line.end.y && line.start.x > line.end.x) {
let end = line.start;
line.start = line.end;
line.end = end;
}
// Cache laden
let mut collisions = COLLISIONS.write().unwrap();
let id = [line.start.x as i16, line.start.y as i16, line.end.x as i16, line.end.y as i16];
// Liniendaten hashbar machen
let id = [
line.start.x as i16,
line.start.y as i16,
line.end.x as i16,
line.end.y as i16,
];
// evtl. gefundenes Ergebnis sofort zurückgeben
if let Some(&r) = collisions.get(&id) {
return r;
}
// ansonsten:
// Polygone finden, die die AABB der Linie schneiden
let rtree = RTREE.read().unwrap();
let polys = rtree.locate_in_envelope_intersecting(&line.envelope());
// Mittelpunkt der Linie bestimmen
let mut middle = line.start;
middle.x += line.dx() / 2.0;
middle.y += line.dy() / 2.0;
@ -317,19 +344,21 @@ fn none_intersect(mut line: Line) -> bool {
continue; // Linie schneidet sich immer selbst
}
if l.intersects(&line) {
// Ergebnis im Cache speichern
collisions.insert(id, false);
return false;
}
}
// falls Mittelpunkt in Polygon:
if p.euclidean_distance(&middle) == 0.0 {
// schneidet Polygon
// schneidet Polygon, Ergebnis im Cache speichern
collisions.insert(id, false);
return false;
}
// (dieser Fall tritt auf, wenn die Linie von einer Polygon-Ecke zu einer anderen Ecke verläuft)
}
// keine Überschneidung gefunden: der Weg ist frei!
// (natürlich auch im Cache speichern)
collisions.insert(id, true);
true
}