path_finding_lib/search/
a_star.rs1#[cfg(test)]
2use std::collections::HashMap;
3
4use crate::{graph::Graph, path::PathFinding};
5#[cfg(test)]
6use crate::graph::Edge;
7use crate::node::{Node, Position};
8use crate::search::dijkstra;
9
10pub fn get_position(node_id: usize, graph: &Graph) -> &Position {
11 match &graph.node_position_lookup {
12 None => panic!("You must offer node positions to the graph before using this heuristic."),
13 Some(positions) => {
14 return match positions.get(&node_id) {
15 None => panic!("Node position missing for given node id: {node_id}"),
16 Some(position) => position
17 };
18 }
19 };
20}
21
22pub fn euclidean_distance(source: usize, destination: usize, graph: &Graph) -> f32 {
23 let src = get_position(source, graph);
24 let dest = get_position(destination, graph);
25
26 return ((dest.x - src.x).powf(2.0) + (dest.y - src.y).powf(2.0) + (dest.z - src.z).powf(2.0)).sqrt();
27}
28
29pub fn manhattan_distance(source: usize, destination: usize, graph: &Graph) -> f32 {
30 let src = get_position(source, graph);
31 let dest = get_position(destination, graph);
32
33 return (dest.x - src.x).abs() + (dest.y - src.y).abs() + (dest.z - src.z).abs();
34}
35
36pub struct AStar {
37 pub heuristic: Box<dyn Fn(usize, usize, &Graph) -> f32>,
38}
39
40impl PathFinding for AStar {
41 fn execute(&self, source: Node, target: Node, graph: &Graph) -> Graph {
42 return dijkstra(source, target, graph, &self.heuristic);
43 }
44}
45
46
47#[test]
48#[should_panic(expected = "You must offer node positions to the graph before using this heuristic.")]
49fn missing_node_positions_should_cause_panic() {
50 get_position(1, &Graph::from(Vec::from([
51 Edge::from(0, 0, 1, 4.0)
52 ])));
53}
54
55#[test]
56#[should_panic(expected = "Node position missing for given node id: 1")]
57fn missing_node_position_should_cause_panic() {
58 let mut graph = Graph::from(Vec::from([
59 Edge::from(0, 0, 1, 4.0)
60 ]));
61
62 graph.offer_positions(HashMap::from([(0, Position::from(0.0, 0.0, 0.0))]));
63
64 get_position(1, &graph);
65}
66
67#[test]
68fn node_position_should_be_returned() {
69 let mut graph = Graph::from(Vec::from([
70 Edge::from(0, 0, 1, 4.0)
71 ]));
72
73 graph.offer_positions(HashMap::from([(1, Position::from(0.1, 0.2, 0.3))]));
74 let pos = get_position(1, &graph);
75
76 assert_eq!(0.1, pos.x);
77 assert_eq!(0.2, pos.y);
78 assert_eq!(0.3, pos.z);
79}
80
81#[test]
82fn euclidean_heuristic_should_return_dist() {
83 let mut graph = Graph::from(Vec::from([
84 Edge::from(0, 0, 1, 4.0)
85 ]));
86
87 graph.offer_positions(HashMap::from([
88 (0, Position::from(20.0, 30.0, 90.0)),
89 (1, Position::from(80.0, 44.0, 40.0))
90 ]));
91
92 assert_eq!(79.347336, euclidean_distance(0, 1, &graph));
93}
94
95#[test]
96fn manhattan_heuristic_should_return_dist() {
97 let mut graph = Graph::from(Vec::from([
98 Edge::from(0, 0, 1, 4.0)
99 ]));
100
101 graph.offer_positions(HashMap::from([
102 (0, Position::from(2.0, 9.0, 0.0)),
103 (1, Position::from(3.0, 5.0, 0.0))
104 ]));
105
106 assert_eq!(5.0, manhattan_distance(0, 1, &graph));
107}