From da8b8af392aaa495375a6774b454661a5b4bee98 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Jul 2022 18:30:51 +0200 Subject: [PATCH 1/3] Produce surface coordinates in approximation --- .../fj-kernel/src/algorithms/approx/cycles.rs | 19 ++++++++------ .../fj-kernel/src/algorithms/approx/faces.rs | 25 +++++++++++-------- .../src/algorithms/triangulate/mod.rs | 10 +++++--- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/cycles.rs b/crates/fj-kernel/src/algorithms/approx/cycles.rs index 1b1b5b139..92beb23e0 100644 --- a/crates/fj-kernel/src/algorithms/approx/cycles.rs +++ b/crates/fj-kernel/src/algorithms/approx/cycles.rs @@ -1,6 +1,6 @@ use fj_math::{Point, Segment}; -use crate::objects::Cycle; +use crate::{local::Local, objects::Cycle}; use super::{curves::approx_curve, edges::approx_edge, Tolerance}; @@ -8,7 +8,7 @@ use super::{curves::approx_curve, edges::approx_edge, Tolerance}; #[derive(Debug, Eq, PartialEq, Hash)] pub struct CycleApprox { /// The points that approximate the cycle - pub points: Vec>, + pub points: Vec>>, } impl CycleApprox { @@ -24,13 +24,16 @@ impl CycleApprox { approx_curve(&edge.curve(), tolerance, &mut edge_points); approx_edge(edge.vertices.clone(), &mut edge_points); - points.extend(edge_points); + points.extend(edge_points.into_iter().map(|point| { + let local = + edge.curve.local().point_from_curve_coords(point.local()); + Local::new(local, point.global()) + })); } - let mut points: Vec<_> = - points.into_iter().map(|point| point.global()).collect(); - - points.dedup(); + // Can't just rely on `dedup`, as the conversion from curve coordinates + // could lead to subtly different surface coordinates. + points.dedup_by(|a, b| a.global() == b.global()); Self { points } } @@ -44,7 +47,7 @@ impl CycleApprox { // up, once `array_windows` is stable. let segment = [segment[0], segment[1]]; - segments.push(Segment::from(segment)); + segments.push(Segment::from(segment.map(|point| point.global()))); } segments diff --git a/crates/fj-kernel/src/algorithms/approx/faces.rs b/crates/fj-kernel/src/algorithms/approx/faces.rs index 7f6664c24..9bcefddd0 100644 --- a/crates/fj-kernel/src/algorithms/approx/faces.rs +++ b/crates/fj-kernel/src/algorithms/approx/faces.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use fj_math::Point; -use crate::objects::Face; +use crate::{local::Local, objects::Face}; use super::{CycleApprox, Tolerance}; @@ -13,7 +13,7 @@ pub struct FaceApprox { /// /// These could be actual vertices from the model, points that approximate /// an edge, or points that approximate a face. - pub points: HashSet>, + pub points: HashSet>>, /// Approximation of the exterior cycle pub exterior: CycleApprox, @@ -83,7 +83,10 @@ mod tests { use fj_math::{Point, Scalar}; use map_macro::set; - use crate::objects::{Face, Surface}; + use crate::{ + local::Local, + objects::{Face, Surface}, + }; use super::{CycleApprox, FaceApprox, Tolerance}; @@ -108,14 +111,14 @@ mod tests { .with_interior_polygon([e, f, g, h]) .build(); - let a = a.to_xyz(); - let b = b.to_xyz(); - let c = c.to_xyz(); - let d = d.to_xyz(); - let e = e.to_xyz(); - let f = f.to_xyz(); - let g = g.to_xyz(); - let h = h.to_xyz(); + let a = Local::new(a, a.to_xyz()); + let b = Local::new(b, b.to_xyz()); + let c = Local::new(c, c.to_xyz()); + let d = Local::new(d, d.to_xyz()); + let e = Local::new(e, e.to_xyz()); + let f = Local::new(f, f.to_xyz()); + let g = Local::new(g, g.to_xyz()); + let h = Local::new(h, h.to_xyz()); let approx = FaceApprox::new(&face, tolerance); let expected = FaceApprox { diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 6e4fb012a..997add704 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -31,7 +31,7 @@ pub fn triangulate( .map(|vertex| { // Can't panic, unless the approximation wrongfully // generates points that are not in the surface. - surface.point_to_surface_coords(vertex) + surface.point_to_surface_coords(vertex.global()) }) .collect(); let face_as_polygon = Polygon::new(surface) @@ -39,7 +39,9 @@ pub fn triangulate( |point| { // Can't panic, unless the approximation wrongfully // generates points that are not in the surface. - surface.point_to_surface_coords(point).local() + surface + .point_to_surface_coords(point.global()) + .local() }, )) .with_interiors(approx.interiors.into_iter().map( @@ -48,7 +50,9 @@ pub fn triangulate( // Can't panic, unless the approximation // wrongfully generates points that are not in // the surface. - surface.point_to_surface_coords(point).local() + surface + .point_to_surface_coords(point.global()) + .local() }) }, )); From 3dd54d7d86e6aa88469a4fd8bbbdbd421f7e1b7b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Jul 2022 18:32:51 +0200 Subject: [PATCH 2/3] Remove useless conversions --- .../src/algorithms/triangulate/mod.rs | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 997add704..4feeb0537 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -25,35 +25,21 @@ pub fn triangulate( let surface = brep.surface; let approx = FaceApprox::new(&face, tolerance); - let points: Vec<_> = approx - .points - .into_iter() - .map(|vertex| { - // Can't panic, unless the approximation wrongfully - // generates points that are not in the surface. - surface.point_to_surface_coords(vertex.global()) - }) - .collect(); + let points: Vec<_> = approx.points.into_iter().collect(); let face_as_polygon = Polygon::new(surface) - .with_exterior(approx.exterior.points.into_iter().map( - |point| { - // Can't panic, unless the approximation wrongfully - // generates points that are not in the surface. - surface - .point_to_surface_coords(point.global()) - .local() - }, - )) + .with_exterior( + approx + .exterior + .points + .into_iter() + .map(|point| point.local()), + ) .with_interiors(approx.interiors.into_iter().map( |interior| { - interior.points.into_iter().map(|point| { - // Can't panic, unless the approximation - // wrongfully generates points that are not in - // the surface. - surface - .point_to_surface_coords(point.global()) - .local() - }) + interior + .points + .into_iter() + .map(|point| point.local()) }, )); From 1ef92904b8de5e2fcaeee58f1f4ef21420bc3c9a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Jul 2022 18:54:27 +0200 Subject: [PATCH 3/3] Remove unused code --- crates/fj-kernel/src/objects/curve.rs | 21 ---------- crates/fj-kernel/src/objects/surface.rs | 54 ------------------------- 2 files changed, 75 deletions(-) diff --git a/crates/fj-kernel/src/objects/curve.rs b/crates/fj-kernel/src/objects/curve.rs index ea3e4c553..848c7a3ee 100644 --- a/crates/fj-kernel/src/objects/curve.rs +++ b/crates/fj-kernel/src/objects/curve.rs @@ -47,27 +47,6 @@ impl Curve { } } - /// Convert a point in model coordinates to curve coordinates - /// - /// Projects the point onto the curve before computing curve coordinate. - /// This is done to make this method robust against floating point accuracy - /// issues. - /// - /// Callers are advised to be careful about the points they pass, as the - /// point not being on the curve, intentional or not, will never result in - /// an error. - pub fn point_to_curve_coords( - &self, - point: impl Into>, - ) -> Point<1> { - let point = point.into(); - - match self { - Self::Circle(curve) => curve.point_to_circle_coords(point), - Self::Line(curve) => curve.point_to_line_coords(point), - } - } - /// Convert a point on the curve into model coordinates pub fn point_from_curve_coords( &self, diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index ae5f90d99..6fa770fd3 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -1,7 +1,5 @@ use fj_math::{Line, Point, Transform, Vector}; -use crate::local::Local; - use super::Curve; /// A two-dimensional shape @@ -64,22 +62,6 @@ impl Surface { } } - /// Convert a point in model coordinates to surface coordinates - pub fn point_to_surface_coords( - &self, - point_3d: impl Into>, - ) -> Local> { - let point_3d = point_3d.into(); - - let point_2d = match self { - Self::SweptCurve(surface) => { - surface.point_to_surface_coords(point_3d) - } - }; - - Local::new(point_2d, point_3d) - } - /// Convert a point in surface coordinates to model coordinates pub fn point_from_surface_coords( &self, @@ -131,19 +113,6 @@ impl SweptCurve { self } - /// Convert a point in model coordinates to surface coordinates - pub fn point_to_surface_coords( - &self, - point: impl Into>, - ) -> Point<2> { - let point = point.into(); - - let u = self.curve.point_to_curve_coords(point).t; - let v = self.path_to_line().point_to_line_coords(point).t; - - Point::from([u, v]) - } - /// Convert a point in surface coordinates to model coordinates pub fn point_from_surface_coords( &self, @@ -203,29 +172,6 @@ mod tests { assert_eq!(expected, reversed); } - #[test] - fn point_to_surface_coords() { - let plane = SweptCurve { - curve: Curve::Line(Line { - origin: Point::from([1., 0., 0.]), - direction: Vector::from([0., 2., 0.]), - }), - path: Vector::from([0., 0., 3.]), - }; - - verify(&plane, Point::from([-1., -1.])); - verify(&plane, Point::from([0., 0.])); - verify(&plane, Point::from([1., 1.])); - verify(&plane, Point::from([2., 3.])); - - fn verify(swept: &SweptCurve, surface_point: Point<2>) { - let point = swept.point_from_surface_coords(surface_point); - let result = swept.point_to_surface_coords(point); - - assert_eq!(result, surface_point); - } - } - #[test] fn point_from_surface_coords() { let swept = SweptCurve {