hexagon_map/sparse_map/
path_finder.rs1use super::*;
2
3use crate::HexPoint;
4use ordered_float::OrderedFloat;
5use pathfinding::prelude::astar;
6
7pub struct PathFinder<'a, T> {
9 map: &'a HexagonMap<T>,
10 start: CubicPoint,
11 end: CubicPoint,
12 passable: Box<dyn Fn(&CubicPoint, &T) -> bool>,
13 action_cost: Box<dyn Fn(&CubicPoint, &T) -> f64>,
14}
15
16impl<T> HexagonMap<T> {
17 pub fn path_finder(&self, start: CubicPoint, end: CubicPoint) -> PathFinder<T> {
31 PathFinder { map: self, start, end, passable: Box::new(|_, _| true), action_cost: Box::new(|_, _| 1.0) }
32 }
33}
34
35impl<'a, T> PathFinder<'a, T> {
36 pub fn with_passable<F>(mut self, passable: F) -> Self
50 where
51 F: Fn(&CubicPoint, &T) -> bool + 'static,
52 {
53 self.passable = Box::new(passable);
54 self
55 }
56 pub fn with_cost<F>(mut self, cost: F) -> Self
70 where
71 F: Fn(&CubicPoint, &T) -> f64 + 'static,
72 {
73 self.action_cost = Box::new(cost);
74 self
75 }
76 pub fn get_point(&self, point: &CubicPoint) -> Option<&T> {
77 self.map.sparse.get(point)
78 }
79 pub fn has_point(&self, point: &CubicPoint) -> bool {
80 self.map.sparse.contains_key(point)
81 }
82 fn distance(&self, point: &CubicPoint) -> OrderedFloat<f64> {
83 OrderedFloat(self.end.taxicab_distance(*point) as f64)
84 }
85 pub fn neighbors(&self, point: &CubicPoint) -> Vec<(CubicPoint, OrderedFloat<f64>)> {
87 let mut neighbors = vec![];
88 for direction in Orientation::all() {
89 if let Some(target) = self.map.sparse.get(&point.go(direction)) {
90 if (self.passable)(point, target) {
91 let cost = (self.action_cost)(point, target);
92 neighbors.push((point.go(direction), OrderedFloat(cost)));
93 }
94 }
95 }
96 neighbors
97 }
98 pub fn solve_points(self) -> (Vec<CubicPoint>, f64) {
99 astar(&self.start, |point| self.neighbors(point), |point| self.distance(point), |point| self.end.eq(point))
100 .map(|(path, cost)| (path, cost.0))
101 .unwrap_or((vec![], f64::INFINITY))
102 }
103 pub fn solve_joint(self) -> (Vec<Joint>, f64) {
104 todo!()
105 }
106}