From 598738cb79a5224ee099fede7ab0c2ab85d67d37 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 13:46:06 +0200 Subject: [PATCH 01/14] Use `Vertex` to specify curve approx boundary --- .../fj-kernel/src/algorithms/approx/curve.rs | 22 +++++--- .../fj-kernel/src/algorithms/approx/edge.rs | 53 +++++++++++++++---- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 2521ae043..60d74dac9 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -2,7 +2,7 @@ use std::cmp::max; use fj_math::{Circle, Point, Scalar}; -use crate::objects::{Curve, CurveKind, GlobalCurve}; +use crate::objects::{Curve, CurveKind, GlobalCurve, Vertex}; use super::{Approx, Tolerance}; @@ -38,7 +38,10 @@ impl Approx for GlobalCurve { ) -> Self::Approximation { match self.kind() { CurveKind::Circle(curve) => approx_circle(curve, range, tolerance), - CurveKind::Line(_) => vec![range.start()], + CurveKind::Line(_) => vec![( + range.start().position(), + range.start().global_form().position(), + )], } } } @@ -64,10 +67,13 @@ fn approx_circle( let n = number_of_vertices_for_circle(tolerance, radius, range.length()); let mut points = Vec::new(); - points.push(range.start()); + points.push(( + range.start().position(), + range.start().global_form().position(), + )); for i in 1..n { - let angle = range.start().0.t + let angle = range.start().position().t + (Scalar::TAU / n as f64 * i as f64) * range.direction(); let point_curve = Point::from([angle]); @@ -92,20 +98,20 @@ fn number_of_vertices_for_circle( } pub struct RangeOnCurve { - pub boundary: [(Point<1>, Point<3>); 2], + pub boundary: [Vertex; 2], } impl RangeOnCurve { - fn start(&self) -> (Point<1>, Point<3>) { + fn start(&self) -> Vertex { self.boundary[0] } - fn end(&self) -> (Point<1>, Point<3>) { + fn end(&self) -> Vertex { self.boundary[1] } fn signed_length(&self) -> Scalar { - (self.end().0 - self.start().0).t + (self.end().position() - self.start().position()).t } fn length(&self) -> Scalar { diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 332de02ec..38747f061 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -1,6 +1,6 @@ use fj_math::{Point, Scalar}; -use crate::objects::Edge; +use crate::objects::{Edge, GlobalVertex, SurfaceVertex, Vertex}; use super::{curve::RangeOnCurve, Approx}; @@ -15,22 +15,55 @@ impl Approx for Edge { ) -> Self::Approximation { // The range is only used for circles right now. let boundary = match self.vertices().get() { - Some(vertices) => vertices.map(|vertex| { - (vertex.position(), vertex.global_form().position()) - }), + Some(vertices) => vertices.map(|&vertex| vertex), None => { + // Creating vertices from nothing, just for the sake of + // approximation is a bit weird. But this code is a temporary + // fallback anyway. It'll do for now, and it will likely be + // removed soon. + let start_curve = Point::from([Scalar::ZERO]); let end_curve = Point::from([Scalar::TAU]); // We're dealing with a circle here. Start and end are identical // points, in global coordinates. - let point_global = self - .global_form() - .curve() - .kind() - .point_from_curve_coords(start_curve); + let vertex_global = { + let point_global = self + .global_form() + .curve() + .kind() + .point_from_curve_coords(start_curve); + + GlobalVertex::from_position(point_global) + }; + + let [start_surface, end_surface] = [start_curve, end_curve] + .map(|point_curve| { + let point_surface = self + .curve() + .kind() + .point_from_curve_coords(point_curve); + SurfaceVertex::new( + point_surface, + *self.curve().surface(), + vertex_global, + ) + }); + + let a = Vertex::new( + start_curve, + *self.curve(), + start_surface, + vertex_global, + ); + let b = Vertex::new( + end_curve, + *self.curve(), + end_surface, + vertex_global, + ); - [(start_curve, point_global), (end_curve, point_global)] + [a, b] } }; From 1227c5023c69450d172315567e6bcbff71bea7bf Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 13:51:25 +0200 Subject: [PATCH 02/14] Refactor --- .../fj-kernel/src/algorithms/approx/curve.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 60d74dac9..724b5b9cc 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -36,13 +36,19 @@ impl Approx for GlobalCurve { tolerance: Tolerance, range: Self::Params, ) -> Self::Approximation { + let mut points = Vec::new(); + match self.kind() { - CurveKind::Circle(curve) => approx_circle(curve, range, tolerance), - CurveKind::Line(_) => vec![( + CurveKind::Circle(curve) => { + approx_circle(curve, range, tolerance, &mut points); + } + CurveKind::Line(_) => points.push(( range.start().position(), range.start().global_form().position(), - )], + )), } + + points } } @@ -54,7 +60,8 @@ fn approx_circle( circle: &Circle<3>, range: impl Into, tolerance: Tolerance, -) -> Vec<(Point<1>, Point<3>)> { + points: &mut Vec<(Point<1>, Point<3>)>, +) { let radius = circle.a().magnitude(); let range = range.into(); @@ -66,7 +73,6 @@ fn approx_circle( let n = number_of_vertices_for_circle(tolerance, radius, range.length()); - let mut points = Vec::new(); points.push(( range.start().position(), range.start().global_form().position(), @@ -81,8 +87,6 @@ fn approx_circle( points.push((point_curve, point_global)); } - - points } fn number_of_vertices_for_circle( From f4734299f33e3e46c04587eae9ee5de2f8e505b0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 13:52:09 +0200 Subject: [PATCH 03/14] Remove duplicated code --- crates/fj-kernel/src/algorithms/approx/curve.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 724b5b9cc..5e079bd7c 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -37,15 +37,16 @@ impl Approx for GlobalCurve { range: Self::Params, ) -> Self::Approximation { let mut points = Vec::new(); + points.push(( + range.start().position(), + range.start().global_form().position(), + )); match self.kind() { CurveKind::Circle(curve) => { approx_circle(curve, range, tolerance, &mut points); } - CurveKind::Line(_) => points.push(( - range.start().position(), - range.start().global_form().position(), - )), + CurveKind::Line(_) => {} } points @@ -73,11 +74,6 @@ fn approx_circle( let n = number_of_vertices_for_circle(tolerance, radius, range.length()); - points.push(( - range.start().position(), - range.start().global_form().position(), - )); - for i in 1..n { let angle = range.start().position().t + (Scalar::TAU / n as f64 * i as f64) * range.direction(); From f6271539b8f39477f8a6c8fc35deac83676d9d8d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 13:58:49 +0200 Subject: [PATCH 04/14] Make methods public --- crates/fj-kernel/src/algorithms/approx/curve.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 5e079bd7c..87885cf9f 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -102,23 +102,23 @@ pub struct RangeOnCurve { } impl RangeOnCurve { - fn start(&self) -> Vertex { + pub fn start(&self) -> Vertex { self.boundary[0] } - fn end(&self) -> Vertex { + pub fn end(&self) -> Vertex { self.boundary[1] } - fn signed_length(&self) -> Scalar { + pub fn signed_length(&self) -> Scalar { (self.end().position() - self.start().position()).t } - fn length(&self) -> Scalar { + pub fn length(&self) -> Scalar { self.signed_length().abs() } - fn direction(&self) -> Scalar { + pub fn direction(&self) -> Scalar { self.signed_length().sign() } } From 4b7454055ca5d6fb1bba6969cad438c5ff1622fc Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:13:58 +0200 Subject: [PATCH 05/14] Derive `Copy` for `RangeOnCurve` --- crates/fj-kernel/src/algorithms/approx/curve.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 87885cf9f..24254a2c0 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -97,6 +97,7 @@ fn number_of_vertices_for_circle( max(n, 3) } +#[derive(Clone, Copy)] pub struct RangeOnCurve { pub boundary: [Vertex; 2], } From ce3ad1dcc8d23f5a82a438ccd8dbbc8fc8f764df Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 13:59:30 +0200 Subject: [PATCH 06/14] Don't recompute surface position --- crates/fj-kernel/src/algorithms/approx/curve.rs | 4 ---- crates/fj-kernel/src/algorithms/approx/edge.rs | 11 ++++++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 24254a2c0..da74d5ed6 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -37,10 +37,6 @@ impl Approx for GlobalCurve { range: Self::Params, ) -> Self::Approximation { let mut points = Vec::new(); - points.push(( - range.start().position(), - range.start().global_form().position(), - )); match self.kind() { CurveKind::Circle(curve) => { diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 38747f061..b6d78a0ff 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -69,6 +69,15 @@ impl Approx for Edge { let range = RangeOnCurve { boundary }; - self.curve().approx(tolerance, range) + let mut points = self.curve().approx(tolerance, range); + points.insert( + 0, + ( + range.start().surface_form().position(), + range.start().global_form().position(), + ), + ); + + points } } From 11351f8de82d61c7f8bca79dcb8a6197b470d22d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:16:18 +0200 Subject: [PATCH 07/14] Remove use of `Approx::Params` --- crates/fj-kernel/src/algorithms/approx/curve.rs | 13 ++++++++----- crates/fj-kernel/src/algorithms/approx/edge.rs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index da74d5ed6..b55208d8d 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -6,21 +6,24 @@ use crate::objects::{Curve, CurveKind, GlobalCurve, Vertex}; use super::{Approx, Tolerance}; -impl Approx for Curve { +impl Approx for (Curve, RangeOnCurve) { type Approximation = Vec<(Point<2>, Point<3>)>; - type Params = RangeOnCurve; + type Params = (); fn approx( &self, tolerance: Tolerance, - range: Self::Params, + _: Self::Params, ) -> Self::Approximation { - self.global_form() + let &(curve, range) = self; + + curve + .global_form() .approx(tolerance, range) .into_iter() .map(|(point_curve, point_global)| { let point_surface = - self.kind().point_from_curve_coords(point_curve); + curve.kind().point_from_curve_coords(point_curve); (point_surface, point_global) }) .collect() diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index b6d78a0ff..085abf8a8 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -69,7 +69,7 @@ impl Approx for Edge { let range = RangeOnCurve { boundary }; - let mut points = self.curve().approx(tolerance, range); + let mut points = (*self.curve(), range).approx(tolerance, ()); points.insert( 0, ( From 4b2164cf13619214d33da7c92833e9ec844f5065 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:17:44 +0200 Subject: [PATCH 08/14] Remove use of `Approx::Params` --- crates/fj-kernel/src/algorithms/approx/curve.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index b55208d8d..5295d98d6 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -17,9 +17,8 @@ impl Approx for (Curve, RangeOnCurve) { ) -> Self::Approximation { let &(curve, range) = self; - curve - .global_form() - .approx(tolerance, range) + (*curve.global_form(), range) + .approx(tolerance, ()) .into_iter() .map(|(point_curve, point_global)| { let point_surface = @@ -30,18 +29,20 @@ impl Approx for (Curve, RangeOnCurve) { } } -impl Approx for GlobalCurve { +impl Approx for (GlobalCurve, RangeOnCurve) { type Approximation = Vec<(Point<1>, Point<3>)>; - type Params = RangeOnCurve; + type Params = (); fn approx( &self, tolerance: Tolerance, - range: Self::Params, + _: Self::Params, ) -> Self::Approximation { + let &(curve, range) = self; + let mut points = Vec::new(); - match self.kind() { + match curve.kind() { CurveKind::Circle(curve) => { approx_circle(curve, range, tolerance, &mut points); } From df1ee8f42d0612be244637ee73fc50fa3a520e01 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:19:09 +0200 Subject: [PATCH 09/14] Remove `Approx::Params` --- crates/fj-kernel/src/algorithms/approx/curve.rs | 16 +++------------- crates/fj-kernel/src/algorithms/approx/cycle.rs | 9 ++------- crates/fj-kernel/src/algorithms/approx/edge.rs | 9 ++------- crates/fj-kernel/src/algorithms/approx/face.rs | 13 ++++--------- crates/fj-kernel/src/algorithms/approx/mod.rs | 9 +-------- crates/fj-kernel/src/algorithms/sweep/edge.rs | 2 +- .../fj-kernel/src/algorithms/triangulate/mod.rs | 2 +- 7 files changed, 14 insertions(+), 46 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 5295d98d6..c30b66d68 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -8,17 +8,12 @@ use super::{Approx, Tolerance}; impl Approx for (Curve, RangeOnCurve) { type Approximation = Vec<(Point<2>, Point<3>)>; - type Params = (); - fn approx( - &self, - tolerance: Tolerance, - _: Self::Params, - ) -> Self::Approximation { + fn approx(&self, tolerance: Tolerance) -> Self::Approximation { let &(curve, range) = self; (*curve.global_form(), range) - .approx(tolerance, ()) + .approx(tolerance) .into_iter() .map(|(point_curve, point_global)| { let point_surface = @@ -31,13 +26,8 @@ impl Approx for (Curve, RangeOnCurve) { impl Approx for (GlobalCurve, RangeOnCurve) { type Approximation = Vec<(Point<1>, Point<3>)>; - type Params = (); - fn approx( - &self, - tolerance: Tolerance, - _: Self::Params, - ) -> Self::Approximation { + fn approx(&self, tolerance: Tolerance) -> Self::Approximation { let &(curve, range) = self; let mut points = Vec::new(); diff --git a/crates/fj-kernel/src/algorithms/approx/cycle.rs b/crates/fj-kernel/src/algorithms/approx/cycle.rs index 6c373609c..0505f97c5 100644 --- a/crates/fj-kernel/src/algorithms/approx/cycle.rs +++ b/crates/fj-kernel/src/algorithms/approx/cycle.rs @@ -6,17 +6,12 @@ use super::{Approx, Tolerance}; impl Approx for Cycle { type Approximation = CycleApprox; - type Params = (); - fn approx( - &self, - tolerance: Tolerance, - (): Self::Params, - ) -> Self::Approximation { + fn approx(&self, tolerance: Tolerance) -> Self::Approximation { let mut points = Vec::new(); for edge in self.edges() { - let edge_points = edge.approx(tolerance, ()); + let edge_points = edge.approx(tolerance); points.extend(edge_points); } diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 085abf8a8..009ba84ce 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -6,13 +6,8 @@ use super::{curve::RangeOnCurve, Approx}; impl Approx for Edge { type Approximation = Vec<(Point<2>, Point<3>)>; - type Params = (); - fn approx( - &self, - tolerance: super::Tolerance, - (): Self::Params, - ) -> Self::Approximation { + fn approx(&self, tolerance: super::Tolerance) -> Self::Approximation { // The range is only used for circles right now. let boundary = match self.vertices().get() { Some(vertices) => vertices.map(|&vertex| vertex), @@ -69,7 +64,7 @@ impl Approx for Edge { let range = RangeOnCurve { boundary }; - let mut points = (*self.curve(), range).approx(tolerance, ()); + let mut points = (*self.curve(), range).approx(tolerance); points.insert( 0, ( diff --git a/crates/fj-kernel/src/algorithms/approx/face.rs b/crates/fj-kernel/src/algorithms/approx/face.rs index 79b4bc932..c75054714 100644 --- a/crates/fj-kernel/src/algorithms/approx/face.rs +++ b/crates/fj-kernel/src/algorithms/approx/face.rs @@ -8,13 +8,8 @@ use super::{Approx, CycleApprox, Tolerance}; impl Approx for Face { type Approximation = FaceApprox; - type Params = (); - fn approx( - &self, - tolerance: Tolerance, - (): Self::Params, - ) -> Self::Approximation { + fn approx(&self, tolerance: Tolerance) -> Self::Approximation { // Curved faces whose curvature is not fully defined by their edges // are not supported yet. For that reason, we can fully ignore `face`'s // `surface` field and just pass the edges to `Self::for_edges`. @@ -33,13 +28,13 @@ impl Approx for Face { let mut interiors = HashSet::new(); for cycle in self.exteriors() { - let cycle = cycle.approx(tolerance, ()); + let cycle = cycle.approx(tolerance); points.extend(cycle.points.iter().copied()); exteriors.push(cycle); } for cycle in self.interiors() { - let cycle = cycle.approx(tolerance, ()); + let cycle = cycle.approx(tolerance); points.extend(cycle.points.iter().copied()); interiors.insert(cycle); @@ -123,7 +118,7 @@ mod tests { let g = (g, g.to_xyz()); let h = (h, h.to_xyz()); - let approx = face.approx(tolerance, ()); + let approx = face.approx(tolerance); let expected = FaceApprox { points: set![a, b, c, d, e, f, g, h], exterior: CycleApprox { diff --git a/crates/fj-kernel/src/algorithms/approx/mod.rs b/crates/fj-kernel/src/algorithms/approx/mod.rs index a86e3f10c..69c67fa59 100644 --- a/crates/fj-kernel/src/algorithms/approx/mod.rs +++ b/crates/fj-kernel/src/algorithms/approx/mod.rs @@ -17,16 +17,9 @@ pub trait Approx { /// The approximation of the object type Approximation; - /// Additional parameters required for the approximation - type Params; - /// Approximate the object /// /// `tolerance` defines how far the approximation is allowed to deviate from /// the actual object. - fn approx( - &self, - tolerance: Tolerance, - params: Self::Params, - ) -> Self::Approximation; + fn approx(&self, tolerance: Tolerance) -> Self::Approximation; } diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 5224cedbf..0a5ab39a4 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -214,7 +214,7 @@ fn create_continuous_side_face( let placeholder = Surface::xy_plane(); let cycle = Cycle::new(placeholder, [edge]); - let approx = cycle.approx(tolerance, ()); + let approx = cycle.approx(tolerance); let mut quads = Vec::new(); for segment in approx.segments() { diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 332d190fa..98621ab02 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -27,7 +27,7 @@ pub fn triangulate( } let surface = face.surface(); - let approx = face.approx(tolerance, ()); + let approx = face.approx(tolerance); let points: Vec<_> = approx .points From f0898e1d233a7d71e9e666ab23319dce86add846 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:20:29 +0200 Subject: [PATCH 10/14] Make `Approx` more flexible to implement --- crates/fj-kernel/src/algorithms/approx/curve.rs | 14 +++++++------- crates/fj-kernel/src/algorithms/approx/cycle.rs | 4 ++-- crates/fj-kernel/src/algorithms/approx/edge.rs | 6 +++--- crates/fj-kernel/src/algorithms/approx/face.rs | 4 ++-- crates/fj-kernel/src/algorithms/approx/mod.rs | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index c30b66d68..874a7170a 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -6,13 +6,13 @@ use crate::objects::{Curve, CurveKind, GlobalCurve, Vertex}; use super::{Approx, Tolerance}; -impl Approx for (Curve, RangeOnCurve) { +impl Approx for (&Curve, RangeOnCurve) { type Approximation = Vec<(Point<2>, Point<3>)>; - fn approx(&self, tolerance: Tolerance) -> Self::Approximation { - let &(curve, range) = self; + fn approx(self, tolerance: Tolerance) -> Self::Approximation { + let (curve, range) = self; - (*curve.global_form(), range) + (curve.global_form(), range) .approx(tolerance) .into_iter() .map(|(point_curve, point_global)| { @@ -24,11 +24,11 @@ impl Approx for (Curve, RangeOnCurve) { } } -impl Approx for (GlobalCurve, RangeOnCurve) { +impl Approx for (&GlobalCurve, RangeOnCurve) { type Approximation = Vec<(Point<1>, Point<3>)>; - fn approx(&self, tolerance: Tolerance) -> Self::Approximation { - let &(curve, range) = self; + fn approx(self, tolerance: Tolerance) -> Self::Approximation { + let (curve, range) = self; let mut points = Vec::new(); diff --git a/crates/fj-kernel/src/algorithms/approx/cycle.rs b/crates/fj-kernel/src/algorithms/approx/cycle.rs index 0505f97c5..6abb78f8b 100644 --- a/crates/fj-kernel/src/algorithms/approx/cycle.rs +++ b/crates/fj-kernel/src/algorithms/approx/cycle.rs @@ -4,10 +4,10 @@ use crate::objects::Cycle; use super::{Approx, Tolerance}; -impl Approx for Cycle { +impl Approx for &Cycle { type Approximation = CycleApprox; - fn approx(&self, tolerance: Tolerance) -> Self::Approximation { + fn approx(self, tolerance: Tolerance) -> Self::Approximation { let mut points = Vec::new(); for edge in self.edges() { diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 009ba84ce..5ef59e180 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -4,10 +4,10 @@ use crate::objects::{Edge, GlobalVertex, SurfaceVertex, Vertex}; use super::{curve::RangeOnCurve, Approx}; -impl Approx for Edge { +impl Approx for &Edge { type Approximation = Vec<(Point<2>, Point<3>)>; - fn approx(&self, tolerance: super::Tolerance) -> Self::Approximation { + fn approx(self, tolerance: super::Tolerance) -> Self::Approximation { // The range is only used for circles right now. let boundary = match self.vertices().get() { Some(vertices) => vertices.map(|&vertex| vertex), @@ -64,7 +64,7 @@ impl Approx for Edge { let range = RangeOnCurve { boundary }; - let mut points = (*self.curve(), range).approx(tolerance); + let mut points = (self.curve(), range).approx(tolerance); points.insert( 0, ( diff --git a/crates/fj-kernel/src/algorithms/approx/face.rs b/crates/fj-kernel/src/algorithms/approx/face.rs index c75054714..b16b8f03f 100644 --- a/crates/fj-kernel/src/algorithms/approx/face.rs +++ b/crates/fj-kernel/src/algorithms/approx/face.rs @@ -6,10 +6,10 @@ use crate::objects::Face; use super::{Approx, CycleApprox, Tolerance}; -impl Approx for Face { +impl Approx for &Face { type Approximation = FaceApprox; - fn approx(&self, tolerance: Tolerance) -> Self::Approximation { + fn approx(self, tolerance: Tolerance) -> Self::Approximation { // Curved faces whose curvature is not fully defined by their edges // are not supported yet. For that reason, we can fully ignore `face`'s // `surface` field and just pass the edges to `Self::for_edges`. diff --git a/crates/fj-kernel/src/algorithms/approx/mod.rs b/crates/fj-kernel/src/algorithms/approx/mod.rs index 69c67fa59..68722eae6 100644 --- a/crates/fj-kernel/src/algorithms/approx/mod.rs +++ b/crates/fj-kernel/src/algorithms/approx/mod.rs @@ -21,5 +21,5 @@ pub trait Approx { /// /// `tolerance` defines how far the approximation is allowed to deviate from /// the actual object. - fn approx(&self, tolerance: Tolerance) -> Self::Approximation; + fn approx(self, tolerance: Tolerance) -> Self::Approximation; } From fcf1622771986397eb122bc1abe86e2a3d2a235a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:27:14 +0200 Subject: [PATCH 11/14] Document `approx` module --- .../fj-kernel/src/algorithms/approx/curve.rs | 23 +++++++++++++++++++ .../fj-kernel/src/algorithms/approx/cycle.rs | 4 ++++ .../fj-kernel/src/algorithms/approx/edge.rs | 7 ++++++ .../fj-kernel/src/algorithms/approx/face.rs | 4 ++++ .../src/algorithms/approx/tolerance.rs | 4 ++++ 5 files changed, 42 insertions(+) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 874a7170a..9610e278d 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -1,3 +1,14 @@ +//! Curve approximation +//! +//! Since curves are infinite (even circles have an infinite coordinate space, +//! even though they connect to themselves in global coordinates), a range must +//! be provided to approximate them. The approximation then returns points +//! within that range. +//! +//! The boundaries of the range are not included in the approximation. This is +//! done, to give the caller (who knows the boundary anyway) more options on how +//! to further process the approximation. + use std::cmp::max; use fj_math::{Circle, Point, Scalar}; @@ -87,28 +98,40 @@ fn number_of_vertices_for_circle( max(n, 3) } +/// The range on which a curve should be approximated #[derive(Clone, Copy)] pub struct RangeOnCurve { + /// The boundary of the range + /// + /// The vertices that make up the boundary are themselves not included in + /// the approximation. pub boundary: [Vertex; 2], } impl RangeOnCurve { + /// Access the start of the range pub fn start(&self) -> Vertex { self.boundary[0] } + /// Access the end of the range pub fn end(&self) -> Vertex { self.boundary[1] } + /// Compute the signed length of the range pub fn signed_length(&self) -> Scalar { (self.end().position() - self.start().position()).t } + /// Compute the absolute length of the range pub fn length(&self) -> Scalar { self.signed_length().abs() } + /// Compute the direction of the range + /// + /// Returns a [`Scalar`] that is zero or +/- one. pub fn direction(&self) -> Scalar { self.signed_length().sign() } diff --git a/crates/fj-kernel/src/algorithms/approx/cycle.rs b/crates/fj-kernel/src/algorithms/approx/cycle.rs index 6abb78f8b..29f2ea94b 100644 --- a/crates/fj-kernel/src/algorithms/approx/cycle.rs +++ b/crates/fj-kernel/src/algorithms/approx/cycle.rs @@ -1,3 +1,7 @@ +//! Cycle approximation +//! +//! See [`CycleApprox`]. + use fj_math::{Point, Segment}; use crate::objects::Cycle; diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 5ef59e180..3cefdc3fc 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -1,3 +1,10 @@ +//! Edge approximation +//! +//! The approximation of a curve is its first vertex, combined with the +//! approximation of its curve. The second vertex is left off, as edge +//! approximations are usually used to build cycle approximations, and this way, +//! the caller doesn't have to call with duplicate vertices. + use fj_math::{Point, Scalar}; use crate::objects::{Edge, GlobalVertex, SurfaceVertex, Vertex}; diff --git a/crates/fj-kernel/src/algorithms/approx/face.rs b/crates/fj-kernel/src/algorithms/approx/face.rs index b16b8f03f..40730cc01 100644 --- a/crates/fj-kernel/src/algorithms/approx/face.rs +++ b/crates/fj-kernel/src/algorithms/approx/face.rs @@ -1,3 +1,7 @@ +//! Face approximation +//! +//! See [`FaceApprox`]. + use std::collections::HashSet; use fj_math::Point; diff --git a/crates/fj-kernel/src/algorithms/approx/tolerance.rs b/crates/fj-kernel/src/algorithms/approx/tolerance.rs index d8e97abb4..f6a3293c1 100644 --- a/crates/fj-kernel/src/algorithms/approx/tolerance.rs +++ b/crates/fj-kernel/src/algorithms/approx/tolerance.rs @@ -1,3 +1,7 @@ +//! Tolerance value for approximation +//! +//! See [`Tolerance`]. + use fj_math::Scalar; /// A tolerance value From 7ed3599e8cb4670d73d9a6c6b616ce57375dd52d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:27:28 +0200 Subject: [PATCH 12/14] Make modules public --- crates/fj-kernel/src/algorithms/approx/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/mod.rs b/crates/fj-kernel/src/algorithms/approx/mod.rs index 68722eae6..d71f96892 100644 --- a/crates/fj-kernel/src/algorithms/approx/mod.rs +++ b/crates/fj-kernel/src/algorithms/approx/mod.rs @@ -1,10 +1,10 @@ //! Approximation of objects -mod curve; -mod cycle; -mod edge; -mod face; -mod tolerance; +pub mod curve; +pub mod cycle; +pub mod edge; +pub mod face; +pub mod tolerance; pub use self::{ cycle::CycleApprox, From 8e0c935553e710ccb4e552d15f2202b285ff060f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:27:49 +0200 Subject: [PATCH 13/14] Remove re-export --- crates/fj-kernel/src/algorithms/approx/face.rs | 2 +- crates/fj-kernel/src/algorithms/approx/mod.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/face.rs b/crates/fj-kernel/src/algorithms/approx/face.rs index 40730cc01..55b7b0586 100644 --- a/crates/fj-kernel/src/algorithms/approx/face.rs +++ b/crates/fj-kernel/src/algorithms/approx/face.rs @@ -8,7 +8,7 @@ use fj_math::Point; use crate::objects::Face; -use super::{Approx, CycleApprox, Tolerance}; +use super::{cycle::CycleApprox, Approx, Tolerance}; impl Approx for &Face { type Approximation = FaceApprox; diff --git a/crates/fj-kernel/src/algorithms/approx/mod.rs b/crates/fj-kernel/src/algorithms/approx/mod.rs index d71f96892..c64934e5f 100644 --- a/crates/fj-kernel/src/algorithms/approx/mod.rs +++ b/crates/fj-kernel/src/algorithms/approx/mod.rs @@ -7,7 +7,6 @@ pub mod face; pub mod tolerance; pub use self::{ - cycle::CycleApprox, face::FaceApprox, tolerance::{InvalidTolerance, Tolerance}, }; From 9ad604e21f8d96fd54464c1b00297779cc872616 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 6 Sep 2022 14:28:07 +0200 Subject: [PATCH 14/14] Remove re-export --- crates/fj-kernel/src/algorithms/approx/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/mod.rs b/crates/fj-kernel/src/algorithms/approx/mod.rs index c64934e5f..cf17774af 100644 --- a/crates/fj-kernel/src/algorithms/approx/mod.rs +++ b/crates/fj-kernel/src/algorithms/approx/mod.rs @@ -6,10 +6,7 @@ pub mod edge; pub mod face; pub mod tolerance; -pub use self::{ - face::FaceApprox, - tolerance::{InvalidTolerance, Tolerance}, -}; +pub use self::tolerance::{InvalidTolerance, Tolerance}; /// Approximate an object pub trait Approx {