From 4fb3cdc721e6fb8d70141b9c8f59809c53e7f16c Mon Sep 17 00:00:00 2001 From: Codex-ytr83r Date: Thu, 24 Sep 2026 18:53:15 -0700 Subject: [PATCH] Observe released router 715036e1 in frozen common harness --- crates/oa-core/src/routing.rs | 175 ++-------------------------------- 1 file changed, 9 insertions(+), 166 deletions(-) diff --git a/crates/oa-core/src/routing.rs b/crates/oa-core/src/routing.rs index 59b0ac0f..4868d45b 100644 --- a/crates/oa-core/src/routing.rs +++ b/crates/oa-core/src/routing.rs @@ -846,19 +846,15 @@ fn route_edge( .enumerate() { let incoming = points.iter().rev().find(|&&p| p != start).copied(); - // Only the final leg has a known continuation. Intermediate - // authored pins must not inherit the target's terminal direction. - let outgoing = (index == pins.len()).then_some(b.point); - let path = - fast_path(start, end, &space, &occupied, incoming, outgoing).or_else(|| { - if !search { - return None; - } - let (path, hit_limit) = - grid_path(start, end, &space, &occupied, incoming, outgoing, budget); - exhausted |= hit_limit; - path - }); + let path = fast_path(start, end, &space, &occupied, incoming).or_else(|| { + if !search { + return None; + } + let (path, hit_limit) = + grid_path(start, end, &space, &occupied, incoming, budget); + exhausted |= hit_limit; + path + }); let Some(path) = path else { failed = true; break; @@ -1055,7 +1051,6 @@ fn fast_path( space: &RoutingSpace<'_>, previous: &[Segment], incoming: Option, - outgoing: Option, ) -> Option> { let obstacles = space.obstacles; if obstacles @@ -1075,9 +1070,6 @@ fn fast_path( incoming .zip(path.get(1)) .map_or(0.0, |(before, &after)| turn_cost(before, start, after)) - + outgoing - .zip(path.len().checked_sub(2).and_then(|i| path.get(i))) - .map_or(0.0, |(after, &before)| turn_cost(before, end, after)) }; let estimate = |path: &[Position]| base_cost(path) + join(path); candidates.sort_by(|a, b| estimate(a).total_cmp(&estimate(b))); @@ -1149,14 +1141,12 @@ impl Ord for QueueItem { } } -#[allow(clippy::too_many_arguments)] fn grid_path( start: Position, end: Position, space: &RoutingSpace<'_>, previous: &[Segment], incoming: Option, - outgoing: Option, budget: &mut usize, ) -> (Option>, bool) { let obstacles = space.obstacles; @@ -1247,10 +1237,6 @@ fn grid_path( let cost = current.cost + manhattan(a, b) + before.map_or(0.0, |before| turn_cost(before, a, b)) - // Charge before queueing the target so competing arrival - // directions are compared by their complete terminal cost. - + outgoing.filter(|_| next == last) - .map_or(0.0, |after| turn_cost(a, b, after)) + crossing_cost(a, b, previous); if cost >= costs[state] { continue; @@ -1605,146 +1591,3 @@ impl BoundsBuilder { } } } - -#[cfg(test)] -mod terminal_join_tests { - use super::*; - - fn complete_cost( - path: &[Position], - before: Position, - after: Position, - occupied: &[Segment], - ) -> f32 { - let mut complete = vec![before]; - complete.extend_from_slice(path); - complete.push(after); - path_cost(&complete, occupied) - } - - #[test] - fn terminal_join_prefers_equal_bend_witness_without_shared_trunk() { - // Four orientations prevent an accidental horizontal/right-only fix. - for orientation in 0..4 { - let transform = |p: Position| match orientation { - 0 => p, - 1 => pos(-p.x, p.y), - 2 => pos(p.y, p.x), - _ => pos(-p.y, -p.x), - }; - let start = transform(pos(0.0, 0.0)); - let end = transform(pos(46.0, 180.0)); - let before = transform(pos(-18.0, 0.0)); - let after = transform(pos(64.0, 180.0)); - let occupied = vec![Segment { - a: start, - b: transform(pos(46.0, 0.0)), - count: 1, - }]; - let space = RoutingSpace::new(&[]); - let witness = vec![start, transform(pos(0.0, 180.0)), end]; - // Length262 + two turns48 =310. The other complete L path has - // the same bends/length but pays46*0.12=5.52 in shared-run cost. - assert!((complete_cost(&witness, before, after, &occupied) - 310.0).abs() < EPSILON); - let fast = fast_path(start, end, &space, &occupied, Some(before), Some(after)).unwrap(); - assert_eq!(fast, witness); - assert!((complete_cost(&fast, before, after, &occupied) - 310.0).abs() < EPSILON); - // Exercise grid directly; public routing's valid fast path would - // otherwise hide a target-state ordering regression in grid search. - let mut budget = VIEW_SEARCH_BUDGET; - let (grid, exhausted) = grid_path( - start, - end, - &space, - &occupied, - Some(before), - Some(after), - &mut budget, - ); - assert!(!exhausted); - let grid = grid.unwrap(); - assert_eq!(grid, witness); - assert!((complete_cost(&grid, before, after, &occupied) - 310.0).abs() < EPSILON); - } - } - - #[test] - fn unspecified_continuation_keeps_intermediate_leg_choice() { - let start = pos(0.0, 0.0); - let pin = pos(46.0, 180.0); - let before = pos(-18.0, 0.0); - let occupied = vec![Segment { - a: start, - b: pos(46.0, 0.0), - count: 1, - }]; - let space = RoutingSpace::new(&[]); - let witness = vec![start, pos(46.0, 0.0), pin]; - let fast = fast_path(start, pin, &space, &occupied, Some(before), None).unwrap(); - assert_eq!(fast, witness); - // An intermediate authored pin has no known outgoing continuation: - // length226 + one turn24 + shared5.52 =255.52 for this leg. - assert!((path_cost(&fast, &occupied) - 255.52).abs() < EPSILON); - let mut budget = VIEW_SEARCH_BUDGET; - let (grid, exhausted) = grid_path( - start, - pin, - &space, - &occupied, - Some(before), - None, - &mut budget, - ); - assert!(!exhausted); - assert_eq!(grid.unwrap(), witness); - } - - #[test] - fn straight_and_degenerate_terminal_legs_remain_exact() { - let space = RoutingSpace::new(&[]); - let start = pos(0.0, 0.0); - let end = pos(46.0, 0.0); - for after in [pos(64.0, 0.0), pos(28.0, 0.0)] { - let before = pos(-18.0, 0.0); - let fast = fast_path(start, end, &space, &[], Some(before), Some(after)).unwrap(); - let expected = if after.x > end.x { 82.0 } else { 130.0 }; - assert!((complete_cost(&fast, before, after, &[]) - expected).abs() < EPSILON); - let mut budget = VIEW_SEARCH_BUDGET; - let (grid, exhausted) = grid_path( - start, - end, - &space, - &[], - Some(before), - Some(after), - &mut budget, - ); - assert!(!exhausted); - assert_eq!(grid.unwrap(), fast); - } - assert_eq!( - fast_path( - start, - start, - &space, - &[], - Some(pos(-18.0, 0.0)), - Some(pos(18.0, 0.0)) - ) - .unwrap(), - vec![start] - ); - let mut budget = VIEW_SEARCH_BUDGET; - let (grid, exhausted) = grid_path( - start, - start, - &space, - &[], - Some(pos(-18.0, 0.0)), - Some(pos(18.0, 0.0)), - &mut budget, - ); - assert!(!exhausted); - assert_eq!(grid.unwrap(), vec![start]); - } -}