redid it library style

This commit is contained in:
2026-03-16 22:27:33 +01:00
parent 1192350b3c
commit cedd29e96e
10 changed files with 840 additions and 129 deletions

101
src/normalize.rs Normal file
View File

@@ -0,0 +1,101 @@
/// Normalizes a gesture by removing translation and scale
///
/// # Arguments
/// * `points` - Slice of Point structs representing the gesture
///
/// # Returns
/// Vector of normalized points centered at origin with unit scale
///
/// # Example
/// ```
/// use redoal::point::Point;
/// use redoal::normalize;
///
/// let points = vec![
/// Point::new(1.0, 2.0),
/// Point::new(3.0, 4.0),
/// Point::new(5.0, 6.0),
/// ];
/// let normalized = normalize(&points);
/// ```
use crate::Point;
pub fn normalize(points: &[Point]) -> Vec<Point> {
let n = points.len() as f64;
// Calculate centroid
let cx = points.iter().map(|p| p.x).sum::<f64>() / n;
let cy = points.iter().map(|p| p.y).sum::<f64>() / n;
// Center points at origin
let mut out: Vec<Point> = points.iter().map(|p| {
Point {
x: p.x - cx,
y: p.y - cy,
}
}).collect();
// Find maximum radius
let mut max_r = 0.0;
for p in &out {
let r = (p.x * p.x + p.y * p.y).sqrt();
if r > max_r {
max_r = r;
}
}
// Scale to unit size
if max_r > 0.0 {
for p in &mut out {
p.x /= max_r;
p.y /= max_r;
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
use crate::point::Point;
#[test]
fn test_normalize_centers_points() {
let points = vec![
Point::new(1.0, 1.0),
Point::new(2.0, 2.0),
Point::new(3.0, 3.0),
];
let normalized = normalize(&points);
let sum_x: f64 = normalized.iter().map(|p| p.x).sum();
let sum_y: f64 = normalized.iter().map(|p| p.y).sum();
// Centroid should be at origin
assert!( (sum_x.abs() < 1e-10) );
assert!( (sum_y.abs() < 1e-10) );
}
#[test]
fn test_normalize_scales_points() {
let points = vec![
Point::new(0.0, 0.0),
Point::new(10.0, 0.0),
Point::new(5.0, 5.0),
];
let normalized = normalize(&points);
let max_r = normalized.iter().map(|p| (p.x * p.x + p.y * p.y).sqrt()).fold(0.0, |a: f64, b| a.max(b));
// All points should be within unit circle
assert!( (max_r - 1.0).abs() < 1e-10 );
}
#[test]
fn test_normalize_empty() {
let points: Vec<Point> = vec![];
let normalized = normalize(&points);
assert_eq!(normalized.len(), 0);
}
}