Rust code for gridless pathfinding
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user