Remove unused code, add comments and misc. changes

This commit is contained in:
arnekeller 2019-04-08 11:57:28 +02:00
parent 5240901326
commit b5f7e52fbe
3 changed files with 27 additions and 37 deletions

View File

@ -221,7 +221,7 @@ Außerdem wird Lisa auf einer optimalen Route vor dem letzten Abschnitt immer vo
\end{figure}
\section{Bedienung des Programms}
Das Programm liest die Problemstellung von der Standardeingabe ein. Die grafische Ausgabe wird in die Standardausgabe geschrieben. Wird $-t$ übergeben, kann die Ausgabe in einem \LaTeX-Dokument verwendet werden. Standardmäßig wird ein SVG-Dokument erzeugt. Mit $-s$ werden auch Zwischenlösungen im aktuellen Ordner als SVG-Dateien gespeichert. Falls man die Geschwindigkeit von Lisa oder dem Bus verändern will, kann man dies mit $-l$ bzw. $-b$ tun. Für zusätzliche Debug-Ausgaben kann man $-d$ verwenden. Die Standardoptionen $-h$ und $-V$ zeigen die Hilfe und die Version des Programms an.
Das Programm liest die Problemstellung von der Standardeingabe ein. Die grafische Ausgabe wird in die Standardausgabe geschrieben. Wird $-t$ übergeben, kann die Ausgabe in einem \LaTeX-Dokument verwendet werden. Standardmäßig wird ein SVG-Dokument erzeugt. Falls man die Geschwindigkeit von Lisa oder dem Bus verändern will, kann man dies mit $-l$ bzw. $-b$ tun. Für zusätzliche Debug-Ausgaben kann man $-d$ verwenden. Die Standardoptionen $-h$ und $-V$ zeigen die Hilfe und die Version des Programms an.
\lstinputlisting[caption=Hilfetext des Programmes,frame=single,breaklines=true]{help.txt}
Das vorgegebene Eingabeformat ist mühsam zu schreiben. Daher kann das Programm auch SVG-Dateien einlesen. Punkte werden als Startpunkte interpretiert, sonstige Pfade sind Hindernisse.
@ -276,6 +276,7 @@ Alle Beispiele sind im Maßstab 1:70m. Für die folgenden fünf Beispiele benöt
\label{fig:bsp5}
\end{figure}
\subsection{Eigene Beispiele}
Für diese benötigt das Programm höchstens 250 ms Rechenzeit.
\lstinputlisting[caption=Lösung für Abb. \ref{fig:ebsp2},frame=single,breaklines=true]{runwelt3.txt}
\begin{figure}[H]
\centering

View File

@ -4,8 +4,6 @@ use svg::node::element::{AnimateMotion, Circle, MotionPath};
use svg::Document;
use svg::Node;
use std::fs;
use super::*;
pub(crate) fn dump_latex_code(route: &[RunState], polys: &[Polygon]) {
@ -90,21 +88,6 @@ pub(crate) fn dump_route(opt: Opt, house: Point, polys: &[Polygon], route: &[Run
);
}
pub(crate) fn save_svg(
opt: Opt,
filename: &str,
house: Point,
polys: &[Polygon],
route: &[RunState],
) {
let (points, lines, route1, route2_start) = gen_params(opt, house, route);
fs::write(
filename,
generate_svg(&points, &lines, polys, &route1, route2_start),
)
.unwrap();
}
#[allow(clippy::type_complexity)]
fn gen_params(
opt: Opt,

View File

@ -1,10 +1,18 @@
// Zeitrechnung
use chrono::{Duration, NaiveTime};
// Geometrie-Datenstrukturen und -Algorithmen
use geo::prelude::*;
// schnellere Hash-Tabelle
use hashbrown::HashMap;
// globale Variablen
use lazy_static::lazy_static;
// effizienteres Readers-Writer-Lock
use parking_lot::RwLock;
// Implementierung des Dijkstra-Algorithmus
use pathfinding::directed::dijkstra::dijkstra;
// R*-Baum-Implementierung
use rstar::{RTree, RTreeObject};
// Kommandozeilen-Argumente einfach einlesen
use structopt::StructOpt;
use std::cmp;
@ -28,9 +36,6 @@ struct Opt {
/// Debug-Modus aktivieren
#[structopt(short = "d", long = "debug")]
debug: bool,
/// Zwischenlösungen speichern
#[structopt(short = "s", long = "save")]
_save_intermediates: bool,
/// Beste Lösung als tkz-Code ausgeben
#[structopt(short = "t", long = "tkz")]
tkz: bool,
@ -52,9 +57,10 @@ struct RunState {
// Bisher zurückgelegte Strecke
total_distance: f32,
}
/// Trait-Implementierung, damit die Struktur in BinaryHeaps passt
/// Trait-Implementierung, damit die Struktur im Dijkstra-Algorithmus verwendet werden kann
impl PartialEq for RunState {
fn eq(&self, other: &Self) -> bool {
// nur die Position ist für die Wegfindung relevant
self.pos.x() == other.pos.x() && self.pos.y() == other.pos.y()
}
}
@ -89,7 +95,7 @@ fn main() {
// Geschwindigkeiten in m/s umrechnen
let bus_speed = opt.bus / 3.6;
let lisa_speed = opt.lisa / 3.6;
// Startzeitpunkt berechnen
// Startzeitpunkt berechnen (für eine gegebene Position und Laufstrecke)
let calc_time = |total_distance, y| {
NaiveTime::from_hms(7, 30, 0)
- Duration::seconds(((total_distance * (opt.bus / opt.lisa) - y) / bus_speed) as i64)
@ -103,9 +109,10 @@ fn main() {
let data = input::read_input();
let house = data.start;
let polys = data.polys;
// Polygone in RTree speichern
// Polygone in R*-Baum speichern
let mut rtree = RTREE.write();
*rtree = RTree::bulk_load(polys.clone());
// Write-Lock aufheben
drop(rtree);
// alle Ecken der Hindernisse bestimmen
let points = polys
@ -136,9 +143,11 @@ fn main() {
let mut iterations = 0;
let mut time = time::Duration::from_secs(0);
let best = dijkstra(
// Dijkstra-Algorithmus anwenden
let route = dijkstra(
&start,
|last| {
// ausgehend von einem Zustand die nächsten Zustände/Positionen bestimmen
let start = Instant::now();
// neue Zustände
let mut all = vec![];
@ -146,8 +155,6 @@ fn main() {
// versuche, zu jeder anderen Ecke zu gehen
for &next in points
.iter()
// Ecke sollte nicht schon in Route sein
//.filter(|&&next| !state.iter().any(|p| p.pos == next))
// Weg zu dieser Ecke sollte kein Polygon schneiden
.filter(|&&next| none_intersect(Line::new(last.pos, next)))
{
@ -159,7 +166,7 @@ fn main() {
bus,
total_distance,
};
//eprintln!("{:?} -> {:?} {:?} {:?}", last.pos, new.pos, last.bus, bus);
// Weg kann nicht besser sein als direkter Weg
debug_assert!((last.bus - bus) > -0.01);
all.push((new, ((last.bus - bus) * 1000.0) as u32));
}
@ -190,15 +197,14 @@ fn main() {
|node| node.pos.x() == 0.0,
)
.unwrap().0;
//best.reverse();
// Performanz-Einschätzung ausgeben
if opt.debug {
eprintln!("{}us/iteration ({} iterations)", time.as_micros() / iterations, iterations)
}
// beste Lösung ausgeben
eprintln!("Finale Lösung:");
let route = best;
let last = route.last().unwrap();
eprintln!(
"Startzeit: {:?}",
@ -238,7 +244,7 @@ fn main() {
display::dump_route(opt, house, &polys, &route);
}
// Prozess direkt beenden, ohne Variablen zu löschen
// (ca. 20% der Laufzeit..)
// (spart ca. 20% der Laufzeit..)
std::process::exit(0);
}
@ -247,11 +253,11 @@ 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());
static ref COLLISIONS: RwLock<HashMap<[i32; 4], bool>> = RwLock::new(HashMap::new());
}
/// Schneidet die Linie keines der Polygone?
/// (Berührungen erlaubt)
/// (Berührungen sind 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) {
@ -261,10 +267,10 @@ fn none_intersect(mut line: Line) -> bool {
let mut collisions = COLLISIONS.write();
// 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,
line.start.x as i32,
line.start.y as i32,
line.end.x as i32,
line.end.y as i32,
];
// evtl. gefundenes Ergebnis sofort zurückgeben
if let Some(&r) = collisions.get(&id) {