Cleanup edge to the last node when done with pathfinding

This commit is contained in:
Manuel Vögele
2022-02-01 01:26:34 +01:00
parent 1e14ff24b0
commit 1f434b3f6b
+47 -11
View File
@@ -18,11 +18,20 @@ pub struct Edge {
pub struct Node { pub struct Node {
pub point: Point, pub point: Point,
edges: Option<Vec<Edge>>, edges: Option<Vec<Edge>>,
final_edge: Option<Option<Edge>>,
} }
impl Node { impl Node {
pub fn new(point: Point) -> Self { pub fn new(point: Point) -> Self {
Self { point, edges: None } Self {
point,
edges: None,
final_edge: None,
}
}
fn iter_edges(&self) -> std::iter::Chain<std::slice::Iter<'_, Edge>, std::option::Iter<'_, Edge>> {
self.edges.as_ref().unwrap().iter().chain(self.final_edge.as_ref().unwrap().iter())
} }
} }
@@ -50,7 +59,10 @@ impl From<DiscoveredNode> for DiscoveredNodePtr {
} }
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct NodeStorage(Vec<NodePtr>); pub struct NodeStorage {
regular_nodes: Vec<NodePtr>,
final_node: Option<NodePtr>,
}
impl NodeStorage { impl NodeStorage {
fn new() -> Self { fn new() -> Self {
@@ -58,16 +70,30 @@ impl NodeStorage {
} }
fn push(&mut self, node: NodePtr) { fn push(&mut self, node: NodePtr) {
self.0.push(node); self.regular_nodes.push(node);
} }
fn initialize_edges(&self, node: &NodePtr) { fn initialize_edges(&mut self, node: &NodePtr) {
if node.borrow().final_edge.is_none() {
let final_edge = self
.final_node
.as_ref()
.filter(|neighbor| {
!collides_with_wall(node.borrow().point, neighbor.borrow().point)
})
.map(|neighbor| Edge {
target: neighbor.clone(),
cost: node.borrow().point.distance_to(neighbor.borrow().point),
});
node.borrow_mut().final_edge = Some(final_edge);
}
if node.borrow().edges.is_some() { if node.borrow().edges.is_some() {
return; return;
} }
let point = node.borrow().point; let point = node.borrow().point;
let mut edges = Vec::new(); let mut edges = Vec::new();
for neighbor in &self.0 { for neighbor in &self.regular_nodes {
if Rc::ptr_eq(neighbor, node) { if Rc::ptr_eq(neighbor, node) {
continue; continue;
} }
@@ -80,12 +106,22 @@ impl NodeStorage {
}); });
} }
} }
node.borrow_mut().edges = Some(edges); node.borrow_mut().edges = Some(edges);
} }
pub fn iter(&self) -> std::slice::Iter<'_, NodePtr> { pub fn cleanup_final_edges(&mut self) {
self.0.iter() for node in &self.regular_nodes {
node.borrow_mut().final_edge = None;
}
}
pub fn iter(
&self,
) -> std::iter::Chain<
std::slice::Iter<'_, Rc<RefCell<Node>>>,
std::option::Iter<'_, Rc<RefCell<Node>>>,
> {
self.regular_nodes.iter().chain(self.final_node.iter())
} }
} }
@@ -137,9 +173,9 @@ impl Pathfinder {
} }
pub fn find_path(&mut self, from: Point, to: Point) -> Option<DiscoveredNodePtr> { pub fn find_path(&mut self, from: Point, to: Point) -> Option<DiscoveredNodePtr> {
self.nodes.cleanup_final_edges();
let mut nodes = self.nodes.clone(); let mut nodes = self.nodes.clone();
nodes.push(NodePtr::from(Node::new(from))); nodes.final_node = Some(NodePtr::from(Node::new(from)));
let nodes = nodes;
let to_node = NodePtr::from(Node::new(to)); let to_node = NodePtr::from(Node::new(to));
nodes.initialize_edges(&to_node); nodes.initialize_edges(&to_node);
let to = DiscoveredNode { let to = DiscoveredNode {
@@ -169,7 +205,7 @@ impl Pathfinder {
return Some(current_node); return Some(current_node);
} }
previous_nodes.insert(current_node.borrow().node.clone()); previous_nodes.insert(current_node.borrow().node.clone());
for edge in current_node.borrow().node.borrow().edges.as_ref().unwrap() { for edge in current_node.borrow().node.borrow().iter_edges() {
let neighbor = &edge.target; let neighbor = &edge.target;
if previous_nodes.contains(neighbor) { if previous_nodes.contains(neighbor) {
continue; continue;