Skip to content

Commit

Permalink
Use breadth-first graph traversals to improve numerical stability
Browse files Browse the repository at this point in the history
  • Loading branch information
patowen committed Apr 14, 2024
1 parent 20a6875 commit 673c310
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions common/src/traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ use crate::{

/// Ensure all nodes within `distance` of `start` exist
pub fn ensure_nearby(graph: &mut Graph, start: &Position, distance: f64) {
let mut pending = Vec::<(NodeId, na::Matrix4<f64>)>::new();
// We do a breadth-first instead of a depth-first traversal here to prevent too much error
// from accumulating due to repeated transformations being applied.
let mut pending = VecDeque::<(NodeId, na::Matrix4<f64>)>::new();
let mut visited = FxHashSet::<NodeId>::default();

pending.push((start.node, na::Matrix4::identity()));
pending.push_back((start.node, na::Matrix4::identity()));
visited.insert(start.node);
let start_p = start.local.map(|x| x as f64) * math::origin();

while let Some((node, current_transform)) = pending.pop() {
while let Some((node, current_transform)) = pending.pop_front() {
for side in Side::iter() {
let neighbor = graph.ensure_neighbor(node, side);
if visited.contains(&neighbor) {
Expand All @@ -32,7 +34,7 @@ pub fn ensure_nearby(graph: &mut Graph, start: &Position, distance: f64) {
if math::distance(&start_p, &neighbor_p) > distance {
continue;
}
pending.push((neighbor, neighbor_transform));
pending.push_back((neighbor, neighbor_transform));
}
}
}
Expand All @@ -50,17 +52,20 @@ pub fn nearby_nodes(
}

let mut result = Vec::new();
let mut pending = Vec::<PendingNode>::new();

// We do a breadth-first instead of a depth-first traversal here to prevent too much error
// from accumulating due to repeated transformations being applied.
let mut pending = VecDeque::<PendingNode>::new();
let mut visited = FxHashSet::<NodeId>::default();
let start_p = start.local.map(|x| x as f64) * math::origin();

pending.push(PendingNode {
pending.push_back(PendingNode {
id: start.node,
transform: na::Matrix4::identity(),
});
visited.insert(start.node);

while let Some(current) = pending.pop() {
while let Some(current) = pending.pop_front() {
let current_p = current.transform * math::origin();
if math::distance(&start_p, &current_p) > distance {
continue;
Expand All @@ -75,7 +80,7 @@ pub fn nearby_nodes(
if visited.contains(&neighbor) {
continue;
}
pending.push(PendingNode {
pending.push_back(PendingNode {
id: neighbor,
transform: current.transform * side.reflection(),
});
Expand Down

0 comments on commit 673c310

Please sign in to comment.