diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index cd943e676..1e3ca504b 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -4,7 +4,7 @@ use fj_math::{Point, Scalar, Vector}; use crate::{ algorithms::intersect::face_point::FacePointIntersection, - objects::{Face, HalfEdge, Vertex}, + objects::{CurveKind, Face, HalfEdge, Vertex}, }; use super::{HorizontalRayToTheRight, Intersect}; @@ -15,19 +15,15 @@ impl Intersect for (&HorizontalRayToTheRight<3>, &Face) { fn intersect(self) -> Option { let (ray, face) = self; - let (plane_origin, plane_direction_1, plane_direction_2) = match face - .surface() - { - crate::objects::Surface::SweptCurve(surface) => match surface.curve - { - crate::objects::CurveKind::Circle(_) => todo!( + let (plane_origin, plane_direction_1, plane_direction_2) = + match face.surface().u() { + CurveKind::Circle(_) => todo!( "Casting a ray against a swept circle is not supported yet" ), - crate::objects::CurveKind::Line(line) => { - (line.origin(), line.direction(), surface.path) + CurveKind::Line(line) => { + (line.origin(), line.direction(), face.surface().v()) } - }, - }; + }; let plane_and_ray_are_parallel = { let plane_normal = plane_direction_1.cross(&plane_direction_2); diff --git a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs index 459e16c2e..9b230fed7 100644 --- a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs @@ -73,15 +73,14 @@ struct PlaneParametric { impl PlaneParametric { pub fn extract_from_surface(surface: &Surface) -> Self { let (line, path) = { - let Surface::SweptCurve(surface) = surface; - let line = match surface.curve { + let line = match surface.u() { CurveKind::Line(line) => line, _ => todo!( "Only plane-plane intersection is currently supported." ), }; - (line, surface.path) + (line, surface.v()) }; Self { diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index 3c233a9aa..cd7178e1d 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -1,6 +1,6 @@ use fj_math::Vector; -use crate::objects::{Curve, GlobalCurve, Surface, SweptCurve}; +use crate::objects::{Curve, GlobalCurve, Surface}; use super::Sweep; @@ -16,9 +16,6 @@ impl Sweep for GlobalCurve { type Swept = Surface; fn sweep(self, path: impl Into>) -> Self::Swept { - Surface::SweptCurve(SweptCurve { - curve: *self.kind(), - path: path.into(), - }) + Surface::new(*self.kind(), path.into()) } } diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 1c44e542f..e7391ab0e 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -2,7 +2,7 @@ use fj_math::{Scalar, Vector}; use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, - objects::{CurveKind, Face, Shell, Surface}, + objects::{CurveKind, Face, Shell}, }; use super::Sweep; @@ -16,16 +16,14 @@ impl Sweep for Face { let mut faces = Vec::new(); let is_negative_sweep = { - let Surface::SweptCurve(surface) = self.surface(); - - let a = match surface.curve { + let a = match self.surface().u() { CurveKind::Circle(_) => todo!( "Sweeping from faces defined in round surfaces is not \ supported" ), CurveKind::Line(line) => line.direction(), }; - let b = surface.path; + let b = self.surface().v(); let normal = a.cross(&b); diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index 02ac8d051..63165586e 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -2,7 +2,7 @@ use fj_math::{Line, Point, Scalar, Vector}; use crate::objects::{ Curve, CurveKind, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Surface, - SurfaceVertex, SweptCurve, Vertex, + SurfaceVertex, Vertex, }; use super::Sweep; @@ -46,13 +46,8 @@ impl Sweep for (Vertex, Surface) { // // Let's make sure that these requirements are met. { - let Surface::SweptCurve(SweptCurve { - curve: surface_curve, - path: surface_path, - }) = surface; - - assert_eq!(vertex.curve().global_form().kind(), &surface_curve); - assert_eq!(path, surface_path); + assert_eq!(vertex.curve().global_form().kind(), &surface.u()); + assert_eq!(path, surface.v()); } // With that out of the way, let's start by creating the `GlobalEdge`, diff --git a/crates/fj-kernel/src/algorithms/transform.rs b/crates/fj-kernel/src/algorithms/transform.rs index ffae0d2d1..fefd8d11e 100644 --- a/crates/fj-kernel/src/algorithms/transform.rs +++ b/crates/fj-kernel/src/algorithms/transform.rs @@ -131,11 +131,10 @@ impl TransformObject for Solid { impl TransformObject for Surface { fn transform(self, transform: &Transform) -> Self { - match self { - Self::SweptCurve(surface) => { - Self::SweptCurve(surface.transform(transform)) - } - } + Self::new( + self.u().transform(transform), + transform.transform_vector(&self.v()), + ) } } diff --git a/crates/fj-kernel/src/objects/curve.rs b/crates/fj-kernel/src/objects/curve.rs index ab864f41d..6e3d7a6dc 100644 --- a/crates/fj-kernel/src/objects/curve.rs +++ b/crates/fj-kernel/src/objects/curve.rs @@ -106,15 +106,6 @@ impl CurveKind { } } - /// Create a new instance that is reversed - #[must_use] - pub fn reverse(self) -> Self { - match self { - Self::Circle(curve) => Self::Circle(curve.reverse()), - Self::Line(curve) => Self::Line(curve.reverse()), - } - } - /// Convert a point on the curve into model coordinates pub fn point_from_curve_coords( &self, diff --git a/crates/fj-kernel/src/objects/mod.rs b/crates/fj-kernel/src/objects/mod.rs index b1b8e5437..a437140d9 100644 --- a/crates/fj-kernel/src/objects/mod.rs +++ b/crates/fj-kernel/src/objects/mod.rs @@ -22,6 +22,6 @@ pub use self::{ shell::Shell, sketch::Sketch, solid::Solid, - surface::{Surface, SweptCurve}, + surface::Surface, vertex::{GlobalVertex, SurfaceVertex, Vertex}, }; diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index 76f1e42de..bfd197ac0 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -1,98 +1,62 @@ -use fj_math::{Line, Point, Transform, Vector}; +use fj_math::{Line, Point, Vector}; use super::CurveKind; /// A two-dimensional shape #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] -pub enum Surface { - /// A swept curve - SweptCurve(SweptCurve), +pub struct Surface { + u: CurveKind<3>, + v: Vector<3>, } impl Surface { + /// Construct a `Surface` from two paths that define its coordinate system + pub fn new(u: CurveKind<3>, v: Vector<3>) -> Self { + Self { u, v } + } + /// Construct a `Surface` that represents the xy-plane pub fn xy_plane() -> Self { - Self::SweptCurve(SweptCurve { - curve: CurveKind::x_axis(), - path: Vector::unit_y(), - }) + Self { + u: CurveKind::x_axis(), + v: Vector::unit_y(), + } } /// Construct a `Surface` that represents the xz-plane pub fn xz_plane() -> Self { - Self::SweptCurve(SweptCurve { - curve: CurveKind::x_axis(), - path: Vector::unit_z(), - }) + Self { + u: CurveKind::x_axis(), + v: Vector::unit_z(), + } } /// Construct a `Surface` that represents the yz-plane pub fn yz_plane() -> Self { - Self::SweptCurve(SweptCurve { - curve: CurveKind::y_axis(), - path: Vector::unit_z(), - }) + Self { + u: CurveKind::y_axis(), + v: Vector::unit_z(), + } } /// Construct a plane from 3 points pub fn plane_from_points(points: [impl Into>; 3]) -> Self { let [a, b, c] = points.map(Into::into); - let curve = CurveKind::Line(Line::from_points([a, b])); - let path = c - a; + let u = CurveKind::Line(Line::from_points([a, b])); + let v = c - a; - Self::SweptCurve(SweptCurve { curve, path }) + Self { u, v } } - /// Convert a point in surface coordinates to model coordinates - pub fn point_from_surface_coords( - &self, - point: impl Into>, - ) -> Point<3> { - match self { - Self::SweptCurve(surface) => { - surface.point_from_surface_coords(point) - } - } + /// Access the path that defines the u-coordinate of this surface + pub fn u(&self) -> CurveKind<3> { + self.u } - /// Convert a vector in surface coordinates to model coordinates - pub fn vector_from_surface_coords( - &self, - vector: impl Into>, - ) -> Vector<3> { - match self { - Self::SweptCurve(surface) => { - surface.vector_from_surface_coords(vector) - } - } - } -} - -/// A surface that was swept from a curve -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] -pub struct SweptCurve { - /// The curve that this surface was swept from - pub curve: CurveKind<3>, - - /// The path that the curve was swept along - pub path: Vector<3>, -} - -impl SweptCurve { - /// Create a new instance that is reversed - #[must_use] - pub fn reverse(mut self) -> Self { - self.path = -self.path; - self - } - - /// Transform the surface - #[must_use] - pub fn transform(mut self, transform: &Transform) -> Self { - self.curve = self.curve.transform(transform); - self.path = transform.transform_vector(&self.path); - self + /// Access the path that defines the v-coordinate of this surface + pub fn v(&self) -> Vector<3> { + self.v } /// Convert a point in surface coordinates to model coordinates @@ -101,7 +65,7 @@ impl SweptCurve { point: impl Into>, ) -> Point<3> { let point = point.into(); - self.curve.point_from_curve_coords([point.u]) + self.u.point_from_curve_coords([point.u]) + self.path_to_line().vector_from_line_coords([point.v]) } @@ -111,12 +75,12 @@ impl SweptCurve { vector: impl Into>, ) -> Vector<3> { let vector = vector.into(); - self.curve.vector_from_curve_coords([vector.u]) + self.u.vector_from_curve_coords([vector.u]) + self.path_to_line().vector_from_line_coords([vector.v]) } fn path_to_line(&self) -> Line<3> { - Line::from_origin_and_direction(self.curve.origin(), self.path) + Line::from_origin_and_direction(self.u.origin(), self.v) } } @@ -127,38 +91,16 @@ mod tests { use crate::objects::CurveKind; - use super::SweptCurve; - - #[test] - fn reverse() { - let original = SweptCurve { - curve: CurveKind::Line(Line::from_origin_and_direction( - Point::from([1., 0., 0.]), - Vector::from([0., 2., 0.]), - )), - path: Vector::from([0., 0., 3.]), - }; - - let reversed = original.reverse(); - - let expected = SweptCurve { - curve: CurveKind::Line(Line::from_origin_and_direction( - Point::from([1., 0., 0.]), - Vector::from([0., 2., 0.]), - )), - path: Vector::from([0., 0., -3.]), - }; - assert_eq!(expected, reversed); - } + use super::Surface; #[test] fn point_from_surface_coords() { - let swept = SweptCurve { - curve: CurveKind::Line(Line::from_origin_and_direction( + let swept = Surface { + u: CurveKind::Line(Line::from_origin_and_direction( Point::from([1., 1., 1.]), Vector::from([0., 2., 0.]), )), - path: Vector::from([0., 0., 2.]), + v: Vector::from([0., 0., 2.]), }; assert_eq!( @@ -169,12 +111,12 @@ mod tests { #[test] fn vector_from_surface_coords() { - let swept = SweptCurve { - curve: CurveKind::Line(Line::from_origin_and_direction( + let swept = Surface { + u: CurveKind::Line(Line::from_origin_and_direction( Point::from([1., 0., 0.]), Vector::from([0., 2., 0.]), )), - path: Vector::from([0., 0., 2.]), + v: Vector::from([0., 0., 2.]), }; assert_eq!(