mirror of
https://github.com/hannobraun/Fornjot
synced 2025-02-07 15:55:53 +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…
Reference in New Issue
Block a user