Always keep tokenSize/2 distance from walls

This commit is contained in:
Manuel Vögele
2022-02-02 10:36:03 +01:00
parent b55af992ec
commit 4d6543174a
3 changed files with 68 additions and 14 deletions
+3 -1
View File
@@ -18,8 +18,10 @@ export function isPathfindingEnabled() {
export function findPath(from, to, token, previousWaypoints) { export function findPath(from, to, token, previousWaypoints) {
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) { if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
// TODO Store multiple pathfinders for different token sizes
let tokenSize = Math.max(token.data.width, token.data.height) * canvas.dimensions.size;
if (!gridlessPathfinder) if (!gridlessPathfinder)
gridlessPathfinder = GridlessPathfinding.initialize(canvas.walls.placeables); gridlessPathfinder = GridlessPathfinding.initialize(canvas.walls.placeables, tokenSize);
paintGridlessPathfindingDebug(gridlessPathfinder); paintGridlessPathfindingDebug(gridlessPathfinder);
return GridlessPathfinding.findPath(gridlessPathfinder, from, to); return GridlessPathfinding.findPath(gridlessPathfinder, from, to);
} }
+2 -2
View File
@@ -74,13 +74,13 @@ impl Wall {
#[allow(dead_code)] #[allow(dead_code)]
#[wasm_bindgen] #[wasm_bindgen]
pub fn initialize(js_walls: Vec<JsValue>) -> Pathfinder { pub fn initialize(js_walls: Vec<JsValue>, token_size: f64) -> Pathfinder {
let mut walls = Vec::with_capacity(js_walls.len()); let mut walls = Vec::with_capacity(js_walls.len());
for wall in js_walls { for wall in js_walls {
let wall = JsWall::from(wall); let wall = JsWall::from(wall);
walls.push(Wall::from_js(&wall)); walls.push(Wall::from_js(&wall));
} }
Pathfinder::initialize(walls) Pathfinder::initialize(walls, token_size)
} }
#[allow(dead_code)] #[allow(dead_code)]
+61 -9
View File
@@ -147,10 +147,11 @@ pub struct Pathfinder {
} }
impl Pathfinder { impl Pathfinder {
pub fn initialize<I>(walls: I) -> Self pub fn initialize<I>(walls: I, token_size: f64) -> Self
where where
I: IntoIterator<Item = Wall>, I: IntoIterator<Item = Wall>,
{ {
let distance_from_walls = token_size / 2.0;
let mut endpoints = FxHashMap::<Point, Vec<f64>>::default(); let mut endpoints = FxHashMap::<Point, Vec<f64>>::default();
let mut line_segments = Vec::new(); let mut line_segments = Vec::new();
for wall in walls { for wall in walls {
@@ -180,8 +181,27 @@ impl Pathfinder {
if angle_diff <= PI { if angle_diff <= PI {
continue; continue;
} }
if angle_diff > 1.5 * PI {
let angle_between = angle_diff / 2.0 + angle1; let angle_between = angle_diff / 2.0 + angle1;
nodes.push(calc_pathfinding_node(point, angle_between)); nodes.push(calc_pathfinding_node(
point,
angle_between,
distance_from_walls,
&mut line_segments,
));
}
nodes.push(calc_pathfinding_node(
point,
angle1 + 0.5 * PI,
distance_from_walls,
&mut line_segments,
));
nodes.push(calc_pathfinding_node(
point,
angle2 - 0.5 * PI,
distance_from_walls,
&mut line_segments,
));
} }
let angle1 = angles.last().unwrap(); let angle1 = angles.last().unwrap();
let angle2 = angles.first().unwrap() + 2.0 * PI; let angle2 = angles.first().unwrap() + 2.0 * PI;
@@ -189,9 +209,27 @@ impl Pathfinder {
if angle_diff <= PI { if angle_diff <= PI {
continue; continue;
} }
if angle_diff > 1.5 * PI {
let angle_between = angle_diff / 2.0 + angle1; let angle_between = angle_diff / 2.0 + angle1;
let angle_between = angle_between.rem_euclid(2.0 * PI); nodes.push(calc_pathfinding_node(
nodes.push(calc_pathfinding_node(point, angle_between)); point,
angle_between,
distance_from_walls,
&mut line_segments,
));
}
nodes.push(calc_pathfinding_node(
point,
angle1 + 0.5 * PI,
distance_from_walls,
&mut line_segments,
));
nodes.push(calc_pathfinding_node(
point,
angle2 - 0.5 * PI,
distance_from_walls,
&mut line_segments,
));
} }
// TODO Eliminating nodes close to each other may improve performance // TODO Eliminating nodes close to each other may improve performance
Self { Self {
@@ -263,9 +301,23 @@ impl Pathfinder {
} }
} }
fn calc_pathfinding_node(p: Point, angle: f64) -> NodePtr { fn calc_pathfinding_node(
let diatance_from_walls = 10.0; p: Point,
let x = p.x + angle.cos() * diatance_from_walls; angle: f64,
let y = p.y + angle.sin() * diatance_from_walls; distance_from_walls: f64,
NodePtr::from(Node::new(Point { x, y })) line_segments: &mut Vec<LineSegment>,
) -> NodePtr {
let offset_x = angle.cos() * distance_from_walls;
let offset_y = angle.sin() * distance_from_walls;
line_segments.push(LineSegment::new(
p,
Point {
x: p.x + offset_x * 0.99,
y: p.y + offset_y * 0.99,
},
));
NodePtr::from(Node::new(Point {
x: p.x + offset_x,
y: p.y + offset_y,
}))
} }