use nalgebra::Point2;
use projective_grid::square::detect::SquareGridParams;
use projective_grid::square::extension::{ExtensionParams, LocalExtensionParams};
use projective_grid::{ExtensionStrategy, RegularGridDetector, RegularGridParams};
fn clean_grid(cols: i32, rows: i32, pitch: f32, ox: f32, oy: f32) -> Vec<Point2<f32>> {
let mut points = Vec::new();
for j in 0..rows {
for i in 0..cols {
points.push(Point2::new(i as f32 * pitch + ox, j as f32 * pitch + oy));
}
}
points
}
fn report(label: &str, detector: &RegularGridDetector, points: &[Point2<f32>]) {
match detector.detect(points) {
Ok(g) => {
let s = &g.stats;
println!(
"{label:<34} labelled={:<3} before_prune={:<3} pruned={:<2} \
dropped_validation={:<2} canonicalized={}",
g.points.len(),
s.labelled_before_prune,
s.pruned_disconnected,
s.dropped_by_validation,
s.canonicalized,
);
}
Err(e) => println!("{label:<34} ERROR: {e}"),
}
}
fn main() {
let pitch = 32.0;
let mut noisy = clean_grid(6, 5, pitch, 60.0, 60.0);
noisy.push(Point2::new(7.0, 9.0)); noisy.push(Point2::new(900.0, 12.0)); noisy.push(Point2::new(15.0, 800.0)); println!("== connectivity pruning ({} input points) ==", noisy.len());
for &prune in &[true, false] {
let det =
RegularGridDetector::new(RegularGridParams::default().with_prune_disconnected(prune));
report(&format!("prune_disconnected = {prune}"), &det, &noisy);
let g = det.detect(&noisy).expect("clean core grid detects");
let stray: Vec<usize> = g
.points
.iter()
.map(|p| p.source_index)
.filter(|&idx| idx >= 30)
.collect();
println!(" spurious input indices in output: {stray:?} (expect [])");
}
println!("\n== top-left canonicalisation ==");
let mut flipped = Vec::new();
for j in 0..5 {
for i in 0..6 {
flipped.push(Point2::new(
300.0 - i as f32 * pitch,
220.0 - j as f32 * pitch,
));
}
}
for &canon in &[true, false] {
let det = RegularGridDetector::new(
RegularGridParams::default().with_canonicalize_top_left(canon),
);
let g = det.detect(&flipped).expect("flipped grid detects");
let origin = g
.points
.iter()
.find(|p| p.grid == (0, 0))
.map(|p| p.position)
.unwrap();
println!(
"canonicalize_top_left = {canon:<5} -> (0,0) at ({:5.1}, {:5.1}) \
axis_i=({:+.2}, {:+.2}) axis_j=({:+.2}, {:+.2})",
origin.x, origin.y, g.axis_i.x, g.axis_i.y, g.axis_j.x, g.axis_j.y,
);
}
println!(" (canonicalized: (0,0) sits top-left and axis_i/axis_j point right/down)");
println!("\n== extension strategy ==");
let clean = clean_grid(6, 5, pitch, 60.0, 60.0);
let strategies = [
("Disabled", ExtensionStrategy::Disabled),
(
"Global(default)",
ExtensionStrategy::Global(ExtensionParams::default()),
),
(
"Local(default)",
ExtensionStrategy::Local(LocalExtensionParams::default()),
),
];
for (name, strategy) in strategies {
let params = RegularGridParams::new(SquareGridParams::default()).with_extension(strategy);
let det = RegularGridDetector::new(params);
report(&format!("extension = {name}"), &det, &clean);
}
}