mirror of
				https://github.com/hannobraun/Fornjot
				synced 2025-10-31 12:18:20 +00:00 
			
		
		
		
	Merge pull request #465 from hannobraun/tolerance
Add `Tolerance` struct to enforce validity of tolerance values
This commit is contained in:
		
						commit
						c8223e57ef
					
				| @ -1,4 +1,7 @@ | |||||||
| use std::path::PathBuf; | use std::{path::PathBuf, str::FromStr as _}; | ||||||
|  | 
 | ||||||
|  | use fj_kernel::algorithms::Tolerance; | ||||||
|  | use fj_math::Scalar; | ||||||
| 
 | 
 | ||||||
| /// Fornjot - Experimental CAD System
 | /// Fornjot - Experimental CAD System
 | ||||||
| #[derive(clap::Parser)] | #[derive(clap::Parser)] | ||||||
| @ -16,8 +19,8 @@ pub struct Args { | |||||||
|     pub parameters: Vec<String>, |     pub parameters: Vec<String>, | ||||||
| 
 | 
 | ||||||
|     /// Model deviation tolerance
 |     /// Model deviation tolerance
 | ||||||
|     #[clap[short, long]] |     #[clap[short, long, parse(try_from_str = parse_tolerance)]] | ||||||
|     pub tolerance: Option<f64>, |     pub tolerance: Option<Tolerance>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Args { | impl Args { | ||||||
| @ -29,3 +32,11 @@ impl Args { | |||||||
|         <Self as clap::Parser>::parse() |         <Self as clap::Parser>::parse() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn parse_tolerance(input: &str) -> anyhow::Result<Tolerance> { | ||||||
|  |     let tolerance = f64::from_str(input)?; | ||||||
|  |     let tolerance = Scalar::from_f64(tolerance); | ||||||
|  |     let tolerance = Tolerance::from_scalar(tolerance)?; | ||||||
|  | 
 | ||||||
|  |     Ok(tolerance) | ||||||
|  | } | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ use std::{collections::HashMap, time::Instant}; | |||||||
| 
 | 
 | ||||||
| use fj_host::Model; | use fj_host::Model; | ||||||
| use fj_interop::{debug::DebugInfo, mesh::Mesh}; | use fj_interop::{debug::DebugInfo, mesh::Mesh}; | ||||||
| use fj_kernel::algorithms::triangulate; | use fj_kernel::algorithms::{triangulate, Tolerance}; | ||||||
| use fj_math::{Aabb, Point, Scalar}; | use fj_math::{Aabb, Point, Scalar}; | ||||||
| use fj_operations::ToShape as _; | use fj_operations::ToShape as _; | ||||||
| use futures::executor::block_on; | use futures::executor::block_on; | ||||||
| @ -78,7 +78,9 @@ fn main() -> anyhow::Result<()> { | |||||||
|         parameters.insert(key, value); |         parameters.insert(key, value); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let shape_processor = ShapeProcessor::new(args.tolerance)?; |     let shape_processor = ShapeProcessor { | ||||||
|  |         tolerance: args.tolerance, | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     if let Some(path) = args.export { |     if let Some(path) = args.export { | ||||||
|         let shape = model.load_once(¶meters)?; |         let shape = model.load_once(¶meters)?; | ||||||
| @ -238,26 +240,10 @@ fn main() -> anyhow::Result<()> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct ShapeProcessor { | struct ShapeProcessor { | ||||||
|     tolerance: Option<Scalar>, |     tolerance: Option<Tolerance>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ShapeProcessor { | impl ShapeProcessor { | ||||||
|     fn new(tolerance: Option<f64>) -> anyhow::Result<Self> { |  | ||||||
|         if let Some(tolerance) = tolerance { |  | ||||||
|             if tolerance <= 0. { |  | ||||||
|                 anyhow::bail!( |  | ||||||
|                     "Invalid user defined model deviation tolerance: {}.\n\ |  | ||||||
|                     Tolerance must be larger than zero",
 |  | ||||||
|                     tolerance |  | ||||||
|                 ); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         let tolerance = tolerance.map(Scalar::from_f64); |  | ||||||
| 
 |  | ||||||
|         Ok(Self { tolerance }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn process(&self, shape: &fj::Shape) -> ProcessedShape { |     fn process(&self, shape: &fj::Shape) -> ProcessedShape { | ||||||
|         let aabb = shape.bounding_volume(); |         let aabb = shape.bounding_volume(); | ||||||
| 
 | 
 | ||||||
| @ -273,11 +259,8 @@ impl ShapeProcessor { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 // `tolerance` must not be zero, or we'll run into trouble.
 |  | ||||||
|                 let tolerance = min_extent / Scalar::from_f64(1000.); |                 let tolerance = min_extent / Scalar::from_f64(1000.); | ||||||
|                 assert!(tolerance > Scalar::ZERO); |                 Tolerance::from_scalar(tolerance).unwrap() | ||||||
| 
 |  | ||||||
|                 tolerance |  | ||||||
|             } |             } | ||||||
|             Some(user_defined_tolerance) => user_defined_tolerance, |             Some(user_defined_tolerance) => user_defined_tolerance, | ||||||
|         }; |         }; | ||||||
|  | |||||||
| @ -25,7 +25,7 @@ impl FaceApprox { | |||||||
|     ///
 |     ///
 | ||||||
|     /// `tolerance` defines how far the approximation is allowed to deviate from
 |     /// `tolerance` defines how far the approximation is allowed to deviate from
 | ||||||
|     /// the actual face.
 |     /// the actual face.
 | ||||||
|     pub fn new(face: &Face, tolerance: Scalar) -> Self { |     pub fn new(face: &Face, tolerance: Tolerance) -> Self { | ||||||
|         // Curved faces whose curvature is not fully defined by their edges
 |         // Curved faces whose curvature is not fully defined by their edges
 | ||||||
|         // are not supported yet. For that reason, we can fully ignore `face`'s
 |         // are not supported yet. For that reason, we can fully ignore `face`'s
 | ||||||
|         // `surface` field and just pass the edges to `Self::for_edges`.
 |         // `surface` field and just pass the edges to `Self::for_edges`.
 | ||||||
| @ -88,7 +88,7 @@ impl CycleApprox { | |||||||
|     ///
 |     ///
 | ||||||
|     /// `tolerance` defines how far the approximation is allowed to deviate from
 |     /// `tolerance` defines how far the approximation is allowed to deviate from
 | ||||||
|     /// the actual face.
 |     /// the actual face.
 | ||||||
|     pub fn new(cycle: &Cycle, tolerance: Scalar) -> Self { |     pub fn new(cycle: &Cycle, tolerance: Tolerance) -> Self { | ||||||
|         let mut points = Vec::new(); |         let mut points = Vec::new(); | ||||||
| 
 | 
 | ||||||
|         for edge in cycle.edges() { |         for edge in cycle.edges() { | ||||||
| @ -160,6 +160,61 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// A tolerance value
 | ||||||
|  | ///
 | ||||||
|  | /// A tolerance value is used during approximation. It defines the maximum
 | ||||||
|  | /// allowed deviation of the approximation from the actual shape.
 | ||||||
|  | ///
 | ||||||
|  | /// The `Tolerance` type enforces that the tolerance value is always larger than
 | ||||||
|  | /// zero, which is an attribute that the approximation code relies on.
 | ||||||
|  | ///
 | ||||||
|  | /// # Failing [`From`]/[`Into`] implementation
 | ||||||
|  | ///
 | ||||||
|  | /// The [`From`]/[`Into`] implementations of tolerance are fallible, which goes
 | ||||||
|  | /// against the explicit mandate of those traits, as stated in their
 | ||||||
|  | /// documentation.
 | ||||||
|  | ///
 | ||||||
|  | /// A fallible [`Into`] provides a lot of convenience in test code. Since said
 | ||||||
|  | /// documentation doesn't provide any actual reasoning for this requirement, I'm
 | ||||||
|  | /// feeling free to just ignore it.
 | ||||||
|  | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] | ||||||
|  | pub struct Tolerance(Scalar); | ||||||
|  | 
 | ||||||
|  | impl Tolerance { | ||||||
|  |     /// Construct a `Tolerance` from a [`Scalar`]
 | ||||||
|  |     ///
 | ||||||
|  |     /// Returns an error, if the passed scalar is not larger than zero.
 | ||||||
|  |     pub fn from_scalar( | ||||||
|  |         scalar: impl Into<Scalar>, | ||||||
|  |     ) -> Result<Self, InvalidTolerance> { | ||||||
|  |         let scalar = scalar.into(); | ||||||
|  | 
 | ||||||
|  |         if scalar <= Scalar::ZERO { | ||||||
|  |             return Err(InvalidTolerance(scalar)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Ok(Self(scalar)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Return the [`Scalar`] that defines the tolerance
 | ||||||
|  |     pub fn inner(&self) -> Scalar { | ||||||
|  |         self.0 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<S> From<S> for Tolerance | ||||||
|  | where | ||||||
|  |     S: Into<Scalar>, | ||||||
|  | { | ||||||
|  |     fn from(scalar: S) -> Self { | ||||||
|  |         Self::from_scalar(scalar).unwrap() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, thiserror::Error)] | ||||||
|  | #[error("Invalid tolerance ({0}); must be above zero")] | ||||||
|  | pub struct InvalidTolerance(Scalar); | ||||||
|  | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use fj_math::{Point, Scalar}; |     use fj_math::{Point, Scalar}; | ||||||
| @ -171,7 +226,7 @@ mod tests { | |||||||
|         topology::{Face, Vertex}, |         topology::{Face, Vertex}, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     use super::{CycleApprox, FaceApprox}; |     use super::{CycleApprox, FaceApprox, Tolerance}; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn approximate_edge() -> anyhow::Result<()> { |     fn approximate_edge() -> anyhow::Result<()> { | ||||||
| @ -201,7 +256,7 @@ mod tests { | |||||||
|     fn for_face_closed() -> anyhow::Result<()> { |     fn for_face_closed() -> anyhow::Result<()> { | ||||||
|         // Test a closed face, i.e. one that is completely encircled by edges.
 |         // Test a closed face, i.e. one that is completely encircled by edges.
 | ||||||
| 
 | 
 | ||||||
|         let tolerance = Scalar::ONE; |         let tolerance = Tolerance::from_scalar(Scalar::ONE).unwrap(); | ||||||
| 
 | 
 | ||||||
|         let mut shape = Shape::new(); |         let mut shape = Shape::new(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ mod sweep; | |||||||
| mod triangulation; | mod triangulation; | ||||||
| 
 | 
 | ||||||
| pub use self::{ | pub use self::{ | ||||||
|     approximation::{CycleApprox, FaceApprox}, |     approximation::{CycleApprox, FaceApprox, Tolerance}, | ||||||
|     sweep::sweep_shape, |     sweep::sweep_shape, | ||||||
|     triangulation::triangulate, |     triangulation::triangulate, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| 
 | 
 | ||||||
| use fj_math::{Scalar, Transform, Triangle, Vector}; | use fj_math::{Transform, Triangle, Vector}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     geometry::{Surface, SweptCurve}, |     geometry::{Surface, SweptCurve}, | ||||||
| @ -8,13 +8,13 @@ use crate::{ | |||||||
|     topology::{Cycle, Edge, Face, Vertex}, |     topology::{Cycle, Edge, Face, Vertex}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use super::CycleApprox; | use super::{CycleApprox, Tolerance}; | ||||||
| 
 | 
 | ||||||
| /// Create a new shape by sweeping an existing one
 | /// Create a new shape by sweeping an existing one
 | ||||||
| pub fn sweep_shape( | pub fn sweep_shape( | ||||||
|     mut source: Shape, |     mut source: Shape, | ||||||
|     path: Vector<3>, |     path: Vector<3>, | ||||||
|     tolerance: Scalar, |     tolerance: Tolerance, | ||||||
|     color: [u8; 4], |     color: [u8; 4], | ||||||
| ) -> Shape { | ) -> Shape { | ||||||
|     let mut target = Shape::new(); |     let mut target = Shape::new(); | ||||||
| @ -316,6 +316,7 @@ mod tests { | |||||||
|     use fj_math::{Point, Scalar, Vector}; |     use fj_math::{Point, Scalar, Vector}; | ||||||
| 
 | 
 | ||||||
|     use crate::{ |     use crate::{ | ||||||
|  |         algorithms::Tolerance, | ||||||
|         geometry::{Surface, SweptCurve}, |         geometry::{Surface, SweptCurve}, | ||||||
|         shape::{Handle, Shape}, |         shape::{Handle, Shape}, | ||||||
|         topology::{Cycle, Edge, Face}, |         topology::{Cycle, Edge, Face}, | ||||||
| @ -325,12 +326,14 @@ mod tests { | |||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn sweep() -> anyhow::Result<()> { |     fn sweep() -> anyhow::Result<()> { | ||||||
|  |         let tolerance = Tolerance::from_scalar(Scalar::ONE).unwrap(); | ||||||
|  | 
 | ||||||
|         let sketch = Triangle::new([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.]])?; |         let sketch = Triangle::new([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.]])?; | ||||||
| 
 | 
 | ||||||
|         let mut swept = sweep_shape( |         let mut swept = sweep_shape( | ||||||
|             sketch.shape, |             sketch.shape, | ||||||
|             Vector::from([0., 0., 1.]), |             Vector::from([0., 0., 1.]), | ||||||
|             Scalar::from_f64(0.), |             tolerance, | ||||||
|             [255, 0, 0, 255], |             [255, 0, 0, 255], | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,18 +3,18 @@ mod polygon; | |||||||
| mod ray; | mod ray; | ||||||
| 
 | 
 | ||||||
| use fj_interop::{debug::DebugInfo, mesh::Mesh}; | use fj_interop::{debug::DebugInfo, mesh::Mesh}; | ||||||
| use fj_math::{Point, Scalar}; | use fj_math::Point; | ||||||
| 
 | 
 | ||||||
| use crate::{shape::Shape, topology::Face}; | use crate::{shape::Shape, topology::Face}; | ||||||
| 
 | 
 | ||||||
| use self::polygon::Polygon; | use self::polygon::Polygon; | ||||||
| 
 | 
 | ||||||
| use super::FaceApprox; | use super::{FaceApprox, Tolerance}; | ||||||
| 
 | 
 | ||||||
| /// Triangulate a shape
 | /// Triangulate a shape
 | ||||||
| pub fn triangulate( | pub fn triangulate( | ||||||
|     mut shape: Shape, |     mut shape: Shape, | ||||||
|     tolerance: Scalar, |     tolerance: Tolerance, | ||||||
|     debug_info: &mut DebugInfo, |     debug_info: &mut DebugInfo, | ||||||
| ) -> Mesh<Point<3>> { | ) -> Mesh<Point<3>> { | ||||||
|     let mut mesh = Mesh::new(); |     let mut mesh = Mesh::new(); | ||||||
| @ -83,7 +83,9 @@ mod tests { | |||||||
|     use fj_interop::{debug::DebugInfo, mesh::Mesh}; |     use fj_interop::{debug::DebugInfo, mesh::Mesh}; | ||||||
|     use fj_math::{Point, Scalar}; |     use fj_math::{Point, Scalar}; | ||||||
| 
 | 
 | ||||||
|     use crate::{geometry::Surface, shape::Shape, topology::Face}; |     use crate::{ | ||||||
|  |         algorithms::Tolerance, geometry::Surface, shape::Shape, topology::Face, | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn simple() -> anyhow::Result<()> { |     fn simple() -> anyhow::Result<()> { | ||||||
| @ -143,7 +145,7 @@ mod tests { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn triangulate(shape: Shape) -> Mesh<Point<3>> { |     fn triangulate(shape: Shape) -> Mesh<Point<3>> { | ||||||
|         let tolerance = Scalar::ONE; |         let tolerance = Tolerance::from_scalar(Scalar::ONE).unwrap(); | ||||||
| 
 | 
 | ||||||
|         let mut debug_info = DebugInfo::new(); |         let mut debug_info = DebugInfo::new(); | ||||||
|         super::triangulate(shape, tolerance, &mut debug_info) |         super::triangulate(shape, tolerance, &mut debug_info) | ||||||
|  | |||||||
| @ -2,6 +2,8 @@ use std::f64::consts::PI; | |||||||
| 
 | 
 | ||||||
| use fj_math::{Point, Scalar, Transform, Vector}; | use fj_math::{Point, Scalar, Transform, Vector}; | ||||||
| 
 | 
 | ||||||
|  | use crate::algorithms::Tolerance; | ||||||
|  | 
 | ||||||
| /// A circle
 | /// A circle
 | ||||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] | ||||||
| pub struct Circle { | pub struct Circle { | ||||||
| @ -80,7 +82,7 @@ impl Circle { | |||||||
|     ///
 |     ///
 | ||||||
|     /// `tolerance` specifies how much the approximation is allowed to deviate
 |     /// `tolerance` specifies how much the approximation is allowed to deviate
 | ||||||
|     /// from the circle.
 |     /// from the circle.
 | ||||||
|     pub fn approx(&self, tolerance: Scalar, out: &mut Vec<Point<3>>) { |     pub fn approx(&self, tolerance: Tolerance, out: &mut Vec<Point<3>>) { | ||||||
|         let radius = self.radius.magnitude(); |         let radius = self.radius.magnitude(); | ||||||
| 
 | 
 | ||||||
|         // To approximate the circle, we use a regular polygon for which
 |         // To approximate the circle, we use a regular polygon for which
 | ||||||
| @ -98,12 +100,11 @@ impl Circle { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn number_of_vertices(tolerance: Scalar, radius: Scalar) -> u64 { |     fn number_of_vertices(tolerance: Tolerance, radius: Scalar) -> u64 { | ||||||
|         assert!(tolerance > Scalar::ZERO); |         if tolerance.inner() > radius / Scalar::TWO { | ||||||
|         if tolerance > radius / Scalar::TWO { |  | ||||||
|             3 |             3 | ||||||
|         } else { |         } else { | ||||||
|             (Scalar::PI / (Scalar::ONE - (tolerance / radius)).acos()) |             (Scalar::PI / (Scalar::ONE - (tolerance.inner() / radius)).acos()) | ||||||
|                 .ceil() |                 .ceil() | ||||||
|                 .into_u64() |                 .into_u64() | ||||||
|         } |         } | ||||||
| @ -116,6 +117,8 @@ mod tests { | |||||||
| 
 | 
 | ||||||
|     use fj_math::{Point, Scalar, Vector}; |     use fj_math::{Point, Scalar, Vector}; | ||||||
| 
 | 
 | ||||||
|  |     use crate::algorithms::Tolerance; | ||||||
|  | 
 | ||||||
|     use super::Circle; |     use super::Circle; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -150,7 +153,7 @@ mod tests { | |||||||
|         verify_result(1., 100., 23); |         verify_result(1., 100., 23); | ||||||
| 
 | 
 | ||||||
|         fn verify_result( |         fn verify_result( | ||||||
|             tolerance: impl Into<Scalar>, |             tolerance: impl Into<Tolerance>, | ||||||
|             radius: impl Into<Scalar>, |             radius: impl Into<Scalar>, | ||||||
|             n: u64, |             n: u64, | ||||||
|         ) { |         ) { | ||||||
| @ -159,9 +162,9 @@ mod tests { | |||||||
| 
 | 
 | ||||||
|             assert_eq!(n, Circle::number_of_vertices(tolerance, radius)); |             assert_eq!(n, Circle::number_of_vertices(tolerance, radius)); | ||||||
| 
 | 
 | ||||||
|             assert!(calculate_error(radius, n) <= tolerance); |             assert!(calculate_error(radius, n) <= tolerance.inner()); | ||||||
|             if n > 3 { |             if n > 3 { | ||||||
|                 assert!(calculate_error(radius, n - 1) >= tolerance); |                 assert!(calculate_error(radius, n - 1) >= tolerance.inner()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,9 +1,11 @@ | |||||||
| mod circle; | mod circle; | ||||||
| mod line; | mod line; | ||||||
| 
 | 
 | ||||||
|  | use crate::algorithms::Tolerance; | ||||||
|  | 
 | ||||||
| pub use self::{circle::Circle, line::Line}; | pub use self::{circle::Circle, line::Line}; | ||||||
| 
 | 
 | ||||||
| use fj_math::{Point, Scalar, Transform, Vector}; | use fj_math::{Point, Transform, Vector}; | ||||||
| 
 | 
 | ||||||
| /// A one-dimensional shape
 | /// A one-dimensional shape
 | ||||||
| ///
 | ///
 | ||||||
| @ -96,7 +98,7 @@ impl Curve { | |||||||
|     /// The `approximate_between` methods of the curves then need to make sure
 |     /// The `approximate_between` methods of the curves then need to make sure
 | ||||||
|     /// to only return points in between those vertices, not the vertices
 |     /// to only return points in between those vertices, not the vertices
 | ||||||
|     /// themselves.
 |     /// themselves.
 | ||||||
|     pub fn approx(&self, tolerance: Scalar, out: &mut Vec<Point<3>>) { |     pub fn approx(&self, tolerance: Tolerance, out: &mut Vec<Point<3>>) { | ||||||
|         match self { |         match self { | ||||||
|             Self::Circle(circle) => circle.approx(tolerance, out), |             Self::Circle(circle) => circle.approx(tolerance, out), | ||||||
|             Self::Line(_) => {} |             Self::Line(_) => {} | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::{ | use fj_kernel::{ | ||||||
|  |     algorithms::Tolerance, | ||||||
|     geometry::Surface, |     geometry::Surface, | ||||||
|     shape::Shape, |     shape::Shape, | ||||||
|     topology::{Cycle, Edge, Face}, |     topology::{Cycle, Edge, Face}, | ||||||
| @ -9,7 +10,7 @@ use fj_math::{Aabb, Point, Scalar}; | |||||||
| use super::ToShape; | use super::ToShape; | ||||||
| 
 | 
 | ||||||
| impl ToShape for fj::Circle { | impl ToShape for fj::Circle { | ||||||
|     fn to_shape(&self, _: Scalar, _: &mut DebugInfo) -> Shape { |     fn to_shape(&self, _: Tolerance, _: &mut DebugInfo) -> Shape { | ||||||
|         let mut shape = Shape::new(); |         let mut shape = Shape::new(); | ||||||
| 
 | 
 | ||||||
|         // Circles have just a single round edge with no vertices. So none need
 |         // Circles have just a single round edge with no vertices. So none need
 | ||||||
|  | |||||||
| @ -2,15 +2,20 @@ use std::collections::HashMap; | |||||||
| 
 | 
 | ||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::{ | use fj_kernel::{ | ||||||
|  |     algorithms::Tolerance, | ||||||
|     shape::{Handle, Shape}, |     shape::{Handle, Shape}, | ||||||
|     topology::{Cycle, Edge, Face, Vertex}, |     topology::{Cycle, Edge, Face, Vertex}, | ||||||
| }; | }; | ||||||
| use fj_math::{Aabb, Scalar}; | use fj_math::Aabb; | ||||||
| 
 | 
 | ||||||
| use super::ToShape; | use super::ToShape; | ||||||
| 
 | 
 | ||||||
| impl ToShape for fj::Difference2d { | impl ToShape for fj::Difference2d { | ||||||
|     fn to_shape(&self, tolerance: Scalar, debug_info: &mut DebugInfo) -> Shape { |     fn to_shape( | ||||||
|  |         &self, | ||||||
|  |         tolerance: Tolerance, | ||||||
|  |         debug_info: &mut DebugInfo, | ||||||
|  |     ) -> Shape { | ||||||
|         // This method assumes that `b` is fully contained within `a`:
 |         // This method assumes that `b` is fully contained within `a`:
 | ||||||
|         // https://github.com/hannobraun/Fornjot/issues/92
 |         // https://github.com/hannobraun/Fornjot/issues/92
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,15 +2,20 @@ use std::collections::HashMap; | |||||||
| 
 | 
 | ||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::{ | use fj_kernel::{ | ||||||
|  |     algorithms::Tolerance, | ||||||
|     shape::Shape, |     shape::Shape, | ||||||
|     topology::{Cycle, Edge, Face, Vertex}, |     topology::{Cycle, Edge, Face, Vertex}, | ||||||
| }; | }; | ||||||
| use fj_math::{Aabb, Scalar}; | use fj_math::Aabb; | ||||||
| 
 | 
 | ||||||
| use super::ToShape; | use super::ToShape; | ||||||
| 
 | 
 | ||||||
| impl ToShape for fj::Group { | impl ToShape for fj::Group { | ||||||
|     fn to_shape(&self, tolerance: Scalar, debug_info: &mut DebugInfo) -> Shape { |     fn to_shape( | ||||||
|  |         &self, | ||||||
|  |         tolerance: Tolerance, | ||||||
|  |         debug_info: &mut DebugInfo, | ||||||
|  |     ) -> Shape { | ||||||
|         let mut shape = Shape::new(); |         let mut shape = Shape::new(); | ||||||
| 
 | 
 | ||||||
|         let a = self.a.to_shape(tolerance, debug_info); |         let a = self.a.to_shape(tolerance, debug_info); | ||||||
|  | |||||||
| @ -14,13 +14,13 @@ mod sweep; | |||||||
| mod transform; | mod transform; | ||||||
| 
 | 
 | ||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::shape::Shape; | use fj_kernel::{algorithms::Tolerance, shape::Shape}; | ||||||
| use fj_math::{Aabb, Scalar}; | use fj_math::Aabb; | ||||||
| 
 | 
 | ||||||
| /// Implemented for all operations from the [`fj`] crate
 | /// Implemented for all operations from the [`fj`] crate
 | ||||||
| pub trait ToShape { | pub trait ToShape { | ||||||
|     /// Compute the boundary representation of the shape
 |     /// Compute the boundary representation of the shape
 | ||||||
|     fn to_shape(&self, tolerance: Scalar, debug: &mut DebugInfo) -> Shape; |     fn to_shape(&self, tolerance: Tolerance, debug: &mut DebugInfo) -> Shape; | ||||||
| 
 | 
 | ||||||
|     /// Access the axis-aligned bounding box of a shape
 |     /// Access the axis-aligned bounding box of a shape
 | ||||||
|     ///
 |     ///
 | ||||||
| @ -70,7 +70,7 @@ macro_rules! dispatch { | |||||||
| 
 | 
 | ||||||
| dispatch! { | dispatch! { | ||||||
|     to_shape( |     to_shape( | ||||||
|         tolerance: Scalar, |         tolerance: Tolerance, | ||||||
|         debug: &mut DebugInfo, |         debug: &mut DebugInfo, | ||||||
|     ) -> Shape; |     ) -> Shape; | ||||||
|     bounding_volume() -> Aabb<3>; |     bounding_volume() -> Aabb<3>; | ||||||
|  | |||||||
| @ -1,15 +1,16 @@ | |||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::{ | use fj_kernel::{ | ||||||
|  |     algorithms::Tolerance, | ||||||
|     geometry::Surface, |     geometry::Surface, | ||||||
|     shape::Shape, |     shape::Shape, | ||||||
|     topology::{Cycle, Edge, Face, Vertex}, |     topology::{Cycle, Edge, Face, Vertex}, | ||||||
| }; | }; | ||||||
| use fj_math::{Aabb, Point, Scalar}; | use fj_math::{Aabb, Point}; | ||||||
| 
 | 
 | ||||||
| use super::ToShape; | use super::ToShape; | ||||||
| 
 | 
 | ||||||
| impl ToShape for fj::Sketch { | impl ToShape for fj::Sketch { | ||||||
|     fn to_shape(&self, _: Scalar, _: &mut DebugInfo) -> Shape { |     fn to_shape(&self, _: Tolerance, _: &mut DebugInfo) -> Shape { | ||||||
|         let mut shape = Shape::new(); |         let mut shape = Shape::new(); | ||||||
|         let mut vertices = Vec::new(); |         let mut vertices = Vec::new(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,11 +1,18 @@ | |||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::{algorithms::sweep_shape, shape::Shape}; | use fj_kernel::{ | ||||||
| use fj_math::{Aabb, Scalar, Vector}; |     algorithms::{sweep_shape, Tolerance}, | ||||||
|  |     shape::Shape, | ||||||
|  | }; | ||||||
|  | use fj_math::{Aabb, Vector}; | ||||||
| 
 | 
 | ||||||
| use super::ToShape; | use super::ToShape; | ||||||
| 
 | 
 | ||||||
| impl ToShape for fj::Sweep { | impl ToShape for fj::Sweep { | ||||||
|     fn to_shape(&self, tolerance: Scalar, debug_info: &mut DebugInfo) -> Shape { |     fn to_shape( | ||||||
|  |         &self, | ||||||
|  |         tolerance: Tolerance, | ||||||
|  |         debug_info: &mut DebugInfo, | ||||||
|  |     ) -> Shape { | ||||||
|         sweep_shape( |         sweep_shape( | ||||||
|             self.shape().to_shape(tolerance, debug_info), |             self.shape().to_shape(tolerance, debug_info), | ||||||
|             Vector::from([0., 0., self.length()]), |             Vector::from([0., 0., self.length()]), | ||||||
|  | |||||||
| @ -1,12 +1,16 @@ | |||||||
| use fj_interop::debug::DebugInfo; | use fj_interop::debug::DebugInfo; | ||||||
| use fj_kernel::shape::Shape; | use fj_kernel::{algorithms::Tolerance, shape::Shape}; | ||||||
| use fj_math::{Aabb, Scalar, Transform}; | use fj_math::{Aabb, Transform}; | ||||||
| use parry3d_f64::math::Isometry; | use parry3d_f64::math::Isometry; | ||||||
| 
 | 
 | ||||||
| use super::ToShape; | use super::ToShape; | ||||||
| 
 | 
 | ||||||
| impl ToShape for fj::Transform { | impl ToShape for fj::Transform { | ||||||
|     fn to_shape(&self, tolerance: Scalar, debug_info: &mut DebugInfo) -> Shape { |     fn to_shape( | ||||||
|  |         &self, | ||||||
|  |         tolerance: Tolerance, | ||||||
|  |         debug_info: &mut DebugInfo, | ||||||
|  |     ) -> Shape { | ||||||
|         let mut shape = self.shape.to_shape(tolerance, debug_info); |         let mut shape = self.shape.to_shape(tolerance, debug_info); | ||||||
|         let transform = transform(self); |         let transform = transform(self); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user