Initial commit
This commit is contained in:
commit
ce36020814
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
265
Cargo.lock
generated
Normal file
265
Cargo.lock
generated
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
[[package]]
|
||||||
|
name = "Aufgabe1"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"decorum 0.1.2",
|
||||||
|
"geo 0.11.0",
|
||||||
|
"pathfinding 1.1.11-pre",
|
||||||
|
"svg 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace-sys"
|
||||||
|
version = "0.1.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "decorum"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "failure"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "failure_derive"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geo"
|
||||||
|
version = "0.11.0"
|
||||||
|
dependencies = [
|
||||||
|
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"geo-types 0.3.0",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rstar 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geo-types"
|
||||||
|
version = "0.3.0"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rstar 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathfinding"
|
||||||
|
version = "1.1.11-pre"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pdqselect"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "0.4.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "0.6.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rstar"
|
||||||
|
version = "0.1.1"
|
||||||
|
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)",
|
||||||
|
"pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "svg"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "0.15.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727"
|
||||||
|
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
|
||||||
|
"checksum backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3fcce89e5ad5c8949caa9434501f7b55415b3e7ad5270cb88c75a8d35e8f1279"
|
||||||
|
"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 either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||||
|
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
|
||||||
|
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
|
||||||
|
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
|
||||||
|
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||||
|
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
|
||||||
|
"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
|
||||||
|
"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.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
|
||||||
|
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
||||||
|
"checksum rstar 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64ffe043929ee67d46694af1a4851f6bbe571b52a55677ba1686222dc35fd449"
|
||||||
|
"checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7"
|
||||||
|
"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7"
|
||||||
|
"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b"
|
||||||
|
"checksum svg 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7518a18ac78da03c41ca0611128c6d8adf1efae0773c337d6c19793dce860c9b"
|
||||||
|
"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
|
||||||
|
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||||
|
"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"
|
||||||
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "Aufgabe1"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["arne"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
geo = { path = "/home/arne/Documents/Code/Github/geo/geo" }
|
||||||
|
svg = "0.5.11"
|
||||||
|
pathfinding = { path = "/home/arne/Documents/Code/Github/pathfinding" }
|
||||||
|
decorum = { path = "/home/arne/Documents/Code/Github/decorum" }
|
65
src/display.rs
Normal file
65
src/display.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use svg::Document;
|
||||||
|
use svg::Node;
|
||||||
|
use svg::node::element::Circle;
|
||||||
|
use svg::node::element::Path;
|
||||||
|
use svg::node::element::path::Data;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'static str)], polys: &[Polygon]) {
|
||||||
|
let mut document = Document::new()
|
||||||
|
// view box at (0, -200), w*h (200, 200)
|
||||||
|
.set("viewBox", (0, -200, 200, 200));
|
||||||
|
|
||||||
|
for circle in points.iter().map(|(p, color)| {
|
||||||
|
Circle::new()
|
||||||
|
.set("cx", f64::from(p.x()))
|
||||||
|
.set("cy", f64::from(-p.y()))
|
||||||
|
.set("r", 1.2)
|
||||||
|
.set("fill", *color)
|
||||||
|
}) {
|
||||||
|
document.append(circle);
|
||||||
|
}
|
||||||
|
for path in lines.iter().map(|(l, color)| {
|
||||||
|
let data = Data::new()
|
||||||
|
.move_to((f64::from(l.start.x), f64::from(-l.start.y)))
|
||||||
|
.line_to((f64::from(l.end.x), f64::from(-l.end.y)))
|
||||||
|
.close();
|
||||||
|
|
||||||
|
Path::new()
|
||||||
|
.set("fill", "none")
|
||||||
|
.set("stroke", *color)
|
||||||
|
.set("stroke-width", 0.5)
|
||||||
|
.set("d", data)
|
||||||
|
}) {
|
||||||
|
document.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
for path in polys.iter().map(|poly| {
|
||||||
|
let coords = &poly.exterior.0;
|
||||||
|
let first = coords[0].x_y();
|
||||||
|
let mut first: (f64, f64) = (first.0.into(), first.1.into());
|
||||||
|
first.1 *= -1.0;
|
||||||
|
let mut data = Data::new()
|
||||||
|
.move_to(first);
|
||||||
|
for c in &coords[1..] {
|
||||||
|
let c = c.x_y();
|
||||||
|
let mut c: (f64, f64) = (c.0.into(), c.1.into());
|
||||||
|
c.1 *= -1.0;
|
||||||
|
data = data.line_to(c);
|
||||||
|
}
|
||||||
|
data = data.close();
|
||||||
|
|
||||||
|
Path::new()
|
||||||
|
.set("fill", "black")
|
||||||
|
.set("stroke", "black")
|
||||||
|
.set("stroke-width", 0)
|
||||||
|
.set("d", data)
|
||||||
|
}) {
|
||||||
|
document.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg::write(io::stdout(), &document).unwrap();
|
||||||
|
}
|
21
src/input.rs
Normal file
21
src/input.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) struct InputData {
|
||||||
|
pub start: Point,
|
||||||
|
pub polys: Vec<Polygon>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_input() -> InputData {
|
||||||
|
let mut polys = vec![];
|
||||||
|
polys.push(Polygon::new(vec![[2.0.into(), 0.0.into()], [6.0.into(), 0.0.into()], [6.0.into(), 6.0.into()], [2.0.into(), 5.0.into()]].into(), vec![]));
|
||||||
|
polys.push(Polygon::new(vec![[1.0.into(), 20.0.into()], [2.0.into(), 20.0.into()], [2.0.into(), 23.0.into()], [1.0.into(), 23.0.into()]].into(), vec![]));
|
||||||
|
polys.push(Polygon::new(vec![[1.0.into(), 25.0.into()], [2.0.into(), 25.0.into()], [2.0.into(), 28.0.into()], [1.0.into(), 28.0.into()]].into(), vec![]));
|
||||||
|
let mut stick = Polygon::new(vec![[1.0.into(), 115.0.into()], [2.0.into(), 115.0.into()], [2.0.into(), 130.0.into()], [1.0.into(), 130.0.into()]].into(), vec![]);
|
||||||
|
polys.push(stick.clone());
|
||||||
|
stick = stick.translate(35.0.into(), (-20.0).into());
|
||||||
|
polys.push(stick);
|
||||||
|
InputData {
|
||||||
|
start: Point::new(45.0.into(), 95.0.into()),
|
||||||
|
polys
|
||||||
|
}
|
||||||
|
}
|
296
src/main.rs
Normal file
296
src/main.rs
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
use geo::*;
|
||||||
|
use geo::prelude::*;
|
||||||
|
|
||||||
|
use pathfinding::prelude::*;
|
||||||
|
|
||||||
|
use decorum::R64;
|
||||||
|
use decorum::Real;
|
||||||
|
|
||||||
|
use std::cmp;
|
||||||
|
use std::collections::BinaryHeap;
|
||||||
|
|
||||||
|
mod display;
|
||||||
|
mod input;
|
||||||
|
|
||||||
|
type Point = geo::Point<R64>;
|
||||||
|
type Line = geo::Line<R64>;
|
||||||
|
type LineString = geo::LineString<R64>;
|
||||||
|
type Polygon = geo::Polygon<R64>;
|
||||||
|
|
||||||
|
// 30 km/h = 1 units/unit
|
||||||
|
// 15 km/h = 0.5 units/unit
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct RunState {
|
||||||
|
/// Theoretically possible maximum delay
|
||||||
|
delay: R64,
|
||||||
|
/// Our current location
|
||||||
|
pos: Point,
|
||||||
|
/// Current location of the bus, not including any delays
|
||||||
|
bus: Point
|
||||||
|
}
|
||||||
|
impl cmp::Ord for RunState {
|
||||||
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||||
|
self.delay.cmp(&other.delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl cmp::PartialOrd for RunState {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let bus = Point::new(0.0.into(), 0.0.into());
|
||||||
|
/*
|
||||||
|
let house = Point::new(8.0, 20.0);
|
||||||
|
|
||||||
|
let targets = to_bus(bus, house);
|
||||||
|
|
||||||
|
let mut lines = vec![];
|
||||||
|
if targets.len() == 2 {
|
||||||
|
lines.push((Line::new(house, targets[0]), "orange"));
|
||||||
|
lines.push((Line::new(house, targets[1]), "orange"));
|
||||||
|
}
|
||||||
|
display::dump_svg(
|
||||||
|
&[(bus, "#ffa700"), (house, "green"), (targets[0], "red"), (targets[1], "red")],
|
||||||
|
&lines
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
let data = input::read_input();
|
||||||
|
let house = data.start;
|
||||||
|
let polys = data.polys;
|
||||||
|
let points = polys.iter().map(|x| x.exterior.0.clone()).flatten().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let start = RunState {
|
||||||
|
pos: house,
|
||||||
|
bus: bus,
|
||||||
|
delay: max_possible_delay(bus, house)
|
||||||
|
//route: vec![house],
|
||||||
|
//length: 0.0.into()
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
eprintln!("# Max delay possible: {:?}", start.delay);
|
||||||
|
|
||||||
|
let mut states = BinaryHeap::new();
|
||||||
|
states.push(vec![start]);
|
||||||
|
|
||||||
|
let mut best_delay = R64::from(0.0);
|
||||||
|
let mut best = vec![];
|
||||||
|
|
||||||
|
while states.peek().map(|x| x.last().unwrap().delay > best_delay) == Some(true) {
|
||||||
|
eprintln!(". {:?} states left", states.len());
|
||||||
|
let s = states.pop().unwrap();
|
||||||
|
let last = s.last().unwrap();
|
||||||
|
|
||||||
|
// new states
|
||||||
|
let mut all = vec![];
|
||||||
|
|
||||||
|
// attempt to go to any other vertex/point
|
||||||
|
for next in &points {
|
||||||
|
let next = Point::from(*next);
|
||||||
|
if next != last.pos && none_intersect(&polys, &Line::new(last.pos, next)) {
|
||||||
|
// could run to that point
|
||||||
|
let bus_next = last.bus.translate(0.0.into(), distance(last.pos, next) * R64::from(2.0));
|
||||||
|
let mut route = s.clone();
|
||||||
|
eprintln!("{},{} would go {},{}", last.pos.x(), last.pos.y(), next.x(), next.y());
|
||||||
|
route.push(RunState {
|
||||||
|
pos: next,
|
||||||
|
bus: bus_next,
|
||||||
|
delay: max_possible_delay(bus_next, next)
|
||||||
|
});
|
||||||
|
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).map(R64::from) {
|
||||||
|
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).map(R64::from) {
|
||||||
|
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.push(RunState {
|
||||||
|
pos: next,
|
||||||
|
bus: next,
|
||||||
|
delay
|
||||||
|
});
|
||||||
|
eprintln!("# New best delay {:?}", delay);
|
||||||
|
best = route;
|
||||||
|
best_delay = delay;
|
||||||
|
} else {
|
||||||
|
// not worth it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bus_reached {
|
||||||
|
states.extend(all);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
eprintln!("d = {:?}", best_delay);
|
||||||
|
let route = best;
|
||||||
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if let Some(route) = dijkstra::<_, R64, _, _, _>(&start, |node| {
|
||||||
|
eprintln!("{:?}", node);
|
||||||
|
if node.pos.x() == 0.0 {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
assert!(node.pos.x() > 0.0);
|
||||||
|
// get successors (next points)
|
||||||
|
let mut all = Vec::new();
|
||||||
|
|
||||||
|
// try to go to any points of any polygon
|
||||||
|
for next in &points {
|
||||||
|
let next = Point::from(*next);
|
||||||
|
if none_intersect(&polys, &Line::new(node.pos, next)) {
|
||||||
|
eprintln!("{},{} would go {},{}", node.pos.x(), node.pos.y(), next.x(), next.y());
|
||||||
|
all.push((RunState {
|
||||||
|
pos: next,
|
||||||
|
bus: node.bus.translate(0.0.into(), distance(node.pos, next) * R64::from(2.0)),
|
||||||
|
delay: node.delay,
|
||||||
|
}, 0.0.into()));
|
||||||
|
} else {
|
||||||
|
eprintln!("{},{} can't go {},{}", node.pos.x(), node.pos.y(), next.x(), next.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to go the bus
|
||||||
|
for delay in float_range(100.0, 0.0).map(R64::from) {
|
||||||
|
let bus = node.bus.translate(0.0.into(), delay);
|
||||||
|
let range = to_bus(bus, node.pos);
|
||||||
|
if !range.is_empty() {
|
||||||
|
let range = Line::new(range[0], range[1]);
|
||||||
|
for percent in float_range(0.0, 1.0).map(R64::from) {
|
||||||
|
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(node.pos, next)) {
|
||||||
|
let cost = distance(node.pos, next);
|
||||||
|
//eprintln!("(delay {:02}) go from {:?} len {:.2} to {:?}", delay, node.pos, cost, next);
|
||||||
|
all.push((RunState {
|
||||||
|
pos: next,
|
||||||
|
bus: next,
|
||||||
|
delay,
|
||||||
|
//route: { let mut route = node.route.clone(); route.push(next); route },
|
||||||
|
//length: node.length + cost
|
||||||
|
}, -delay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all
|
||||||
|
/*
|
||||||
|
}, |node| {
|
||||||
|
// heuristic
|
||||||
|
// -> current x coordinate ?
|
||||||
|
//node.pos.x()
|
||||||
|
0.0.into()
|
||||||
|
*/
|
||||||
|
}, |node| {
|
||||||
|
// success condition
|
||||||
|
node.pos.x() == 0.0 && node.delay > R64::from(5.0)
|
||||||
|
}) {
|
||||||
|
eprintln!("route found");
|
||||||
|
let first = route.0.first().unwrap();
|
||||||
|
let last = route.0.last().unwrap();
|
||||||
|
let delay = last.delay;
|
||||||
|
eprintln!("d = {}", delay);
|
||||||
|
let points = vec![(house, "red"), (first.bus.translate(0.0.into(), delay), "yellow"), (last.bus, "orange")];
|
||||||
|
let lines = route.0.iter().map(|x| x.pos).collect::<LineString>().lines().map(|x| {
|
||||||
|
(x, "gray")
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
display::dump_svg(&points, &lines, &polys);
|
||||||
|
} else {
|
||||||
|
eprintln!("no route found!");
|
||||||
|
}
|
||||||
|
// */
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [a; b]
|
||||||
|
fn float_range(a: f64, b: f64) -> impl Iterator<Item = f64> {
|
||||||
|
const STEPS: usize = 200;
|
||||||
|
let d = b - a;
|
||||||
|
(0..=STEPS).map(move |s| a + ((s as f64) * d)/STEPS as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn none_intersect(polys: &[Polygon], line: &Line) -> bool {
|
||||||
|
for p in polys {
|
||||||
|
for l in p.exterior.lines() {
|
||||||
|
if l.start == line.start || l.end == line.end || l.start == line.end || l.end == line.start {
|
||||||
|
continue; // would always intersect with itself
|
||||||
|
}
|
||||||
|
if l.intersects(line) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distance(a: Point, b: Point) -> R64 {
|
||||||
|
((a.x() - b.x()).powi(2) + (a.y() - b.y()).powi(2)).sqrt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_possible_delay(bus: Point, start: Point) -> R64 {
|
||||||
|
let a = start.x();
|
||||||
|
let b = start.y();
|
||||||
|
let c = bus.x();
|
||||||
|
assert_eq!(c, 0.0);
|
||||||
|
let d = bus.y();
|
||||||
|
|
||||||
|
b - ((a.powi(2)) * R64::from(3.0)).sqrt() - d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go straight to the bus. Returns the points where the bus can be reached.
|
||||||
|
fn to_bus(bus: Point, start: Point) -> Vec<Point> {
|
||||||
|
let a = start.x();
|
||||||
|
let b = start.y();
|
||||||
|
let c = bus.x();
|
||||||
|
let d = bus.y();
|
||||||
|
|
||||||
|
let v: R64 = -a.powi(2) * R64::from(3.0) + R64::from(6.0) * a * c + b.powi(2) - R64::from(2.0) * b * d - R64::from(3.0) * c.powi(2) + d.powi(2);
|
||||||
|
if v >= 0.0 {
|
||||||
|
// v = sqrt(-3 A^2 + 6 A C + B^2 - 2 B D - 3 C^2 + D^2)
|
||||||
|
let v = v.sqrt();
|
||||||
|
// x = 1/3 (+-v + 2 B - 2 D)
|
||||||
|
let x1: R64 = (v + R64::from(2.0) * b - R64::from(2.0) * d) / R64::from(3.0);
|
||||||
|
let x2: R64 = (-v + R64::from(2.0) * b - R64::from(2.0) * d) / R64::from(3.0);
|
||||||
|
if x1 > R64::from(0.0) && x2 > R64::from(0.0) {
|
||||||
|
vec![bus.translate(0.0.into(), R64::from(2.0) * x1), bus.translate(0.0.into(), R64::from(2.0) * x2)]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn test_to_bus() {
|
||||||
|
assert!(to_bus(Coordinate { x: 0.0.into(), y: 0.0.into() }.into(), Coordinate { x: 1.0.into(), y: 23.0.into() }.into()).len() == 2);
|
||||||
|
assert_eq!(to_bus(Coordinate { x: 0.0.into(), y: 168.7601848778319.into() }.into(), Coordinate { x: 1.0.into(), y: 23.0.into() }.into()), vec![]);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user