Comments, bug fixes and optimizations
This commit is contained in:
parent
5e7ba7e7eb
commit
22b262c292
41
src/main.rs
41
src/main.rs
@ -202,7 +202,7 @@ fn main() {
|
|||||||
total_distance,
|
total_distance,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Verbesserung anzeigen und evtl. speichern
|
// Verbesserung anzeigen
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Verbesserung: {:?} ({:?}+ Möglichkeiten verbleiben)",
|
"Verbesserung: {:?} ({:?}+ Möglichkeiten verbleiben)",
|
||||||
calc_time(total_distance, line.end.y),
|
calc_time(total_distance, line.end.y),
|
||||||
@ -212,6 +212,7 @@ fn main() {
|
|||||||
best.reverse();
|
best.reverse();
|
||||||
best_bus = bus;
|
best_bus = bus;
|
||||||
if opt.save_intermediates {
|
if opt.save_intermediates {
|
||||||
|
// Zwischenlösung als SVG speichern
|
||||||
display::save_svg(
|
display::save_svg(
|
||||||
opt,
|
opt,
|
||||||
&format!("{}{}.svg", save_prefix, save_counter),
|
&format!("{}{}.svg", save_prefix, save_counter),
|
||||||
@ -219,18 +220,24 @@ fn main() {
|
|||||||
&polys,
|
&polys,
|
||||||
&best,
|
&best,
|
||||||
);
|
);
|
||||||
|
save_counter += 1;
|
||||||
}
|
}
|
||||||
save_counter += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// neu gefundene Routen speichern
|
// neu gefundene Routen speichern
|
||||||
|
// -> automatisch im BinaryHeap einsortiert
|
||||||
states.extend(all);
|
states.extend(all);
|
||||||
let end = Instant::now();
|
let end = Instant::now();
|
||||||
total_time += end - start;
|
total_time += end - start;
|
||||||
iterations += 1;
|
iterations += 1;
|
||||||
}
|
}
|
||||||
if opt.debug {
|
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
|
// beste Lösung ausgeben
|
||||||
eprintln!("Finale Lösung:");
|
eprintln!("Finale Lösung:");
|
||||||
@ -263,36 +270,56 @@ fn main() {
|
|||||||
eprintln!("x={:.02} y={:.02}", s.pos.x(), s.pos.y());
|
eprintln!("x={:.02} y={:.02}", s.pos.x(), s.pos.y());
|
||||||
}
|
}
|
||||||
eprintln!("Länge: {:.0}m", last.total_distance);
|
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);
|
eprintln!("Dauer: {:02.0}:{:02.0}", seconds / 60.0, seconds % 60.0);
|
||||||
// beste Route grafisch ausgeben
|
// beste Route grafisch ausgeben
|
||||||
if opt.tkz {
|
if opt.tkz {
|
||||||
|
// als LaTeX-kompatibler Code
|
||||||
display::dump_latex_code(&route, &polys);
|
display::dump_latex_code(&route, &polys);
|
||||||
} else {
|
} else {
|
||||||
|
// oder als animiertes SVG
|
||||||
display::dump_route(opt, house, &polys, &route);
|
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! {
|
lazy_static! {
|
||||||
|
// R*-Baum zur Beschleunigung der Routenabschnitt-Hindernis-Überprüfungen
|
||||||
static ref RTREE: RwLock<RTree<Polygon>> = RwLock::new(RTree::new());
|
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());
|
static ref COLLISIONS: RwLock<HashMap<[i16; 4], bool>> = RwLock::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schneidet die Linie keines der Polygone?
|
/// Schneidet die Linie keines der Polygone?
|
||||||
/// (Berührungen erlaubt)
|
/// (Berührungen erlaubt)
|
||||||
fn none_intersect(mut line: Line) -> bool {
|
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) {
|
if line.start.y > line.end.y || (line.start.y == line.end.y && line.start.x > line.end.x) {
|
||||||
let end = line.start;
|
let end = line.start;
|
||||||
line.start = line.end;
|
line.start = line.end;
|
||||||
line.end = end;
|
line.end = end;
|
||||||
}
|
}
|
||||||
|
// Cache laden
|
||||||
let mut collisions = COLLISIONS.write().unwrap();
|
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) {
|
if let Some(&r) = collisions.get(&id) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
// ansonsten:
|
||||||
|
// Polygone finden, die die AABB der Linie schneiden
|
||||||
let rtree = RTREE.read().unwrap();
|
let rtree = RTREE.read().unwrap();
|
||||||
let polys = rtree.locate_in_envelope_intersecting(&line.envelope());
|
let polys = rtree.locate_in_envelope_intersecting(&line.envelope());
|
||||||
|
// Mittelpunkt der Linie bestimmen
|
||||||
let mut middle = line.start;
|
let mut middle = line.start;
|
||||||
middle.x += line.dx() / 2.0;
|
middle.x += line.dx() / 2.0;
|
||||||
middle.y += line.dy() / 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
|
continue; // Linie schneidet sich immer selbst
|
||||||
}
|
}
|
||||||
if l.intersects(&line) {
|
if l.intersects(&line) {
|
||||||
|
// Ergebnis im Cache speichern
|
||||||
collisions.insert(id, false);
|
collisions.insert(id, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// falls Mittelpunkt in Polygon:
|
// falls Mittelpunkt in Polygon:
|
||||||
if p.euclidean_distance(&middle) == 0.0 {
|
if p.euclidean_distance(&middle) == 0.0 {
|
||||||
// schneidet Polygon
|
// schneidet Polygon, Ergebnis im Cache speichern
|
||||||
collisions.insert(id, false);
|
collisions.insert(id, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// (dieser Fall tritt auf, wenn die Linie von einer Polygon-Ecke zu einer anderen Ecke verläuft)
|
// (dieser Fall tritt auf, wenn die Linie von einer Polygon-Ecke zu einer anderen Ecke verläuft)
|
||||||
}
|
}
|
||||||
// keine Überschneidung gefunden: der Weg ist frei!
|
// keine Überschneidung gefunden: der Weg ist frei!
|
||||||
|
// (natürlich auch im Cache speichern)
|
||||||
collisions.insert(id, true);
|
collisions.insert(id, true);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user