From 18123a6511c5cdfd884b7417747f54b2bd54c290 Mon Sep 17 00:00:00 2001 From: Chris Price Date: Tue, 17 May 2022 21:14:50 +0100 Subject: [PATCH 1/2] Refactor to use thiserror --- Cargo.lock | 2 +- crates/fj-export/Cargo.toml | 2 +- crates/fj-export/src/lib.rs | 51 +++++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9e38d25b..58320c68d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -733,10 +733,10 @@ dependencies = [ name = "fj-export" version = "0.6.0" dependencies = [ - "anyhow", "fj-interop", "fj-math", "stl", + "thiserror", "threemf", ] diff --git a/crates/fj-export/Cargo.toml b/crates/fj-export/Cargo.toml index dd85e88c9..66202bfe4 100644 --- a/crates/fj-export/Cargo.toml +++ b/crates/fj-export/Cargo.toml @@ -13,7 +13,7 @@ categories = ["encoding", "mathematics", "rendering"] [dependencies] -anyhow = "1.0.57" +thiserror = "1.0.31" threemf = "0.3.0" stl = "0.2.1" diff --git a/crates/fj-export/src/lib.rs b/crates/fj-export/src/lib.rs index 130fb0a2a..642fee7ab 100644 --- a/crates/fj-export/src/lib.rs +++ b/crates/fj-export/src/lib.rs @@ -16,7 +16,7 @@ use std::{fs::File, path::Path}; -use anyhow::{anyhow, Result}; +use thiserror::Error; use fj_interop::mesh::Mesh; use fj_math::{Point, Triangle, Vector}; @@ -27,7 +27,7 @@ use fj_math::{Point, Triangle, Vector}; /// /// Currently 3MF & STL file types are supported. The case insensitive file extension of /// the provided path is used to switch between supported types. -pub fn export(mesh: &Mesh>, path: &Path) -> Result<()> { +pub fn export(mesh: &Mesh>, path: &Path) -> Result<(), Error> { match path.extension() { Some(extension) if extension.to_ascii_uppercase() == "3MF" => { export_3mf(mesh, path) @@ -35,14 +35,14 @@ pub fn export(mesh: &Mesh>, path: &Path) -> Result<()> { Some(extension) if extension.to_ascii_uppercase() == "STL" => { export_stl(mesh, path) } - Some(extension) => { - Err(anyhow!("Extension not recognised, got {:?}", extension)) - } - None => Err(anyhow!("No extension specified")), + Some(extension) => Err(Error::InvalidExtension( + extension.to_str().map(|s| s.to_string()), + )), + None => Err(Error::NoExtension), } } -fn export_3mf(mesh: &Mesh>, path: &Path) -> Result<()> { +fn export_3mf(mesh: &Mesh>, path: &Path) -> Result<(), Error> { let vertices = mesh.vertices().map(|vertex| vertex.into()).collect(); let indices: Vec<_> = mesh.indices().collect(); @@ -67,7 +67,7 @@ fn export_3mf(mesh: &Mesh>, path: &Path) -> Result<()> { Ok(()) } -fn export_stl(mesh: &Mesh>, path: &Path) -> Result<()> { +fn export_stl(mesh: &Mesh>, path: &Path) -> Result<(), Error> { let points = mesh .triangles() .map(|triangle| triangle.points) @@ -84,7 +84,7 @@ fn export_stl(mesh: &Mesh>, path: &Path) -> Result<()> { .map(|&points| points.into()) .map(|triangle: Triangle<3>| triangle.to_parry().normal()) .collect::>>() - .ok_or_else(|| anyhow!("Unable to compute normal"))?; + .ok_or(ExportError::InvalidTriangle)?; let normals = normals.iter().map(|vector| vector.into_inner().into()).map( |vector: Vector<3>| { @@ -112,7 +112,10 @@ fn export_stl(mesh: &Mesh>, path: &Path) -> Result<()> { let binary_stl_file = stl::BinaryStlFile { header: stl::BinaryStlHeader { header: [0u8; 80], - num_triangles: triangles.len().try_into()?, + num_triangles: triangles + .len() + .try_into() + .map_err(|_| Error::InvalidTriangleCount)?, }, triangles, }; @@ -121,3 +124,31 @@ fn export_stl(mesh: &Mesh>, path: &Path) -> Result<()> { Ok(()) } + +/// An error that can occur while exporting +#[derive(Debug, Error)] +pub enum Error { + /// No extension specified + #[error("no extension specified")] + NoExtension, + + /// Unrecognised extension found `{0:?}` + #[error("unrecognised extension found `{0:?}`")] + InvalidExtension(Option), + + /// Invalid triangle found when trying to compute normal + #[error("invalid triangle found when trying to compute normal")] + InvalidTriangle, + + /// I/O error whilst exporting to file + #[error("I/O error whilst exporting to file")] + Io(#[from] std::io::Error), + + /// Maximum triangle count exceeded + #[error("maximum triangle count exceeded")] + InvalidTriangleCount, + + /// Threemf error whilst exporting to 3MF file + #[error("threemf error whilst exporting to 3MF file")] + ThreeMF(#[from] threemf::Error), +} From c1ed3f019bcfaf9741be60b739f1cc663ebd12eb Mon Sep 17 00:00:00 2001 From: Chris Price Date: Tue, 17 May 2022 21:21:45 +0100 Subject: [PATCH 2/2] Make use of `Triangle::normal` --- crates/fj-export/src/lib.rs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/crates/fj-export/src/lib.rs b/crates/fj-export/src/lib.rs index 642fee7ab..599d84089 100644 --- a/crates/fj-export/src/lib.rs +++ b/crates/fj-export/src/lib.rs @@ -19,7 +19,7 @@ use std::{fs::File, path::Path}; use thiserror::Error; use fj_interop::mesh::Mesh; -use fj_math::{Point, Triangle, Vector}; +use fj_math::{Point, Triangle}; /// Export the provided mesh to the file at the given path. /// @@ -74,27 +74,14 @@ fn export_stl(mesh: &Mesh>, path: &Path) -> Result<(), Error> { .collect::>(); let vertices = points.iter().map(|points| { - points.map(|point| { - [point.x.into_f32(), point.y.into_f32(), point.z.into_f32()] - }) + points.map(|point| point.coords.components.map(|s| s.into_f32())) }); let normals = points .iter() .map(|&points| points.into()) - .map(|triangle: Triangle<3>| triangle.to_parry().normal()) - .collect::>>() - .ok_or(ExportError::InvalidTriangle)?; - - let normals = normals.iter().map(|vector| vector.into_inner().into()).map( - |vector: Vector<3>| { - [ - vector.x.into_f32(), - vector.y.into_f32(), - vector.z.into_f32(), - ] - }, - ); + .map(|triangle: Triangle<3>| triangle.normal()) + .map(|vector| vector.components.map(|s| s.into_f32())); let triangles = vertices .zip(normals) @@ -136,10 +123,6 @@ pub enum Error { #[error("unrecognised extension found `{0:?}`")] InvalidExtension(Option), - /// Invalid triangle found when trying to compute normal - #[error("invalid triangle found when trying to compute normal")] - InvalidTriangle, - /// I/O error whilst exporting to file #[error("I/O error whilst exporting to file")] Io(#[from] std::io::Error),