use bumpalo::collections::Vec as BumpVec;
use bumpalo::Bump;
use std::time::Instant;
pub fn track_edges(edge_map: &mut [u8], width: usize, height: usize, arena: &Bump) {
let t_start = Instant::now();
let total = width * height;
debug_assert_eq!(edge_map.len(), total, "edge_map size mismatch");
log::info!(
"[track_edges] START {}x{} total={}",
width, height, total
);
{
let last = (height - 1) * width;
edge_map[..width].fill(0);
edge_map[last..last + width].fill(0);
for y in 0..height {
edge_map[y * width] = 0;
edge_map[y * width + width - 1] = 0;
}
}
#[cfg(debug_assertions)]
{
let bad = edge_map[..width].iter().any(|&v| v != 0)
|| edge_map[(height-1)*width..].iter().any(|&v| v != 0)
|| (0..height).any(|y| edge_map[y*width] != 0 || edge_map[y*width+width-1] != 0);
if bad {
log::error!("[track_edges] BUG: boundary clear failed");
}
}
let w = width as isize;
let neighbors: [isize; 8] = [
-w-1, -w, -w+1,
-1, 1,
w-1, w, w+1,
];
let stack_cap = total / 4;
let mut stack = BumpVec::with_capacity_in(stack_cap, arena);
let t_scan = Instant::now();
for (i, &v) in edge_map.iter().enumerate() {
if v == 255 {
stack.push(i as isize);
}
}
let seed_count = stack.len();
log::debug!(
"[track_edges] seeds={} ({:.1}%), scan={:?}",
seed_count,
seed_count as f64 / total as f64 * 100.0,
t_scan.elapsed()
);
if seed_count == 0 {
log::warn!("[track_edges] NO strong edges — check thresholds");
}
let t_bfs = Instant::now();
let mut promoted = 0usize;
while let Some(idx) = stack.pop() {
for &offset in &neighbors {
let n_idx = (idx + offset) as usize;
if let Some(v) = edge_map.get_mut(n_idx) {
if *v == 127 {
*v = 255;
stack.push(n_idx as isize);
promoted += 1;
}
}
}
}
log::debug!(
"[track_edges] BFS promoted={}, elapsed={:?}",
promoted, t_bfs.elapsed()
);
let t_cleanup = Instant::now();
let mut orphans = 0usize;
for v in edge_map.iter_mut() {
if *v == 127 {
*v = 0;
orphans += 1;
}
}
log::debug!(
"[track_edges] orphans={} ({:.1}%), cleanup={:?}",
orphans,
orphans as f64 / total as f64 * 100.0,
t_cleanup.elapsed()
);
#[cfg(debug_assertions)]
{
let final_strong = edge_map.iter().filter(|&&v| v == 255).count();
let ratio = final_strong as f64 / total as f64 * 100.0;
if ratio > 20.0 {
log::warn!("[track_edges] HIGH density {:.1}% — consider raising high_thresh", ratio);
}
}
log::info!(
"[track_edges] END seeds={} promoted={} orphans={} {:.3}ms",
seed_count, promoted, orphans,
t_start.elapsed().as_secs_f64() * 1000.0
);
}