Rust code for gridless pathfinding

This commit is contained in:
Manuel Vögele
2022-01-31 21:48:20 +01:00
parent dc85609a75
commit 08f41ed2ff
8 changed files with 463 additions and 3 deletions
+118
View File
@@ -0,0 +1,118 @@
use js_sys::Array;
use wasm_bindgen::prelude::*;
use crate::{
geometry::Point,
pathfinder::{DiscoveredNodePtr, Pathfinder},
};
#[allow(unused)]
macro_rules! log {
( $( $t:tt )* ) => {
log(&format!( $( $t )* ));
};
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name=warn)]
pub fn log(s: &str);
}
#[wasm_bindgen(
inline_js = "export function collidesWithWall(p1, p2) { return canvas.walls.checkCollision(new Ray(p1, p2)); }"
)]
extern "C" {
#[wasm_bindgen(js_name=collidesWithWall)]
pub fn collides_with_wall(p1: Point, p2: Point) -> bool;
}
#[wasm_bindgen]
extern "C" {
pub type JsWall;
pub type JsWallData;
#[wasm_bindgen(method, getter)]
fn data(this: &JsWall) -> JsWallData;
#[wasm_bindgen(method, getter)]
fn c(this: &JsWallData) -> Vec<f64>;
}
#[derive(Debug, Clone, Copy)]
pub struct Wall {
pub p1: Point,
pub p2: Point,
}
impl Wall {
pub fn new(p1: Point, p2: Point) -> Self {
Self { p1, p2 }
}
}
impl Wall {
fn from_js(wall: &JsWall) -> Self {
let data = wall.data();
let mut c = data.c();
c.iter_mut().for_each(|val| *val = val.round());
Self::new(Point::new(c[0], c[1]), Point::new(c[2], c[3]))
}
}
#[allow(dead_code)]
#[wasm_bindgen(js_name=buildCache)]
pub fn initialize(js_walls: Vec<JsValue>) -> Pathfinder {
let mut walls = Vec::with_capacity(js_walls.len());
for wall in js_walls {
let wall = JsWall::from(wall);
walls.push(Wall::from_js(&wall));
}
Pathfinder::initialize(walls)
}
#[allow(dead_code)]
#[wasm_bindgen]
pub fn free(pathfinder: Pathfinder) {
drop(pathfinder);
}
#[allow(dead_code)]
#[wasm_bindgen(js_name=findPath)]
pub fn find_path(pathfinder: &mut Pathfinder, from: Point, to: Point) -> Option<Array> {
if let Some(first_node) = pathfinder.find_path(from, to) {
Some(first_node.iter_path().map(JsValue::from).collect())
} else {
None
}
}
trait IteratePath {
fn iter_path(&self) -> PathIterator;
}
impl IteratePath for DiscoveredNodePtr {
fn iter_path(&self) -> PathIterator {
PathIterator {
current_node: Some(self.clone()),
}
}
}
struct PathIterator {
current_node: Option<DiscoveredNodePtr>,
}
impl Iterator for PathIterator {
type Item = Point;
fn next(&mut self) -> Option<Self::Item> {
if let Some(node) = self.current_node.clone() {
let point = node.borrow().node.borrow().point;
self.current_node = node.borrow().previous.clone();
Some(point)
} else {
None
}
}
}