From d36142e4f79e79d2fd1a08855ac9f3d2903f70a6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 24 May 2022 16:19:21 +0200 Subject: [PATCH 1/3] Return `Result` from `ToShape::to_shape` --- crates/fj-operations/src/circle.rs | 10 +++++++--- crates/fj-operations/src/difference_2d.rs | 9 +++++---- crates/fj-operations/src/group.rs | 13 ++++++++----- crates/fj-operations/src/lib.rs | 9 ++++++--- crates/fj-operations/src/shape_processor.rs | 2 +- crates/fj-operations/src/sketch.rs | 13 ++++++++++--- crates/fj-operations/src/sweep.rs | 7 +++---- crates/fj-operations/src/transform.rs | 8 ++++---- 8 files changed, 44 insertions(+), 27 deletions(-) diff --git a/crates/fj-operations/src/circle.rs b/crates/fj-operations/src/circle.rs index f3ab8b386..ac643c5af 100644 --- a/crates/fj-operations/src/circle.rs +++ b/crates/fj-operations/src/circle.rs @@ -2,7 +2,7 @@ use fj_interop::debug::DebugInfo; use fj_kernel::{ algorithms::Tolerance, geometry::Surface, - shape::Shape, + shape::{Shape, ValidationError}, topology::{Cycle, Edge, Face}, }; use fj_math::{Aabb, Point, Scalar}; @@ -10,7 +10,11 @@ use fj_math::{Aabb, Point, Scalar}; use super::ToShape; impl ToShape for fj::Circle { - fn to_shape(&self, _: Tolerance, _: &mut DebugInfo) -> Shape { + fn to_shape( + &self, + _: Tolerance, + _: &mut DebugInfo, + ) -> Result { let mut shape = Shape::new(); // Circles have just a single round edge with no vertices. So none need @@ -27,7 +31,7 @@ impl ToShape for fj::Circle { .insert(Face::new(surface, cycles, Vec::new(), self.color())) .unwrap(); - shape + Ok(shape) } fn bounding_volume(&self) -> Aabb<3> { diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index b2d91b8ba..5d64cd111 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -1,7 +1,7 @@ use fj_interop::debug::DebugInfo; use fj_kernel::{ algorithms::Tolerance, - shape::{Handle, Shape}, + shape::{Handle, Shape, ValidationError}, topology::{Cycle, Edge, Face}, }; use fj_math::Aabb; @@ -13,7 +13,7 @@ impl ToShape for fj::Difference2d { &self, tolerance: Tolerance, debug_info: &mut DebugInfo, - ) -> Shape { + ) -> Result { // This method assumes that `b` is fully contained within `a`: // https://github.com/hannobraun/Fornjot/issues/92 @@ -25,7 +25,8 @@ impl ToShape for fj::Difference2d { // Can be cleaned up, once `each_ref` is stable: // https://doc.rust-lang.org/std/primitive.array.html#method.each_ref let [a, b] = self.shapes(); - let [a, b] = [a, b].map(|shape| shape.to_shape(tolerance, debug_info)); + let [a, b] = + [a, b].map(|shape| shape.to_shape(tolerance, debug_info).unwrap()); if let Some(face) = a.faces().next() { // If there's at least one face to subtract from, we can proceed. @@ -74,7 +75,7 @@ impl ToShape for fj::Difference2d { .unwrap(); } - difference + Ok(difference) } fn bounding_volume(&self) -> Aabb<3> { diff --git a/crates/fj-operations/src/group.rs b/crates/fj-operations/src/group.rs index a79bd0b31..30f0aac23 100644 --- a/crates/fj-operations/src/group.rs +++ b/crates/fj-operations/src/group.rs @@ -1,5 +1,8 @@ use fj_interop::debug::DebugInfo; -use fj_kernel::{algorithms::Tolerance, shape::Shape}; +use fj_kernel::{ + algorithms::Tolerance, + shape::{Shape, ValidationError}, +}; use fj_math::Aabb; use super::ToShape; @@ -9,16 +12,16 @@ impl ToShape for fj::Group { &self, tolerance: Tolerance, debug_info: &mut DebugInfo, - ) -> Shape { + ) -> Result { let mut shape = Shape::new(); - let a = self.a.to_shape(tolerance, debug_info); - let b = self.b.to_shape(tolerance, debug_info); + let a = self.a.to_shape(tolerance, debug_info)?; + let b = self.b.to_shape(tolerance, debug_info)?; copy_shape(a, &mut shape); copy_shape(b, &mut shape); - shape + Ok(shape) } fn bounding_volume(&self) -> Aabb<3> { diff --git a/crates/fj-operations/src/lib.rs b/crates/fj-operations/src/lib.rs index 5bd5dd22e..71a445b8b 100644 --- a/crates/fj-operations/src/lib.rs +++ b/crates/fj-operations/src/lib.rs @@ -26,7 +26,10 @@ mod sweep; mod transform; use fj_interop::debug::DebugInfo; -use fj_kernel::{algorithms::Tolerance, shape::Shape}; +use fj_kernel::{ + algorithms::Tolerance, + shape::{Shape, ValidationError}, +}; use fj_math::Aabb; /// Implemented for all operations from the [`fj`] crate @@ -36,7 +39,7 @@ pub trait ToShape { &self, tolerance: Tolerance, debug_info: &mut DebugInfo, - ) -> Shape; + ) -> Result; /// Access the axis-aligned bounding box of a shape /// @@ -88,6 +91,6 @@ dispatch! { to_shape( tolerance: Tolerance, debug_info: &mut DebugInfo, - ) -> Shape; + ) -> Result; bounding_volume() -> Aabb<3>; } diff --git a/crates/fj-operations/src/shape_processor.rs b/crates/fj-operations/src/shape_processor.rs index c9041cdae..23fe08042 100644 --- a/crates/fj-operations/src/shape_processor.rs +++ b/crates/fj-operations/src/shape_processor.rs @@ -37,7 +37,7 @@ impl ShapeProcessor { let mut debug_info = DebugInfo::new(); let mesh = triangulate( - shape.to_shape(tolerance, &mut debug_info), + shape.to_shape(tolerance, &mut debug_info).unwrap(), tolerance, &mut debug_info, ); diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 60e2ef595..43cdc85b1 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -1,13 +1,20 @@ use fj_interop::debug::DebugInfo; use fj_kernel::{ - algorithms::Tolerance, geometry::Surface, shape::Shape, topology::Face, + algorithms::Tolerance, + geometry::Surface, + shape::{Shape, ValidationError}, + topology::Face, }; use fj_math::{Aabb, Point}; use super::ToShape; impl ToShape for fj::Sketch { - fn to_shape(&self, _: Tolerance, _: &mut DebugInfo) -> Shape { + fn to_shape( + &self, + _: Tolerance, + _: &mut DebugInfo, + ) -> Result { let mut shape = Shape::new(); let surface = Surface::xy_plane(); @@ -22,7 +29,7 @@ impl ToShape for fj::Sketch { .build() .unwrap(); - shape + Ok(shape) } fn bounding_volume(&self) -> Aabb<3> { diff --git a/crates/fj-operations/src/sweep.rs b/crates/fj-operations/src/sweep.rs index af66ea4f6..ca5f05df6 100644 --- a/crates/fj-operations/src/sweep.rs +++ b/crates/fj-operations/src/sweep.rs @@ -1,7 +1,7 @@ use fj_interop::debug::DebugInfo; use fj_kernel::{ algorithms::{sweep_shape, Tolerance}, - shape::Shape, + shape::{Shape, ValidationError}, }; use fj_math::{Aabb, Vector}; @@ -12,14 +12,13 @@ impl ToShape for fj::Sweep { &self, tolerance: Tolerance, debug_info: &mut DebugInfo, - ) -> Shape { + ) -> Result { sweep_shape( - self.shape().to_shape(tolerance, debug_info), + self.shape().to_shape(tolerance, debug_info)?, Vector::from(self.path()), tolerance, self.shape().color(), ) - .unwrap() } fn bounding_volume(&self) -> Aabb<3> { diff --git a/crates/fj-operations/src/transform.rs b/crates/fj-operations/src/transform.rs index 454a0e1eb..cce5478d4 100644 --- a/crates/fj-operations/src/transform.rs +++ b/crates/fj-operations/src/transform.rs @@ -1,7 +1,7 @@ use fj_interop::debug::DebugInfo; use fj_kernel::{ algorithms::{transform_shape, Tolerance}, - shape::Shape, + shape::{Shape, ValidationError}, }; use fj_math::{Aabb, Transform, Vector}; @@ -12,13 +12,13 @@ impl ToShape for fj::Transform { &self, tolerance: Tolerance, debug_info: &mut DebugInfo, - ) -> Shape { - let mut shape = self.shape.to_shape(tolerance, debug_info); + ) -> Result { + let mut shape = self.shape.to_shape(tolerance, debug_info)?; let transform = transform(self); transform_shape(&mut shape, &transform); - shape + Ok(shape) } fn bounding_volume(&self) -> Aabb<3> { From b959744191bcb062aac6291b76fe3a2ab73eb562 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 24 May 2022 16:20:28 +0200 Subject: [PATCH 2/3] Improve error handling in sweep operation --- crates/fj-operations/src/difference_2d.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index 5d64cd111..d10823a8d 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -1,7 +1,7 @@ use fj_interop::debug::DebugInfo; use fj_kernel::{ algorithms::Tolerance, - shape::{Handle, Shape, ValidationError}, + shape::{Handle, Shape, ValidationError, ValidationResult}, topology::{Cycle, Edge, Face}, }; use fj_math::Aabb; @@ -45,11 +45,12 @@ impl ToShape for fj::Difference2d { for cycle in face.exteriors.as_handle() { let cycle = - add_cycle(cycle.clone(), &mut difference, false); + add_cycle(cycle.clone(), &mut difference, false)?; exteriors.push(cycle); } for cycle in face.interiors.as_handle() { - let cycle = add_cycle(cycle.clone(), &mut difference, true); + let cycle = + add_cycle(cycle.clone(), &mut difference, true)?; interiors.push(cycle); } } @@ -65,7 +66,8 @@ impl ToShape for fj::Difference2d { ); for cycle in face.exteriors.as_handle() { - let cycle = add_cycle(cycle.clone(), &mut difference, true); + let cycle = + add_cycle(cycle.clone(), &mut difference, true)?; interiors.push(cycle); } } @@ -90,12 +92,12 @@ fn add_cycle( cycle: Handle>, shape: &mut Shape, reverse: bool, -) -> Handle> { +) -> ValidationResult> { let mut edges = Vec::new(); for edge in cycle.get().edges() { let curve = edge.curve(); let curve = if reverse { curve.reverse() } else { curve }; - let curve = shape.insert(curve).unwrap(); + let curve = shape.insert(curve)?; let vertices = edge.vertices.clone().map(|vs| { let mut vs = vs.map(|vertex| vertex.canonical()); @@ -107,7 +109,7 @@ fn add_cycle( vs }); - let edge = shape.merge(Edge::new(curve, vertices)).unwrap(); + let edge = shape.merge(Edge::new(curve, vertices))?; edges.push(edge); } @@ -115,5 +117,7 @@ fn add_cycle( edges.reverse(); } - shape.insert(Cycle::new(edges)).unwrap() + let cycle = shape.insert(Cycle::new(edges))?; + + Ok(cycle) } From 0fd7c4e45cd698479e7c85a0d01b56e4550367b2 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 24 May 2022 16:23:38 +0200 Subject: [PATCH 3/3] Return `Result` from `ShapeProcessor::process` --- crates/fj-app/src/main.rs | 2 +- crates/fj-operations/src/shape_processor.rs | 16 +++++++++++----- crates/fj-viewer/src/run.rs | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index c7896d3a9..0788d887b 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -63,7 +63,7 @@ fn main() -> anyhow::Result<()> { if let Some(path) = args.export { let shape = model.load_once(¶meters)?; - let shape = shape_processor.process(&shape); + let shape = shape_processor.process(&shape)?; export(&shape.mesh, &path)?; diff --git a/crates/fj-operations/src/shape_processor.rs b/crates/fj-operations/src/shape_processor.rs index 23fe08042..bb4855fe2 100644 --- a/crates/fj-operations/src/shape_processor.rs +++ b/crates/fj-operations/src/shape_processor.rs @@ -1,7 +1,10 @@ //! API for processing shapes use fj_interop::{debug::DebugInfo, mesh::Mesh}; -use fj_kernel::algorithms::{triangulate, Tolerance}; +use fj_kernel::{ + algorithms::{triangulate, Tolerance}, + shape::ValidationError, +}; use fj_math::{Aabb, Point, Scalar}; use crate::ToShape as _; @@ -14,7 +17,10 @@ pub struct ShapeProcessor { impl ShapeProcessor { /// Process an [`fj::Shape`] into [`ProcessedShape`] - pub fn process(&self, shape: &fj::Shape) -> ProcessedShape { + pub fn process( + &self, + shape: &fj::Shape, + ) -> Result { let aabb = shape.bounding_volume(); let tolerance = match self.tolerance { @@ -37,16 +43,16 @@ impl ShapeProcessor { let mut debug_info = DebugInfo::new(); let mesh = triangulate( - shape.to_shape(tolerance, &mut debug_info).unwrap(), + shape.to_shape(tolerance, &mut debug_info)?, tolerance, &mut debug_info, ); - ProcessedShape { + Ok(ProcessedShape { aabb, mesh, debug_info, - } + }) } } diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 946abb550..657199900 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -47,7 +47,7 @@ pub fn run( let now = Instant::now(); if let Some(new_shape) = watcher.receive() { - let new_shape = shape_processor.process(&new_shape); + let new_shape = shape_processor.process(&new_shape).unwrap(); renderer.update_geometry( (&new_shape.mesh).into(), (&new_shape.debug_info).into(),