From 9277037ba94a9da1b457fb1955a9e4ad0eac1c10 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:52:17 +0200 Subject: [PATCH 1/3] Move curve approximation test suite --- crates/fj-core/src/algorithms/approx/curve.rs | 115 ++++++++++++++++++ crates/fj-core/src/algorithms/approx/edge.rs | 115 ------------------ 2 files changed, 115 insertions(+), 115 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 71d01d6ff..41ebc8c09 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -169,3 +169,118 @@ impl CurveApproxCache { .unwrap_or(approx) } } + +#[cfg(test)] +mod tests { + use std::{f64::consts::TAU, ops::Deref}; + + use pretty_assertions::assert_eq; + + use crate::{ + algorithms::approx::{Approx, ApproxPoint}, + geometry::{CurveBoundary, GlobalPath, SurfaceGeometry}, + objects::{HalfEdge, Surface}, + operations::BuildHalfEdge, + services::Services, + }; + + #[test] + fn approx_line_on_flat_surface() { + let mut services = Services::new(); + + let surface = services.objects.surfaces.xz_plane(); + let edge = + HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services); + + let tolerance = 1.; + let approx = (&edge, surface.deref()).approx(tolerance); + + let expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + assert_eq!(approx.points, expected_approx); + } + + #[test] + fn approx_line_on_curved_surface_but_not_along_curve() { + let mut services = Services::new(); + + let surface = Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 0., 1.].into(), + }); + let edge = + HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services); + + let tolerance = 1.; + let approx = (&edge, &surface).approx(tolerance); + + let expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + assert_eq!(approx.points, expected_approx); + } + + #[test] + fn approx_line_on_curved_surface_along_curve() { + let mut services = Services::new(); + + let path = GlobalPath::circle_from_radius(1.); + let boundary = CurveBoundary::from([[0.], [TAU]]); + + let surface = Surface::new(SurfaceGeometry { + u: path, + v: [0., 0., 1.].into(), + }); + let edge = HalfEdge::line_segment( + [[0., 1.], [TAU, 1.]], + Some(boundary.inner), + &mut services, + ); + + let tolerance = 1.; + let approx = (&edge, &surface).approx(tolerance); + + let mut expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + expected_approx.extend( + (path, boundary).approx(tolerance).into_iter().map( + |(point_local, _)| { + let point_surface = + edge.path().point_from_path_coords(point_local); + ApproxPoint::from_surface_point(point_surface, &surface) + }, + ), + ); + assert_eq!(approx.points, expected_approx); + } + + #[test] + fn approx_circle_on_flat_surface() { + let mut services = Services::new(); + + let surface = services.objects.surfaces.xz_plane(); + let edge = HalfEdge::circle([0., 0.], 1., &mut services); + + let tolerance = 1.; + let approx = (&edge, surface.deref()).approx(tolerance); + + let mut expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + expected_approx.extend( + (&edge.path(), CurveBoundary::from([[0.], [TAU]])) + .approx(tolerance) + .into_iter() + .map(|(_, point_surface)| { + ApproxPoint::from_surface_point(point_surface, &surface) + }), + ); + assert_eq!(approx.points, expected_approx); + } +} diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index a36433637..c9303b25d 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -72,118 +72,3 @@ pub struct HalfEdgeApproxCache { start_position: VertexApproxCache, curve: CurveApproxCache, } - -#[cfg(test)] -mod tests { - use std::{f64::consts::TAU, ops::Deref}; - - use pretty_assertions::assert_eq; - - use crate::{ - algorithms::approx::{Approx, ApproxPoint}, - geometry::{CurveBoundary, GlobalPath, SurfaceGeometry}, - objects::{HalfEdge, Surface}, - operations::BuildHalfEdge, - services::Services, - }; - - #[test] - fn approx_line_on_flat_surface() { - let mut services = Services::new(); - - let surface = services.objects.surfaces.xz_plane(); - let edge = - HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services); - - let tolerance = 1.; - let approx = (&edge, surface.deref()).approx(tolerance); - - let expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - assert_eq!(approx.points, expected_approx); - } - - #[test] - fn approx_line_on_curved_surface_but_not_along_curve() { - let mut services = Services::new(); - - let surface = Surface::new(SurfaceGeometry { - u: GlobalPath::circle_from_radius(1.), - v: [0., 0., 1.].into(), - }); - let edge = - HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services); - - let tolerance = 1.; - let approx = (&edge, &surface).approx(tolerance); - - let expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - assert_eq!(approx.points, expected_approx); - } - - #[test] - fn approx_line_on_curved_surface_along_curve() { - let mut services = Services::new(); - - let path = GlobalPath::circle_from_radius(1.); - let boundary = CurveBoundary::from([[0.], [TAU]]); - - let surface = Surface::new(SurfaceGeometry { - u: path, - v: [0., 0., 1.].into(), - }); - let edge = HalfEdge::line_segment( - [[0., 1.], [TAU, 1.]], - Some(boundary.inner), - &mut services, - ); - - let tolerance = 1.; - let approx = (&edge, &surface).approx(tolerance); - - let mut expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - expected_approx.extend( - (path, boundary).approx(tolerance).into_iter().map( - |(point_local, _)| { - let point_surface = - edge.path().point_from_path_coords(point_local); - ApproxPoint::from_surface_point(point_surface, &surface) - }, - ), - ); - assert_eq!(approx.points, expected_approx); - } - - #[test] - fn approx_circle_on_flat_surface() { - let mut services = Services::new(); - - let surface = services.objects.surfaces.xz_plane(); - let edge = HalfEdge::circle([0., 0.], 1., &mut services); - - let tolerance = 1.; - let approx = (&edge, surface.deref()).approx(tolerance); - - let mut expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - expected_approx.extend( - (&edge.path(), CurveBoundary::from([[0.], [TAU]])) - .approx(tolerance) - .into_iter() - .map(|(_, point_surface)| { - ApproxPoint::from_surface_point(point_surface, &surface) - }), - ); - assert_eq!(approx.points, expected_approx); - } -} From 17704c0e4404fe1c5b0ff342053cb120d7fe6601 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 24 Oct 2023 09:39:45 +0200 Subject: [PATCH 2/3] Rename variable to prepare for follow-on change --- crates/fj-core/src/algorithms/approx/curve.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 41ebc8c09..517fe8f76 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -227,11 +227,11 @@ mod tests { fn approx_line_on_curved_surface_along_curve() { let mut services = Services::new(); - let path = GlobalPath::circle_from_radius(1.); + let global_path = GlobalPath::circle_from_radius(1.); let boundary = CurveBoundary::from([[0.], [TAU]]); let surface = Surface::new(SurfaceGeometry { - u: path, + u: global_path, v: [0., 0., 1.].into(), }); let edge = HalfEdge::line_segment( @@ -248,7 +248,7 @@ mod tests { ApproxPoint::from_surface_point(point_surface, &surface) }]; expected_approx.extend( - (path, boundary).approx(tolerance).into_iter().map( + (global_path, boundary).approx(tolerance).into_iter().map( |(point_local, _)| { let point_surface = edge.path().point_from_path_coords(point_local); From 52a6bd4b3c04fcbf015fc61b625212604364c103 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:56:40 +0200 Subject: [PATCH 3/3] Simplify test suite The test suite was previously written against edge approximation, but was actually testing the implementation details of the curve approximation. This resulted in some complexity that wasn't necessary. The test suite now specifically targets curve approximation. --- crates/fj-core/src/algorithms/approx/curve.rs | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 517fe8f76..bf22f66bd 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -178,9 +178,9 @@ mod tests { use crate::{ algorithms::approx::{Approx, ApproxPoint}, - geometry::{CurveBoundary, GlobalPath, SurfaceGeometry}, - objects::{HalfEdge, Surface}, - operations::BuildHalfEdge, + geometry::{CurveBoundary, GlobalPath, SurfaceGeometry, SurfacePath}, + objects::{Curve, Surface}, + operations::Insert, services::Services, }; @@ -188,39 +188,37 @@ mod tests { fn approx_line_on_flat_surface() { let mut services = Services::new(); + let curve = Curve::new().insert(&mut services); + let (surface_path, boundary) = + SurfacePath::line_from_points([[1., 1.], [2., 1.]]); + let boundary = CurveBoundary::from(boundary); let surface = services.objects.surfaces.xz_plane(); - let edge = - HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services); let tolerance = 1.; - let approx = (&edge, surface.deref()).approx(tolerance); + let approx = + (&curve, surface_path, surface.deref(), boundary).approx(tolerance); - let expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - assert_eq!(approx.points, expected_approx); + assert_eq!(approx.points, vec![]); } #[test] fn approx_line_on_curved_surface_but_not_along_curve() { let mut services = Services::new(); + let curve = Curve::new().insert(&mut services); + let (surface_path, boundary) = + SurfacePath::line_from_points([[1., 1.], [2., 1.]]); + let boundary = CurveBoundary::from(boundary); let surface = Surface::new(SurfaceGeometry { u: GlobalPath::circle_from_radius(1.), v: [0., 0., 1.].into(), }); - let edge = - HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services); let tolerance = 1.; - let approx = (&edge, &surface).approx(tolerance); + let approx = + (&curve, surface_path, &surface, boundary).approx(tolerance); - let expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - assert_eq!(approx.points, expected_approx); + assert_eq!(approx.points, vec![]); } #[test] @@ -228,34 +226,32 @@ mod tests { let mut services = Services::new(); let global_path = GlobalPath::circle_from_radius(1.); + let curve = Curve::new().insert(&mut services); + let surface_path = SurfacePath::line_from_points_with_coords([ + ([0.], [0., 1.]), + ([TAU], [TAU, 1.]), + ]); let boundary = CurveBoundary::from([[0.], [TAU]]); - let surface = Surface::new(SurfaceGeometry { u: global_path, v: [0., 0., 1.].into(), }); - let edge = HalfEdge::line_segment( - [[0., 1.], [TAU, 1.]], - Some(boundary.inner), - &mut services, - ); let tolerance = 1.; - let approx = (&edge, &surface).approx(tolerance); - - let mut expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - expected_approx.extend( - (global_path, boundary).approx(tolerance).into_iter().map( - |(point_local, _)| { - let point_surface = - edge.path().point_from_path_coords(point_local); - ApproxPoint::from_surface_point(point_surface, &surface) - }, - ), - ); + let approx = + (&curve, surface_path, &surface, boundary).approx(tolerance); + + let expected_approx = (global_path, boundary) + .approx(tolerance) + .into_iter() + .map(|(point_local, _)| { + let point_surface = + surface_path.point_from_path_coords(point_local); + let point_global = + surface.geometry().point_from_surface_coords(point_surface); + ApproxPoint::new(point_local, point_global) + }) + .collect::>(); assert_eq!(approx.points, expected_approx); } @@ -263,24 +259,27 @@ mod tests { fn approx_circle_on_flat_surface() { let mut services = Services::new(); + let curve = Curve::new().insert(&mut services); + let surface_path = + SurfacePath::circle_from_center_and_radius([0., 0.], 1.); + let boundary = CurveBoundary::from([[0.], [TAU]]); let surface = services.objects.surfaces.xz_plane(); - let edge = HalfEdge::circle([0., 0.], 1., &mut services); let tolerance = 1.; - let approx = (&edge, surface.deref()).approx(tolerance); - - let mut expected_approx = vec![{ - let point_surface = edge.start_position(); - ApproxPoint::from_surface_point(point_surface, &surface) - }]; - expected_approx.extend( - (&edge.path(), CurveBoundary::from([[0.], [TAU]])) - .approx(tolerance) - .into_iter() - .map(|(_, point_surface)| { - ApproxPoint::from_surface_point(point_surface, &surface) - }), - ); + let approx = + (&curve, surface_path, surface.deref(), boundary).approx(tolerance); + + let expected_approx = (&surface_path, boundary) + .approx(tolerance) + .into_iter() + .map(|(point_local, _)| { + let point_surface = + surface_path.point_from_path_coords(point_local); + let point_global = + surface.geometry().point_from_surface_coords(point_surface); + ApproxPoint::new(point_local, point_global) + }) + .collect::>(); assert_eq!(approx.points, expected_approx); } }