Fancy output; initial documentation
This commit is contained in:
parent
460e0749ad
commit
d97e51c3bc
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
tmp*.svg
|
||||
tmp*.svg
|
||||
*.pdf
|
||||
|
38
Cargo.lock
generated
38
Cargo.lock
generated
@ -2,6 +2,7 @@
|
||||
name = "Aufgabe1"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"decorum 0.1.2",
|
||||
"geo 0.11.0",
|
||||
"svg 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -44,6 +45,16 @@ name = "cfg-if"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "decorum"
|
||||
version = "0.1.2"
|
||||
@ -96,6 +107,14 @@ name = "libc"
|
||||
version = "0.2.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.6"
|
||||
@ -122,6 +141,11 @@ dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rstar"
|
||||
version = "0.1.1"
|
||||
@ -177,6 +201,16 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
@ -207,13 +241,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
||||
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476"
|
||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27"
|
||||
"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
|
||||
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
||||
"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
|
||||
"checksum rstar 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64ffe043929ee67d46694af1a4851f6bbe571b52a55677ba1686222dc35fd449"
|
||||
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
|
||||
"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7"
|
||||
@ -221,6 +258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum svg 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a863ec1f8e7cfd4ea449f77445cca06aac240b9a677ccf12b0f65ef020db52c7"
|
||||
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
@ -4,7 +4,11 @@ version = "0.1.0"
|
||||
authors = ["arne"]
|
||||
edition = "2018"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
[dependencies]
|
||||
geo = { path = "/home/arne/Documents/Code/Github/geo/geo" }
|
||||
svg = "0.5.11"
|
||||
decorum = { path = "/home/arne/Documents/Code/Github/decorum" }
|
||||
chrono = "0.4.6"
|
||||
|
157
DokumentationAufgabe1.tex
Normal file
157
DokumentationAufgabe1.tex
Normal file
@ -0,0 +1,157 @@
|
||||
\documentclass[a4paper,10pt,ngerman]{scrartcl}
|
||||
\usepackage{babel}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[a4paper,margin=2.5cm]{geometry}
|
||||
|
||||
% automatische Quotes
|
||||
\usepackage{csquotes}
|
||||
\MakeOuterQuote{"}
|
||||
|
||||
% Die nächsten drei Felder bitte anpassen:
|
||||
\newcommand{\Name}{Arne Keller} % Teamname oder eigenen Namen angeben
|
||||
\newcommand{\TeilnahmeId}{50966}
|
||||
\newcommand{\Aufgabe}{Aufgabe 1: Lisa rennt}
|
||||
|
||||
% Kopf- und Fußzeilen
|
||||
\usepackage{scrlayer-scrpage, lastpage}
|
||||
\setkomafont{pageheadfoot}{\textrm}
|
||||
\lohead{\Aufgabe}
|
||||
\chead{\thepage{}/\pageref{LastPage}}
|
||||
\rohead{\Name/Teilnahme-Id: \TeilnahmeId}
|
||||
\cfoot{}
|
||||
|
||||
% Für mathematische Befehle und Symbole
|
||||
\usepackage{amsmath,amsthm,amssymb}
|
||||
|
||||
% Für Bilder
|
||||
\usepackage{graphicx,subcaption,float}
|
||||
\usepackage{tkz-euclide}
|
||||
\usetkzobj{all}
|
||||
|
||||
% Für Algorithmen
|
||||
%\usepackage{algpseudocode}
|
||||
|
||||
% Für Quelltext
|
||||
\usepackage{listings}
|
||||
\usepackage{color}
|
||||
\definecolor{mygreen}{rgb}{0,0.6,0}
|
||||
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
|
||||
\definecolor{mymauve}{rgb}{0.58,0,0.82}
|
||||
\lstset{
|
||||
keywordstyle=\color{blue},commentstyle=\color{mygreen},
|
||||
stringstyle=\color{mymauve},rulecolor=\color{black},
|
||||
basicstyle=\footnotesize\ttfamily,numberstyle=\tiny\color{mygray},
|
||||
captionpos=b, % sets the caption-position to bottom
|
||||
keepspaces=true, % keeps spaces in text
|
||||
numbers=left, numbersep=5pt, showspaces=false,showstringspaces=false,
|
||||
showtabs=false, stepnumber=2, tabsize=2, title=\lstname
|
||||
}
|
||||
\lstdefinelanguage{Rust}{
|
||||
keywords={break, match, continue, else, for, fn, if, return, self, let, mut, loop, while, extern, crate, use, static, enum, struct, impl, as, type, derive, mod},
|
||||
morecomment=[l]{//},
|
||||
morecomment=[s]{/*}{*/},
|
||||
morestring=[b]",
|
||||
sensitive=true
|
||||
}
|
||||
|
||||
% Diese beiden Pakete müssen als letztes geladen werden
|
||||
%\usepackage{hyperref} % Anklickbare Links im Dokument
|
||||
%\usepackage{cleveref}
|
||||
|
||||
% Daten für die Titelseite
|
||||
\title{\Aufgabe}
|
||||
\author{\Name\\Teilnahme-ID: \TeilnahmeId}
|
||||
\date{29. April 2019}
|
||||
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
|
||||
\section{Lösungsidee}
|
||||
Zunächst kann man feststellen, dass der letzte Abschnitt jeder Route zum Bus immer exakt gerade ist. In einer Kurve würde Lisa weiter laufen, ohne am Ende auf der y-Achse weiter zu sein. Es gibt keinen, einen oder zwei Treffpunkte, bei denen Lisa (ohne zu warten) den Bus erwischt:
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}{.33\textwidth}
|
||||
\centering
|
||||
\begin{tikzpicture}
|
||||
\tkzInit[xmax=3.5,ymax=7.5]
|
||||
\tkzAxeXY
|
||||
\tkzGrid
|
||||
\tkzDefPoint(0,0){B}
|
||||
\tkzDefPoint(1.25,3.5){L}
|
||||
\tkzDefPoint(0,2.83333){M1}
|
||||
\tkzDefPoint(0,6.5){M2}
|
||||
|
||||
\tkzDrawSegment(L,M1)
|
||||
\tkzDrawSegment(L,M2)
|
||||
\tkzDrawPoints(B,L,M1,M2)
|
||||
|
||||
\tkzLabelPoints(B,L,M1,M2)
|
||||
\end{tikzpicture}
|
||||
\caption{Zwei Treffpunkte}
|
||||
\label{abb:fall1}
|
||||
\end{subfigure}%
|
||||
\begin{subfigure}{.33\textwidth}
|
||||
\centering
|
||||
\begin{tikzpicture}
|
||||
\tkzInit[xmax=3.5,ymax=7.5]
|
||||
\tkzAxeXY
|
||||
\tkzGrid
|
||||
\tkzDefPoint(0,0){B}
|
||||
\tkzDefPoint(2.020725942,3.5){L}
|
||||
\tkzDefPoint(0,4.614){M}
|
||||
|
||||
\tkzDrawSegment(L,M)
|
||||
\tkzDrawPoints(B,L,M)
|
||||
|
||||
\tkzLabelPoints[yshift=14pt](M)
|
||||
\tkzLabelPoints(B,L)
|
||||
\end{tikzpicture}
|
||||
\caption{Ein Treffpunkt}
|
||||
\label{abb:fall1}
|
||||
\end{subfigure}%
|
||||
\begin{subfigure}{.33\textwidth}
|
||||
\centering
|
||||
\begin{tikzpicture}
|
||||
\tkzInit[xmax=3.5,ymax=7.5]
|
||||
\tkzAxeXY
|
||||
\tkzGrid
|
||||
\tkzDefPoint(0,0){B}
|
||||
\tkzDefPoint(3,3.5){L}
|
||||
|
||||
\tkzDrawPoints(B,L)
|
||||
|
||||
\tkzLabelPoints(B,L)
|
||||
\end{tikzpicture}
|
||||
\caption{Kein Treffpunkt}
|
||||
\label{abb:fall1}
|
||||
\end{subfigure}
|
||||
\caption{Mögliche Treffpunktanzahlen}
|
||||
\label{fig:treffpunkte}
|
||||
\end{figure}
|
||||
|
||||
\begin{proof}
|
||||
Sei Lisa bei $L(x_{L},y_{L})$ und der Bus bei $B(x_{B},y_{B})$. $M(x_{M},y_{M})$ sei der Treffpunkt von Lisa mit dem Bus. $d$ sei der Weg, den Lisa zu diesem Punkt geht.
|
||||
\begin{align*}
|
||||
d &= \sqrt{(x_{L}-x_{M})^2 + (y_{L}-y_{M})^2} &&\text{(Satz des Pythagoras)} \\
|
||||
&= \sqrt{x_{L}^2 + (y_{L}-y_{M})^2} &&\text{($x_{B} = x_{M} = 0$)} \\
|
||||
d^2 &= x_{L}^2 + (y_{L}-y_{M})^2 \\
|
||||
&= x_{L}^2 + (y_{L}-y_{B}-2d)^2 &&\text{($y_{M} = y_{B} + 2d$)} \\
|
||||
&= x_{L}^2 + y_{L}^2 + y_{B}^2 + 4d^2 - 2y_{B}y_{M} - 4dy_{L} + 4dy_{B} \\
|
||||
-3d^2 + 4\cdot(y_{B}-y_{L})\cdot{}d &= x_{L}^2 + y_{L}^2 + y_{B}^2 - 2y_{B}y_{M} \\
|
||||
d &= \frac{a\pm\sqrt{a^2 + 12\cdot{}(-x_{L}^2 - y_{L}^2 - y_{B}^2 + 2y_{B}y_{M})}}{-6} &&\text{($a = 4\cdot(y_{B}-y_{L})$)}\qedhere
|
||||
\end{align*}
|
||||
\end{proof}
|
||||
|
||||
Für diese Gleichung gibt es maximal zwei nicht-negative Lösungen.
|
||||
|
||||
\section{Umsetzung}
|
||||
|
||||
\section{Beispiele}
|
||||
|
||||
\section{Quellcode}
|
||||
\lstinputlisting[frame=single,language=Rust,breaklines=true]{src/main.rs}
|
||||
|
||||
\end{document}
|
@ -4,17 +4,49 @@ use svg::node::element::{AnimateMotion, Circle, MotionPath};
|
||||
use svg::Document;
|
||||
use svg::Node;
|
||||
|
||||
use std::io;
|
||||
use std::fs;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub(crate) fn dump_svg(
|
||||
pub(crate) fn dump_route(house: Point, polys: &[Polygon], route: &Vec<RunState>) {
|
||||
let (points, lines, route1, route2_start) = gen_params(house, route);
|
||||
print!("{}", generate_svg(&points, &lines, polys, &route1, route2_start));
|
||||
}
|
||||
|
||||
pub(crate) fn save_svg(filename: &str, house: Point, polys: &[Polygon], route: &Vec<RunState>) {
|
||||
let (points, lines, route1, route2_start) = gen_params(house, route);
|
||||
fs::write(filename, generate_svg(&points, &lines, polys, &route1, route2_start)).unwrap();
|
||||
}
|
||||
|
||||
fn gen_params(house: Point, route: &Vec<RunState>) -> (Vec<(Point, &'static str)>, Vec<(Line, &'static str)>, Vec<Point>, Point) {
|
||||
let first = route.first().unwrap();
|
||||
let last = route.last().unwrap();
|
||||
let best_delay = last.delay;
|
||||
let points = vec![
|
||||
(house, "red"),
|
||||
(first.bus.translate(0.0.into(), best_delay), "yellow"),
|
||||
(last.bus, "orange"),
|
||||
];
|
||||
let lines = route
|
||||
.iter()
|
||||
.map(|x| x.pos)
|
||||
.collect::<LineString>()
|
||||
.lines()
|
||||
.map(|x| (x, "gray"))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let route1 = route.iter().map(|x| x.pos).collect::<Vec<_>>();
|
||||
let route2_start = first.bus.translate(0.0.into(), best_delay);
|
||||
(points, lines, route1, route2_start)
|
||||
}
|
||||
|
||||
pub(crate) fn generate_svg(
|
||||
points: &[(Point, &'static str)],
|
||||
lines: &[(Line, &'static str)],
|
||||
polys: &[Polygon],
|
||||
route1: &[Point],
|
||||
route2_start: Point,
|
||||
) {
|
||||
) -> String {
|
||||
let mut document = Document::new()
|
||||
// view box at (0, -200), w*h (200, 200)
|
||||
.set("viewBox", (0, -1100, 2100, 2100))
|
||||
@ -125,5 +157,5 @@ pub(crate) fn dump_svg(
|
||||
dot1.append(motion1);
|
||||
document.append(dot1);
|
||||
|
||||
svg::write(io::stdout(), &document).unwrap();
|
||||
document.to_string()
|
||||
}
|
||||
|
134
src/main.rs
134
src/main.rs
@ -1,23 +1,25 @@
|
||||
use geo::prelude::*;
|
||||
|
||||
use chrono::{Duration, NaiveTime};
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
mod display;
|
||||
mod input;
|
||||
|
||||
type Point = geo::Point<f32>;
|
||||
type Line = geo::Line<f32>;
|
||||
type LineString = geo::LineString<f32>;
|
||||
type Polygon = geo::Polygon<f32>;
|
||||
type Point = geo::Point<f64>;
|
||||
type Line = geo::Line<f64>;
|
||||
type LineString = geo::LineString<f64>;
|
||||
type Polygon = geo::Polygon<f64>;
|
||||
|
||||
// 30 km/h = 1 units/unit
|
||||
// 15 km/h = 0.5 units/unit
|
||||
// 30 km/h = 8+1/3 meters/second
|
||||
// 15 km/h = 4+1/6 meters/second
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct RunState {
|
||||
/// Theoretically possible maximum delay
|
||||
delay: f32,
|
||||
delay: f64,
|
||||
/// Our current location
|
||||
pos: Point,
|
||||
/// Current location of the bus, not including any delays
|
||||
@ -36,7 +38,11 @@ impl cmp::PartialOrd for RunState {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let bus = Point::new(0.0, -2000.0);
|
||||
// starting at 07:00, bus is 15 km away
|
||||
let start_time = NaiveTime::from_hms(7, 0, 0);
|
||||
let bus = Point::new(0.0, -15000.0);
|
||||
let bus_speed = 30.0 / 3.6;
|
||||
let delay_to_time = |delay| start_time + Duration::seconds((delay / bus_speed) as i64);
|
||||
|
||||
let data = input::read_input();
|
||||
let house = data.start;
|
||||
@ -58,25 +64,27 @@ fn main() {
|
||||
delay: max_possible_delay(bus, house),
|
||||
};
|
||||
|
||||
eprintln!("# Max. delay possible: {:?}", start.delay);
|
||||
eprintln!("# Max. delay possible: {:?}", delay_to_time(start.delay));
|
||||
|
||||
let mut states = BinaryHeap::new();
|
||||
states.push(vec![start]);
|
||||
|
||||
let mut best_delay = 0.0;
|
||||
let mut best = vec![];
|
||||
let save_prefix = "tmp3_";
|
||||
let mut save_counter = 0;
|
||||
|
||||
while states.peek().map(|x| x[0].delay > best_delay) == Some(true) {
|
||||
eprintln!(". {:?} states left:", states.len());
|
||||
//eprintln!(". {:?} states left:", states.len());
|
||||
let s = states.pop().unwrap();
|
||||
let last = &s[0]; //s.last().unwrap();
|
||||
eprintln!("{},{}", last.pos.x(), last.pos.y());
|
||||
//eprintln!("{},{}", last.pos.x(), last.pos.y());
|
||||
|
||||
// new states
|
||||
let mut all = vec![];
|
||||
|
||||
// attempt to go to any other vertex/point
|
||||
for next in &points {
|
||||
for next in points.iter().filter(|next| !s.iter().any(|x| x.pos == (**next).into())) {
|
||||
let next = Point::from(*next);
|
||||
if next != last.pos && none_intersect(&polys, &Line::new(last.pos, next)) {
|
||||
// could run to that point
|
||||
@ -94,82 +102,58 @@ fn main() {
|
||||
all.push(route);
|
||||
}
|
||||
}
|
||||
// attempt to go to the bus, with varying delays
|
||||
let mut bus_reached = false;
|
||||
for delay in float_range(last.delay.into(), 0.0) {
|
||||
let bus = last.bus.translate(0.0.into(), delay);
|
||||
let range = to_bus(bus, last.pos);
|
||||
if range.len() == 2 {
|
||||
bus_reached = true; // TODO: what if effectively unreachable?
|
||||
let range = Line::new(range[0], range[1]);
|
||||
for percent in float_range(0.0, 1.0) {
|
||||
let mut next = range.start;
|
||||
next.x += range.dx() * percent;
|
||||
next.y += range.dy() * percent;
|
||||
let next = Point::from(next);
|
||||
if none_intersect(&polys, &Line::new(last.pos, next)) {
|
||||
if delay > best_delay {
|
||||
// new high score!
|
||||
let mut route = s.clone();
|
||||
route.insert(
|
||||
0,
|
||||
RunState {
|
||||
pos: next,
|
||||
bus: next,
|
||||
delay,
|
||||
},
|
||||
);
|
||||
eprintln!("# New best delay {:?}", delay);
|
||||
best = route;
|
||||
best.reverse();
|
||||
best_delay = delay;
|
||||
} else {
|
||||
// not worth it
|
||||
}
|
||||
// attempt to go to the bus
|
||||
let bus = last.bus;
|
||||
let range = to_bus(bus, last.pos);
|
||||
if range.len() == 2 {
|
||||
let range = Line::new(range[0], range[1]);
|
||||
for percent in float_range(0.0, 1.0) {
|
||||
let mut next = range.start;
|
||||
next.x += range.dx() * percent;
|
||||
next.y += range.dy() * percent;
|
||||
let next = Point::from(next);
|
||||
let line = Line::new(last.pos, next);
|
||||
if none_intersect(&polys, &line) {
|
||||
let delay = line.end.y - bus.y() - line.end_point().euclidean_distance(&line.start_point()) * 2.0;
|
||||
if delay > best_delay {
|
||||
// new high score!
|
||||
let mut route = s.clone();
|
||||
route.insert(
|
||||
0,
|
||||
RunState {
|
||||
pos: next,
|
||||
bus: next,
|
||||
delay,
|
||||
},
|
||||
);
|
||||
eprintln!("# New best delay {:?} ({:?} states left)", delay_to_time(delay), states.len());
|
||||
best = route;
|
||||
best.reverse();
|
||||
best_delay = delay;
|
||||
display::save_svg(&format!("{}{}.svg", save_prefix, save_counter), house, &polys, &best);
|
||||
save_counter += 1;
|
||||
} else {
|
||||
// not worth it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if bus_reached {
|
||||
//eprintln!("-> adding all to queue");
|
||||
states.extend(all);
|
||||
}
|
||||
}
|
||||
eprintln!("d = {:?}", best_delay);
|
||||
eprintln!("d = {:?}", delay_to_time(best_delay));
|
||||
let route = best;
|
||||
eprintln!("Route:");
|
||||
for s in &route {
|
||||
eprintln!("{:.02},{:.02}", s.pos.x(), s.pos.y());
|
||||
}
|
||||
let first = route.first().unwrap();
|
||||
let last = route.last().unwrap();
|
||||
let points = vec![
|
||||
(house, "red"),
|
||||
(first.bus.translate(0.0.into(), best_delay), "yellow"),
|
||||
(last.bus, "orange"),
|
||||
];
|
||||
let lines = route
|
||||
.iter()
|
||||
.map(|x| x.pos)
|
||||
.collect::<LineString>()
|
||||
.lines()
|
||||
.map(|x| (x, "gray"))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
display::dump_svg(
|
||||
&points,
|
||||
&lines,
|
||||
&polys,
|
||||
&route.iter().map(|x| x.pos).collect::<Vec<_>>(),
|
||||
first.bus.translate(0.0.into(), best_delay),
|
||||
);
|
||||
display::dump_route(house, &polys, &route);
|
||||
}
|
||||
|
||||
/// [a; b]
|
||||
fn float_range(a: f32, b: f32) -> impl Iterator<Item = f32> {
|
||||
const STEPS: usize = 25;
|
||||
fn float_range(a: f64, b: f64) -> impl Iterator<Item = f64> {
|
||||
const STEPS: usize = 1000;
|
||||
let d = b - a;
|
||||
(0..=STEPS).map(move |s| a + ((s as f32) * d) / STEPS as f32)
|
||||
(0..=STEPS).map(move |s| a + ((s as f64) * d) / STEPS as f64)
|
||||
}
|
||||
|
||||
fn none_intersect(polys: &[Polygon], line: &Line) -> bool {
|
||||
@ -236,11 +220,11 @@ fn none_intersect(polys: &[Polygon], line: &Line) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn distance(a: Point, b: Point) -> f32 {
|
||||
fn distance(a: Point, b: Point) -> f64 {
|
||||
((a.x() - b.x()).powi(2) + (a.y() - b.y()).powi(2)).sqrt()
|
||||
}
|
||||
|
||||
fn max_possible_delay(bus: Point, start: Point) -> f32 {
|
||||
fn max_possible_delay(bus: Point, start: Point) -> f64 {
|
||||
let a = start.x();
|
||||
let b = start.y();
|
||||
let c = bus.x();
|
||||
|
Loading…
Reference in New Issue
Block a user