Remove unused code, add comments and misc. changes
This commit is contained in:
parent
5240901326
commit
b5f7e52fbe
@ -221,7 +221,7 @@ Außerdem wird Lisa auf einer optimalen Route vor dem letzten Abschnitt immer vo
|
|||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\section{Bedienung des Programms}
|
\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}
|
\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.
|
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}
|
\label{fig:bsp5}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\subsection{Eigene Beispiele}
|
\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}
|
\lstinputlisting[caption=Lösung für Abb. \ref{fig:ebsp2},frame=single,breaklines=true]{runwelt3.txt}
|
||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
|
@ -4,8 +4,6 @@ use svg::node::element::{AnimateMotion, Circle, MotionPath};
|
|||||||
use svg::Document;
|
use svg::Document;
|
||||||
use svg::Node;
|
use svg::Node;
|
||||||
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub(crate) fn dump_latex_code(route: &[RunState], polys: &[Polygon]) {
|
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)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn gen_params(
|
fn gen_params(
|
||||||
opt: Opt,
|
opt: Opt,
|
||||||
|
44
src/main.rs
44
src/main.rs
@ -1,10 +1,18 @@
|
|||||||
|
// Zeitrechnung
|
||||||
use chrono::{Duration, NaiveTime};
|
use chrono::{Duration, NaiveTime};
|
||||||
|
// Geometrie-Datenstrukturen und -Algorithmen
|
||||||
use geo::prelude::*;
|
use geo::prelude::*;
|
||||||
|
// schnellere Hash-Tabelle
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
// globale Variablen
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
// effizienteres Readers-Writer-Lock
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
// Implementierung des Dijkstra-Algorithmus
|
||||||
use pathfinding::directed::dijkstra::dijkstra;
|
use pathfinding::directed::dijkstra::dijkstra;
|
||||||
|
// R*-Baum-Implementierung
|
||||||
use rstar::{RTree, RTreeObject};
|
use rstar::{RTree, RTreeObject};
|
||||||
|
// Kommandozeilen-Argumente einfach einlesen
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@ -28,9 +36,6 @@ struct Opt {
|
|||||||
/// Debug-Modus aktivieren
|
/// Debug-Modus aktivieren
|
||||||
#[structopt(short = "d", long = "debug")]
|
#[structopt(short = "d", long = "debug")]
|
||||||
debug: bool,
|
debug: bool,
|
||||||
/// Zwischenlösungen speichern
|
|
||||||
#[structopt(short = "s", long = "save")]
|
|
||||||
_save_intermediates: bool,
|
|
||||||
/// Beste Lösung als tkz-Code ausgeben
|
/// Beste Lösung als tkz-Code ausgeben
|
||||||
#[structopt(short = "t", long = "tkz")]
|
#[structopt(short = "t", long = "tkz")]
|
||||||
tkz: bool,
|
tkz: bool,
|
||||||
@ -52,9 +57,10 @@ struct RunState {
|
|||||||
// Bisher zurückgelegte Strecke
|
// Bisher zurückgelegte Strecke
|
||||||
total_distance: f32,
|
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 {
|
impl PartialEq for RunState {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
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()
|
self.pos.x() == other.pos.x() && self.pos.y() == other.pos.y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +95,7 @@ fn main() {
|
|||||||
// Geschwindigkeiten in m/s umrechnen
|
// Geschwindigkeiten in m/s umrechnen
|
||||||
let bus_speed = opt.bus / 3.6;
|
let bus_speed = opt.bus / 3.6;
|
||||||
let lisa_speed = opt.lisa / 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| {
|
let calc_time = |total_distance, y| {
|
||||||
NaiveTime::from_hms(7, 30, 0)
|
NaiveTime::from_hms(7, 30, 0)
|
||||||
- Duration::seconds(((total_distance * (opt.bus / opt.lisa) - y) / bus_speed) as i64)
|
- 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 data = input::read_input();
|
||||||
let house = data.start;
|
let house = data.start;
|
||||||
let polys = data.polys;
|
let polys = data.polys;
|
||||||
// Polygone in RTree speichern
|
// Polygone in R*-Baum speichern
|
||||||
let mut rtree = RTREE.write();
|
let mut rtree = RTREE.write();
|
||||||
*rtree = RTree::bulk_load(polys.clone());
|
*rtree = RTree::bulk_load(polys.clone());
|
||||||
|
// Write-Lock aufheben
|
||||||
drop(rtree);
|
drop(rtree);
|
||||||
// alle Ecken der Hindernisse bestimmen
|
// alle Ecken der Hindernisse bestimmen
|
||||||
let points = polys
|
let points = polys
|
||||||
@ -136,9 +143,11 @@ fn main() {
|
|||||||
let mut iterations = 0;
|
let mut iterations = 0;
|
||||||
let mut time = time::Duration::from_secs(0);
|
let mut time = time::Duration::from_secs(0);
|
||||||
|
|
||||||
let best = dijkstra(
|
// Dijkstra-Algorithmus anwenden
|
||||||
|
let route = dijkstra(
|
||||||
&start,
|
&start,
|
||||||
|last| {
|
|last| {
|
||||||
|
// ausgehend von einem Zustand die nächsten Zustände/Positionen bestimmen
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
// neue Zustände
|
// neue Zustände
|
||||||
let mut all = vec![];
|
let mut all = vec![];
|
||||||
@ -146,8 +155,6 @@ fn main() {
|
|||||||
// versuche, zu jeder anderen Ecke zu gehen
|
// versuche, zu jeder anderen Ecke zu gehen
|
||||||
for &next in points
|
for &next in points
|
||||||
.iter()
|
.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
|
// Weg zu dieser Ecke sollte kein Polygon schneiden
|
||||||
.filter(|&&next| none_intersect(Line::new(last.pos, next)))
|
.filter(|&&next| none_intersect(Line::new(last.pos, next)))
|
||||||
{
|
{
|
||||||
@ -159,7 +166,7 @@ fn main() {
|
|||||||
bus,
|
bus,
|
||||||
total_distance,
|
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);
|
debug_assert!((last.bus - bus) > -0.01);
|
||||||
all.push((new, ((last.bus - bus) * 1000.0) as u32));
|
all.push((new, ((last.bus - bus) * 1000.0) as u32));
|
||||||
}
|
}
|
||||||
@ -190,15 +197,14 @@ fn main() {
|
|||||||
|node| node.pos.x() == 0.0,
|
|node| node.pos.x() == 0.0,
|
||||||
)
|
)
|
||||||
.unwrap().0;
|
.unwrap().0;
|
||||||
//best.reverse();
|
|
||||||
|
|
||||||
|
// Performanz-Einschätzung ausgeben
|
||||||
if opt.debug {
|
if opt.debug {
|
||||||
eprintln!("{}us/iteration ({} iterations)", time.as_micros() / iterations, iterations)
|
eprintln!("{}us/iteration ({} iterations)", time.as_micros() / iterations, iterations)
|
||||||
}
|
}
|
||||||
|
|
||||||
// beste Lösung ausgeben
|
// beste Lösung ausgeben
|
||||||
eprintln!("Finale Lösung:");
|
eprintln!("Finale Lösung:");
|
||||||
let route = best;
|
|
||||||
let last = route.last().unwrap();
|
let last = route.last().unwrap();
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Startzeit: {:?}",
|
"Startzeit: {:?}",
|
||||||
@ -238,7 +244,7 @@ fn main() {
|
|||||||
display::dump_route(opt, house, &polys, &route);
|
display::dump_route(opt, house, &polys, &route);
|
||||||
}
|
}
|
||||||
// Prozess direkt beenden, ohne Variablen zu löschen
|
// Prozess direkt beenden, ohne Variablen zu löschen
|
||||||
// (ca. 20% der Laufzeit..)
|
// (spart ca. 20% der Laufzeit..)
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,11 +253,11 @@ lazy_static! {
|
|||||||
// R*-Baum zur Beschleunigung der Routenabschnitt-Hindernis-Überprüfungen
|
// 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
|
// 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?
|
/// Schneidet die Linie keines der Polygone?
|
||||||
/// (Berührungen erlaubt)
|
/// (Berührungen sind erlaubt)
|
||||||
fn none_intersect(mut line: Line) -> bool {
|
fn none_intersect(mut line: Line) -> bool {
|
||||||
// Linie normalisieren
|
// 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) {
|
||||||
@ -261,10 +267,10 @@ fn none_intersect(mut line: Line) -> bool {
|
|||||||
let mut collisions = COLLISIONS.write();
|
let mut collisions = COLLISIONS.write();
|
||||||
// Liniendaten hashbar machen
|
// Liniendaten hashbar machen
|
||||||
let id = [
|
let id = [
|
||||||
line.start.x as i16,
|
line.start.x as i32,
|
||||||
line.start.y as i16,
|
line.start.y as i32,
|
||||||
line.end.x as i16,
|
line.end.x as i32,
|
||||||
line.end.y as i16,
|
line.end.y as i32,
|
||||||
];
|
];
|
||||||
// evtl. gefundenes Ergebnis sofort zurückgeben
|
// evtl. gefundenes Ergebnis sofort zurückgeben
|
||||||
if let Some(&r) = collisions.get(&id) {
|
if let Some(&r) = collisions.get(&id) {
|
||||||
|
Loading…
Reference in New Issue
Block a user