use crate::core::{Point, PointCloud};
use crate::error::{CloudError, Result};
pub type Transform = [[f32; 4]; 4];
pub const IDENTITY_TRANSFORM: Transform = [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
];
pub fn icp_registration<P: Point>(
_source: &PointCloud<P>,
_target: &PointCloud<P>,
_max_iterations: usize,
_tolerance: f32,
) -> Result<Transform> {
Ok(IDENTITY_TRANSFORM)
}
pub fn transform_point_cloud<P: Point>(
cloud: PointCloud<P>,
transform: &Transform,
) -> PointCloud<P> {
cloud.map(|point| {
let pos = point.position();
let transformed_pos = apply_transform(pos, transform);
point
})
}
fn apply_transform(point: [f32; 3], transform: &Transform) -> [f32; 3] {
let x = transform[0][0] * point[0]
+ transform[0][1] * point[1]
+ transform[0][2] * point[2]
+ transform[0][3];
let y = transform[1][0] * point[0]
+ transform[1][1] * point[1]
+ transform[1][2] * point[2]
+ transform[1][3];
let z = transform[2][0] * point[0]
+ transform[2][1] * point[1]
+ transform[2][2] * point[2]
+ transform[2][3];
[x, y, z]
}
pub trait RegistrationExt<P: Point> {
fn icp_register(
&self,
target: &PointCloud<P>,
max_iterations: usize,
tolerance: f32,
) -> Result<Transform>;
fn transform(self, transform: &Transform) -> PointCloud<P>;
}
impl<P: Point> RegistrationExt<P> for PointCloud<P> {
fn icp_register(
&self,
target: &PointCloud<P>,
max_iterations: usize,
tolerance: f32,
) -> Result<Transform> {
icp_registration(self, target, max_iterations, tolerance)
}
fn transform(self, transform: &Transform) -> PointCloud<P> {
transform_point_cloud(self, transform)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::PointXYZ;
#[test]
fn test_identity_transform() {
let points = vec![PointXYZ::new(1.0, 2.0, 3.0)];
let cloud = PointCloud::from_points(points);
let transformed = cloud.transform(&IDENTITY_TRANSFORM);
assert_eq!(transformed.len(), 1);
}
#[test]
fn test_icp_placeholder() {
let source_points = vec![PointXYZ::new(0.0, 0.0, 0.0)];
let target_points = vec![PointXYZ::new(1.0, 0.0, 0.0)];
let source = PointCloud::from_points(source_points);
let target = PointCloud::from_points(target_points);
let transform = source.icp_register(&target, 10, 1e-6).unwrap();
assert_eq!(transform, IDENTITY_TRANSFORM);
}
}