Initial commit

This commit is contained in:
Arne Keller 2019-01-17 18:37:39 +01:00
commit ce36020814
6 changed files with 660 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
**/*.rs.bk

265
Cargo.lock generated Normal file
View 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
View 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
View 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
View 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
View 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![]);
}