use std::path::Path;
use nalgebra::{Quaternion, UnitQuaternion, Vector3};
use rigidity_core::PointCloud;
use crate::IoError;
pub fn read_e57(path: &Path) -> Result<PointCloud, IoError> {
let mut file = e57::E57Reader::from_file(path).map_err(|e| IoError::E57(e.to_string()))?;
let clouds = file.pointclouds();
let mut points: Vec<Vector3<f64>> = Vec::new();
for cloud in &clouds {
let (rotation, translation) = cloud.transform.as_ref().map_or_else(
|| (UnitQuaternion::identity(), Vector3::zeros()),
|transform| {
let quaternion = Quaternion::new(
transform.rotation.w,
transform.rotation.x,
transform.rotation.y,
transform.rotation.z,
);
(
UnitQuaternion::from_quaternion(quaternion),
Vector3::new(
transform.translation.x,
transform.translation.y,
transform.translation.z,
),
)
},
);
let reader = file
.pointcloud_simple(cloud)
.map_err(|e| IoError::E57(e.to_string()))?;
for point in reader {
let point = point.map_err(|e| IoError::E57(e.to_string()))?;
if let e57::CartesianCoordinate::Valid { x, y, z } = point.cartesian {
points.push(rotation * Vector3::new(x, y, z) + translation);
}
}
}
if points.is_empty() {
return Ok(PointCloud::new());
}
let mut min = Vector3::repeat(f64::INFINITY);
let mut max = Vector3::repeat(f64::NEG_INFINITY);
for point in &points {
min = min.inf(point);
max = max.sup(point);
}
let mut cloud = PointCloud::with_origin((min + max) * 0.5);
for point in points {
cloud.push(point);
}
Ok(cloud)
}
pub fn write_e57(cloud: &PointCloud, path: &Path) -> Result<(), IoError> {
let mut file =
e57::E57Writer::from_file(path, "rigidity").map_err(|e| IoError::E57(e.to_string()))?;
let prototype = vec![
e57::Record::CARTESIAN_X_F64,
e57::Record::CARTESIAN_Y_F64,
e57::Record::CARTESIAN_Z_F64,
];
let mut writer = file
.add_pointcloud("rigidity-scan", prototype)
.map_err(|e| IoError::E57(e.to_string()))?;
for index in 0..cloud.len() {
let point = cloud.point(index);
writer
.add_point(vec![
e57::RecordValue::Double(point.x),
e57::RecordValue::Double(point.y),
e57::RecordValue::Double(point.z),
])
.map_err(|e| IoError::E57(e.to_string()))?;
}
writer.finalize().map_err(|e| IoError::E57(e.to_string()))?;
file.finalize().map_err(|e| IoError::E57(e.to_string()))?;
Ok(())
}