From d40ca5547cf205d012b36f22f48224cc20f0aaf5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:12:21 +0100 Subject: [PATCH 01/17] Move `path` to new `geometry` module I'm about to add new types that are similar to the path types, and having them in a common parent module makes sense. `geometry` isn't the greatest name for that new module (it's not like the things outside of it aren't geometry), but it's what I can come up with right now. --- crates/fj-kernel/src/algorithms/approx/curve.rs | 4 ++-- crates/fj-kernel/src/algorithms/approx/path.rs | 2 +- crates/fj-kernel/src/algorithms/intersect/curve_edge.rs | 2 +- crates/fj-kernel/src/algorithms/intersect/ray_edge.rs | 2 +- crates/fj-kernel/src/algorithms/intersect/ray_face.rs | 2 +- crates/fj-kernel/src/algorithms/intersect/surface_surface.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/curve.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/edge.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/face.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/vertex.rs | 2 +- crates/fj-kernel/src/builder/curve.rs | 2 +- crates/fj-kernel/src/geometry/mod.rs | 3 +++ crates/fj-kernel/src/{ => geometry}/path.rs | 0 crates/fj-kernel/src/lib.rs | 2 +- crates/fj-kernel/src/objects/curve.rs | 2 +- crates/fj-kernel/src/objects/cycle.rs | 2 +- crates/fj-kernel/src/objects/mod.rs | 2 +- crates/fj-kernel/src/objects/surface.rs | 4 ++-- crates/fj-kernel/src/partial/maybe_partial.rs | 2 +- crates/fj-kernel/src/partial/objects/curve.rs | 2 +- 20 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 crates/fj-kernel/src/geometry/mod.rs rename crates/fj-kernel/src/{ => geometry}/path.rs (100%) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 870925bcc..e52bb05e2 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -12,8 +12,8 @@ use std::collections::BTreeMap; use crate::{ + geometry::path::{GlobalPath, SurfacePath}, objects::{Curve, GlobalCurve}, - path::{GlobalPath, SurfacePath}, storage::{Handle, ObjectId}, }; @@ -198,10 +198,10 @@ mod tests { use crate::{ algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint}, builder::CurveBuilder, + geometry::path::GlobalPath, insert::Insert, objects::{Objects, Surface}, partial::PartialCurve, - path::GlobalPath, }; use super::CurveApprox; diff --git a/crates/fj-kernel/src/algorithms/approx/path.rs b/crates/fj-kernel/src/algorithms/approx/path.rs index 1ce214b79..85335fa76 100644 --- a/crates/fj-kernel/src/algorithms/approx/path.rs +++ b/crates/fj-kernel/src/algorithms/approx/path.rs @@ -32,7 +32,7 @@ use std::iter; use fj_math::{Circle, Point, Scalar, Sign}; -use crate::path::{GlobalPath, SurfacePath}; +use crate::geometry::path::{GlobalPath, SurfacePath}; use super::{Approx, Tolerance}; diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index ac53e7fff..0ebeafcaf 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -1,8 +1,8 @@ use fj_math::{Point, Segment}; use crate::{ + geometry::path::SurfacePath, objects::{Curve, HalfEdge}, - path::SurfacePath, }; use super::LineSegmentIntersection; diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_edge.rs b/crates/fj-kernel/src/algorithms/intersect/ray_edge.rs index b3a79f44d..962fed93b 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_edge.rs @@ -4,8 +4,8 @@ use fj_math::Segment; use crate::{ algorithms::intersect::{HorizontalRayToTheRight, Intersect}, + geometry::path::SurfacePath, objects::HalfEdge, - path::SurfacePath, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index f5526972f..290d00f63 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -4,8 +4,8 @@ use fj_math::{Plane, Point, Scalar}; use crate::{ algorithms::intersect::face_point::FacePointIntersection, + geometry::path::GlobalPath, objects::{Face, HalfEdge, Vertex}, - path::GlobalPath, storage::Handle, }; diff --git a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs index 43ed585d6..28d736c85 100644 --- a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs @@ -2,8 +2,8 @@ use fj_interop::ext::ArrayExt; use fj_math::{Line, Plane, Point, Scalar}; use crate::{ + geometry::path::{GlobalPath, SurfacePath}, objects::{Curve, GlobalCurve, Objects, Surface}, - path::{GlobalPath, SurfacePath}, storage::Handle, validate::ValidationError, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index 76ec79719..48e8a89fe 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -1,8 +1,8 @@ use fj_math::{Circle, Line, Vector}; use crate::{ + geometry::path::{GlobalPath, SurfacePath}, objects::{Curve, Objects, Surface}, - path::{GlobalPath, SurfacePath}, storage::Handle, validate::ValidationError, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 901533c47..3d1489d24 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -4,13 +4,13 @@ use iter_fixed::IntoIteratorFixed; use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, + geometry::path::SurfacePath, insert::Insert, objects::{ Curve, Cycle, Face, GlobalEdge, HalfEdge, Objects, SurfaceVertex, Vertex, }, partial::HasPartial, - path::SurfacePath, storage::Handle, validate::ValidationError, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index cc99370b6..6bd851aae 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -2,8 +2,8 @@ use fj_math::{Scalar, Vector}; use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, + geometry::path::GlobalPath, objects::{Face, Objects, Shell}, - path::GlobalPath, storage::Handle, validate::ValidationError, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index e07754a62..d5706a1db 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -3,11 +3,11 @@ use fj_math::{Line, Point, Scalar, Vector}; use try_insert_ext::EntryInsertExt; use crate::{ + geometry::path::SurfacePath, objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, Surface, SurfaceVertex, Vertex, }, - path::SurfacePath, storage::Handle, validate::ValidationError, }; diff --git a/crates/fj-kernel/src/builder/curve.rs b/crates/fj-kernel/src/builder/curve.rs index 1380bfff8..85d71a63c 100644 --- a/crates/fj-kernel/src/builder/curve.rs +++ b/crates/fj-kernel/src/builder/curve.rs @@ -1,6 +1,6 @@ use fj_math::{Point, Scalar, Vector}; -use crate::{partial::PartialCurve, path::SurfacePath}; +use crate::{geometry::path::SurfacePath, partial::PartialCurve}; /// Builder API for [`PartialCurve`] pub trait CurveBuilder { diff --git a/crates/fj-kernel/src/geometry/mod.rs b/crates/fj-kernel/src/geometry/mod.rs new file mode 100644 index 000000000..4c5965dc7 --- /dev/null +++ b/crates/fj-kernel/src/geometry/mod.rs @@ -0,0 +1,3 @@ +//! Types that are tied to objects, but aren't objects themselves + +pub mod path; diff --git a/crates/fj-kernel/src/path.rs b/crates/fj-kernel/src/geometry/path.rs similarity index 100% rename from crates/fj-kernel/src/path.rs rename to crates/fj-kernel/src/geometry/path.rs diff --git a/crates/fj-kernel/src/lib.rs b/crates/fj-kernel/src/lib.rs index 607c7b11c..87091d3a1 100644 --- a/crates/fj-kernel/src/lib.rs +++ b/crates/fj-kernel/src/lib.rs @@ -89,10 +89,10 @@ pub mod algorithms; pub mod builder; +pub mod geometry; pub mod insert; pub mod iter; pub mod objects; pub mod partial; -pub mod path; pub mod storage; pub mod validate; diff --git a/crates/fj-kernel/src/objects/curve.rs b/crates/fj-kernel/src/objects/curve.rs index 54837aa5f..2d1b439ef 100644 --- a/crates/fj-kernel/src/objects/curve.rs +++ b/crates/fj-kernel/src/objects/curve.rs @@ -1,5 +1,5 @@ use crate::{ - path::SurfacePath, + geometry::path::SurfacePath, storage::{Handle, HandleWrapper}, }; diff --git a/crates/fj-kernel/src/objects/cycle.rs b/crates/fj-kernel/src/objects/cycle.rs index 412f07b50..91633ef83 100644 --- a/crates/fj-kernel/src/objects/cycle.rs +++ b/crates/fj-kernel/src/objects/cycle.rs @@ -3,7 +3,7 @@ use std::slice; use fj_interop::ext::SliceExt; use fj_math::{Scalar, Winding}; -use crate::{path::SurfacePath, storage::Handle}; +use crate::{geometry::path::SurfacePath, storage::Handle}; use super::{HalfEdge, Surface}; diff --git a/crates/fj-kernel/src/objects/mod.rs b/crates/fj-kernel/src/objects/mod.rs index d0406c0c9..9ad85435f 100644 --- a/crates/fj-kernel/src/objects/mod.rs +++ b/crates/fj-kernel/src/objects/mod.rs @@ -100,7 +100,7 @@ use std::convert::Infallible; use fj_math::Vector; use crate::{ - path::GlobalPath, + geometry::path::GlobalPath, storage::{Handle, Store}, validate::{ CycleValidationError, FaceValidationError, HalfEdgeValidationError, diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index 6da597626..bc17758de 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -1,6 +1,6 @@ use fj_math::{Line, Point, Vector}; -use crate::path::GlobalPath; +use crate::geometry::path::GlobalPath; /// A two-dimensional shape #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] @@ -66,7 +66,7 @@ mod tests { use fj_math::{Line, Point, Vector}; use pretty_assertions::assert_eq; - use crate::path::GlobalPath; + use crate::geometry::path::GlobalPath; use super::Surface; diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 0fef15070..64a9aa1d8 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -1,12 +1,12 @@ use fj_math::Point; use crate::{ + geometry::path::SurfacePath, insert::Insert, objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, Surface, SurfaceVertex, Vertex, }, - path::SurfacePath, storage::Handle, validate::{Validate, ValidationError}, }; diff --git a/crates/fj-kernel/src/partial/objects/curve.rs b/crates/fj-kernel/src/partial/objects/curve.rs index f5670e27a..a82a7af2f 100644 --- a/crates/fj-kernel/src/partial/objects/curve.rs +++ b/crates/fj-kernel/src/partial/objects/curve.rs @@ -1,7 +1,7 @@ use crate::{ + geometry::path::SurfacePath, objects::{Curve, GlobalCurve, Objects, Surface}, partial::{MaybePartial, MergeWith, Mergeable}, - path::SurfacePath, storage::Handle, validate::ValidationError, }; From 72efbc66ccd6d64ae4d3dccf8ca5c61d1ed35ab7 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:20:40 +0100 Subject: [PATCH 02/17] Add `SurfaceGeometry` This is only the start of this particular refactoring. Eventually, all the math-y parts of `Surface` will live in `SurfaceGeometry`. This has the advantage of decoupling those math-y parts from the existence of a `Surface`, which means they can be used as part of a hypothetical `PartialSurface`. --- crates/fj-kernel/src/geometry/mod.rs | 1 + crates/fj-kernel/src/geometry/surface.rs | 15 +++++++ crates/fj-kernel/src/objects/surface.rs | 53 ++++++++++++++---------- 3 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 crates/fj-kernel/src/geometry/surface.rs diff --git a/crates/fj-kernel/src/geometry/mod.rs b/crates/fj-kernel/src/geometry/mod.rs index 4c5965dc7..654a3c108 100644 --- a/crates/fj-kernel/src/geometry/mod.rs +++ b/crates/fj-kernel/src/geometry/mod.rs @@ -1,3 +1,4 @@ //! Types that are tied to objects, but aren't objects themselves pub mod path; +pub mod surface; diff --git a/crates/fj-kernel/src/geometry/surface.rs b/crates/fj-kernel/src/geometry/surface.rs new file mode 100644 index 000000000..53281be62 --- /dev/null +++ b/crates/fj-kernel/src/geometry/surface.rs @@ -0,0 +1,15 @@ +//! The geometry that defines a surface + +use fj_math::Vector; + +use super::path::GlobalPath; + +/// The geometry that defines a surface +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct SurfaceGeometry { + /// The u-axis of the surface + pub u: GlobalPath, + + /// The v-axis of the surface + pub v: Vector<3>, +} diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index bc17758de..7be2d79e1 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -1,19 +1,21 @@ use fj_math::{Line, Point, Vector}; -use crate::geometry::path::GlobalPath; +use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry}; /// A two-dimensional shape #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct Surface { - u: GlobalPath, - v: Vector<3>, + geometry: SurfaceGeometry, } impl Surface { /// Construct a `Surface` from two paths that define its coordinate system pub fn new(u: GlobalPath, v: impl Into>) -> Self { let v = v.into(); - Self { u, v } + + Self { + geometry: SurfaceGeometry { u, v }, + } } /// Construct a plane from 3 points @@ -23,17 +25,19 @@ impl Surface { let u = GlobalPath::Line(Line::from_points([a, b])); let v = c - a; - Self { u, v } + Self { + geometry: SurfaceGeometry { u, v }, + } } /// Access the path that defines the u-coordinate of this surface pub fn u(&self) -> GlobalPath { - self.u + self.geometry.u } /// Access the path that defines the v-coordinate of this surface pub fn v(&self) -> Vector<3> { - self.v + self.geometry.v } /// Convert a point in surface coordinates to model coordinates @@ -42,7 +46,7 @@ impl Surface { point: impl Into>, ) -> Point<3> { let point = point.into(); - self.u.point_from_path_coords([point.u]) + self.geometry.u.point_from_path_coords([point.u]) + self.path_to_line().vector_from_line_coords([point.v]) } @@ -52,12 +56,15 @@ impl Surface { vector: impl Into>, ) -> Vector<3> { let vector = vector.into(); - self.u.vector_from_path_coords([vector.u]) + self.geometry.u.vector_from_path_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.u.origin(), self.v) + Line::from_origin_and_direction( + self.geometry.u.origin(), + self.geometry.v, + ) } } @@ -66,18 +73,20 @@ mod tests { use fj_math::{Line, Point, Vector}; use pretty_assertions::assert_eq; - use crate::geometry::path::GlobalPath; + use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry}; use super::Surface; #[test] fn point_from_surface_coords() { let swept = Surface { - u: GlobalPath::Line(Line::from_origin_and_direction( - Point::from([1., 1., 1.]), - Vector::from([0., 2., 0.]), - )), - v: Vector::from([0., 0., 2.]), + geometry: SurfaceGeometry { + u: GlobalPath::Line(Line::from_origin_and_direction( + Point::from([1., 1., 1.]), + Vector::from([0., 2., 0.]), + )), + v: Vector::from([0., 0., 2.]), + }, }; assert_eq!( @@ -89,11 +98,13 @@ mod tests { #[test] fn vector_from_surface_coords() { let swept = Surface { - u: GlobalPath::Line(Line::from_origin_and_direction( - Point::from([1., 0., 0.]), - Vector::from([0., 2., 0.]), - )), - v: Vector::from([0., 0., 2.]), + geometry: SurfaceGeometry { + u: GlobalPath::Line(Line::from_origin_and_direction( + Point::from([1., 0., 0.]), + Vector::from([0., 2., 0.]), + )), + v: Vector::from([0., 0., 2.]), + }, }; assert_eq!( From b4f1e15b20e208af10d3c382b4812103d452a4e0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:23:50 +0100 Subject: [PATCH 03/17] Update variable names --- crates/fj-kernel/src/objects/surface.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index 7be2d79e1..b905cf221 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -79,7 +79,7 @@ mod tests { #[test] fn point_from_surface_coords() { - let swept = Surface { + let surface = Surface { geometry: SurfaceGeometry { u: GlobalPath::Line(Line::from_origin_and_direction( Point::from([1., 1., 1.]), @@ -90,14 +90,14 @@ mod tests { }; assert_eq!( - swept.point_from_surface_coords([2., 4.]), + surface.point_from_surface_coords([2., 4.]), Point::from([1., 5., 9.]), ); } #[test] fn vector_from_surface_coords() { - let swept = Surface { + let surface = Surface { geometry: SurfaceGeometry { u: GlobalPath::Line(Line::from_origin_and_direction( Point::from([1., 0., 0.]), @@ -108,7 +108,7 @@ mod tests { }; assert_eq!( - swept.vector_from_surface_coords([2., 4.]), + surface.vector_from_surface_coords([2., 4.]), Vector::from([0., 4., 8.]), ); } From 5cacbd6cea44f4467e5f44fdd65905e1a1743eb8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:25:30 +0100 Subject: [PATCH 04/17] Add `Surface::geometry` --- crates/fj-kernel/src/objects/surface.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index b905cf221..12f49f5c8 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -30,6 +30,11 @@ impl Surface { } } + /// Access the surface's geometry + pub fn geometry(&self) -> SurfaceGeometry { + self.geometry + } + /// Access the path that defines the u-coordinate of this surface pub fn u(&self) -> GlobalPath { self.geometry.u From 18f5d46a5f8cfeaf998c6b0f380fcaef26fb039e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:27:40 +0100 Subject: [PATCH 05/17] Move coordinate conversion to `SurfaceGeometry` --- .../fj-kernel/src/algorithms/approx/curve.rs | 15 ++-- .../fj-kernel/src/algorithms/sweep/curve.rs | 28 +++++-- .../src/algorithms/triangulate/mod.rs | 22 +++--- crates/fj-kernel/src/builder/vertex.rs | 4 +- crates/fj-kernel/src/geometry/surface.rs | 68 ++++++++++++++++- crates/fj-kernel/src/objects/surface.rs | 73 ------------------- crates/fj-kernel/src/validate/vertex.rs | 1 + 7 files changed, 112 insertions(+), 99 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index e52bb05e2..03981062f 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -90,6 +90,7 @@ fn approx_global_curve( let point_global = curve .surface() + .geometry() .point_from_surface_coords(point_surface); (point_curve, point_global) }) @@ -108,8 +109,10 @@ fn approx_global_curve( for (u, _) in approx_u { let t = (u.t - line.origin().u) / line.direction().u; let point_surface = curve.path().point_from_path_coords([t]); - let point_global = - curve.surface().point_from_surface_coords(point_surface); + let point_global = curve + .surface() + .geometry() + .point_from_surface_coords(point_surface); points.push((u, point_global)); } @@ -276,7 +279,7 @@ mod tests { let point_surface = curve.path().point_from_path_coords(point_local); let point_global = - surface.point_from_surface_coords(point_surface); + surface.geometry().point_from_surface_coords(point_surface); ApproxPoint::new(point_surface, point_global) }) .collect::>(); @@ -306,8 +309,10 @@ mod tests { .approx(tolerance) .into_iter() .map(|(_, point_surface)| { - let point_global = - curve.surface().point_from_surface_coords(point_surface); + let point_global = curve + .surface() + .geometry() + .point_from_surface_coords(point_surface); ApproxPoint::new(point_surface, point_global) }) .collect::>(); diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index 48e8a89fe..e2237912c 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -44,20 +44,32 @@ impl Sweep for Handle { let u = match self.path() { SurfacePath::Circle(circle) => { - let center = - self.surface().point_from_surface_coords(circle.center()); - let a = self.surface().vector_from_surface_coords(circle.a()); - let b = self.surface().vector_from_surface_coords(circle.b()); + let center = self + .surface() + .geometry() + .point_from_surface_coords(circle.center()); + let a = self + .surface() + .geometry() + .vector_from_surface_coords(circle.a()); + let b = self + .surface() + .geometry() + .vector_from_surface_coords(circle.b()); let circle = Circle::new(center, a, b); GlobalPath::Circle(circle) } SurfacePath::Line(line) => { - let origin = - self.surface().point_from_surface_coords(line.origin()); - let direction = - self.surface().vector_from_surface_coords(line.direction()); + let origin = self + .surface() + .geometry() + .point_from_surface_coords(line.origin()); + let direction = self + .surface() + .geometry() + .vector_from_surface_coords(line.direction()); let line = Line::from_origin_and_direction(origin, direction); diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index a1a0ebe50..a6ade6f9b 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -148,12 +148,12 @@ mod tests { let triangles = triangulate(face)?; - let a = surface.point_from_surface_coords(a); - let b = surface.point_from_surface_coords(b); - let e = surface.point_from_surface_coords(e); - let f = surface.point_from_surface_coords(f); - let g = surface.point_from_surface_coords(g); - let h = surface.point_from_surface_coords(h); + let a = surface.geometry().point_from_surface_coords(a); + let b = surface.geometry().point_from_surface_coords(b); + let e = surface.geometry().point_from_surface_coords(e); + let f = surface.geometry().point_from_surface_coords(f); + let g = surface.geometry().point_from_surface_coords(g); + let h = surface.geometry().point_from_surface_coords(h); // Let's test that some correct triangles are present. We don't need to // test them all. @@ -209,11 +209,11 @@ mod tests { let triangles = triangulate(face)?; - let a3 = surface.point_from_surface_coords(a); - let b3 = surface.point_from_surface_coords(b); - let c3 = surface.point_from_surface_coords(c); - let d3 = surface.point_from_surface_coords(d); - let e3 = surface.point_from_surface_coords(e); + let a3 = surface.geometry().point_from_surface_coords(a); + let b3 = surface.geometry().point_from_surface_coords(b); + let c3 = surface.geometry().point_from_surface_coords(c); + let d3 = surface.geometry().point_from_surface_coords(d); + let e3 = surface.geometry().point_from_surface_coords(e); assert!(triangles.contains_triangle([a3, b3, d3])); assert!(triangles.contains_triangle([b3, c3, d3])); diff --git a/crates/fj-kernel/src/builder/vertex.rs b/crates/fj-kernel/src/builder/vertex.rs index 879d5533f..7059bc05f 100644 --- a/crates/fj-kernel/src/builder/vertex.rs +++ b/crates/fj-kernel/src/builder/vertex.rs @@ -73,7 +73,9 @@ impl GlobalVertexBuilder for PartialGlobalVertex { position: impl Into>, ) -> Self { PartialGlobalVertex { - position: Some(surface.point_from_surface_coords(position)), + position: Some( + surface.geometry().point_from_surface_coords(position), + ), } } } diff --git a/crates/fj-kernel/src/geometry/surface.rs b/crates/fj-kernel/src/geometry/surface.rs index 53281be62..a17abaaa5 100644 --- a/crates/fj-kernel/src/geometry/surface.rs +++ b/crates/fj-kernel/src/geometry/surface.rs @@ -1,6 +1,6 @@ //! The geometry that defines a surface -use fj_math::Vector; +use fj_math::{Line, Point, Vector}; use super::path::GlobalPath; @@ -13,3 +13,69 @@ pub struct SurfaceGeometry { /// The v-axis of the surface pub v: Vector<3>, } + +impl SurfaceGeometry { + /// Convert a point in surface coordinates to model coordinates + pub fn point_from_surface_coords( + &self, + point: impl Into>, + ) -> Point<3> { + let point = point.into(); + self.u.point_from_path_coords([point.u]) + + self.path_to_line().vector_from_line_coords([point.v]) + } + + /// Convert a vector in surface coordinates to model coordinates + pub fn vector_from_surface_coords( + &self, + vector: impl Into>, + ) -> Vector<3> { + let vector = vector.into(); + self.u.vector_from_path_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.u.origin(), self.v) + } +} + +#[cfg(test)] +mod tests { + use fj_math::{Line, Point, Vector}; + use pretty_assertions::assert_eq; + + use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry}; + + #[test] + fn point_from_surface_coords() { + let surface = SurfaceGeometry { + u: GlobalPath::Line(Line::from_origin_and_direction( + Point::from([1., 1., 1.]), + Vector::from([0., 2., 0.]), + )), + v: Vector::from([0., 0., 2.]), + }; + + assert_eq!( + surface.point_from_surface_coords([2., 4.]), + Point::from([1., 5., 9.]), + ); + } + + #[test] + fn vector_from_surface_coords() { + let surface = SurfaceGeometry { + u: GlobalPath::Line(Line::from_origin_and_direction( + Point::from([1., 0., 0.]), + Vector::from([0., 2., 0.]), + )), + v: Vector::from([0., 0., 2.]), + }; + + assert_eq!( + surface.vector_from_surface_coords([2., 4.]), + Vector::from([0., 4., 8.]), + ); + } +} diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index 12f49f5c8..5280a33e2 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -44,77 +44,4 @@ impl Surface { pub fn v(&self) -> Vector<3> { self.geometry.v } - - /// Convert a point in surface coordinates to model coordinates - pub fn point_from_surface_coords( - &self, - point: impl Into>, - ) -> Point<3> { - let point = point.into(); - self.geometry.u.point_from_path_coords([point.u]) - + self.path_to_line().vector_from_line_coords([point.v]) - } - - /// Convert a vector in surface coordinates to model coordinates - pub fn vector_from_surface_coords( - &self, - vector: impl Into>, - ) -> Vector<3> { - let vector = vector.into(); - self.geometry.u.vector_from_path_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.geometry.u.origin(), - self.geometry.v, - ) - } -} - -#[cfg(test)] -mod tests { - use fj_math::{Line, Point, Vector}; - use pretty_assertions::assert_eq; - - use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry}; - - use super::Surface; - - #[test] - fn point_from_surface_coords() { - let surface = Surface { - geometry: SurfaceGeometry { - u: GlobalPath::Line(Line::from_origin_and_direction( - Point::from([1., 1., 1.]), - Vector::from([0., 2., 0.]), - )), - v: Vector::from([0., 0., 2.]), - }, - }; - - assert_eq!( - surface.point_from_surface_coords([2., 4.]), - Point::from([1., 5., 9.]), - ); - } - - #[test] - fn vector_from_surface_coords() { - let surface = Surface { - geometry: SurfaceGeometry { - u: GlobalPath::Line(Line::from_origin_and_direction( - Point::from([1., 0., 0.]), - Vector::from([0., 2., 0.]), - )), - v: Vector::from([0., 0., 2.]), - }, - }; - - assert_eq!( - surface.vector_from_surface_coords([2., 4.]), - Vector::from([0., 4., 8.]), - ); - } } diff --git a/crates/fj-kernel/src/validate/vertex.rs b/crates/fj-kernel/src/validate/vertex.rs index 186fab353..0ed7318e6 100644 --- a/crates/fj-kernel/src/validate/vertex.rs +++ b/crates/fj-kernel/src/validate/vertex.rs @@ -158,6 +158,7 @@ impl SurfaceVertexValidationError { ) -> Result<(), Self> { let surface_position_as_global = surface_vertex .surface() + .geometry() .point_from_surface_coords(surface_vertex.position()); let global_position = surface_vertex.global_form().position(); From 4053d9932696f8f96fd0f925fb664d056ffef869 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:30:11 +0100 Subject: [PATCH 06/17] Remove redundant getters --- crates/fj-kernel/src/algorithms/approx/curve.rs | 4 ++-- crates/fj-kernel/src/algorithms/intersect/ray_face.rs | 4 ++-- .../src/algorithms/intersect/surface_surface.rs | 4 ++-- crates/fj-kernel/src/algorithms/sweep/curve.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/face.rs | 4 ++-- crates/fj-kernel/src/algorithms/sweep/vertex.rs | 2 +- crates/fj-kernel/src/algorithms/transform/surface.rs | 4 ++-- crates/fj-kernel/src/objects/surface.rs | 10 ---------- 8 files changed, 12 insertions(+), 22 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 03981062f..e6494571e 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -62,7 +62,7 @@ fn approx_global_curve( // This will probably all be unified eventually, as `SurfacePath` and // `GlobalPath` grow APIs that are better suited to implementing this code // in a more abstract way. - let points = match (curve.path(), curve.surface().u()) { + let points = match (curve.path(), curve.surface().geometry().u) { (SurfacePath::Circle(_), GlobalPath::Circle(_)) => { todo!( "Approximating a circle on a curved surface not supported yet." @@ -102,7 +102,7 @@ fn approx_global_curve( [curve.path().point_from_path_coords(point_curve).u] })); - let approx_u = (curve.surface().u(), range_u) + let approx_u = (curve.surface().geometry().u, range_u) .approx_with_cache(tolerance, &mut ()); let mut points = Vec::new(); diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index 290d00f63..175abbaff 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -17,14 +17,14 @@ impl Intersect for (&HorizontalRayToTheRight<3>, &Handle) { fn intersect(self) -> Option { let (ray, face) = self; - let plane = match face.surface().u() { + let plane = match face.surface().geometry().u { GlobalPath::Circle(_) => todo!( "Casting a ray against a swept circle is not supported yet" ), GlobalPath::Line(line) => Plane::from_parametric( line.origin(), line.direction(), - face.surface().v(), + face.surface().geometry().v, ), }; diff --git a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs index 28d736c85..5cdf55261 100644 --- a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs @@ -74,12 +74,12 @@ impl SurfaceSurfaceIntersection { fn plane_from_surface(surface: &Surface) -> Plane { let (line, path) = { - let line = match surface.u() { + let line = match surface.geometry().u { GlobalPath::Line(line) => line, _ => todo!("Only plane-plane intersection is currently supported."), }; - (line, surface.v()) + (line, surface.geometry().v) }; Plane::from_parametric(line.origin(), line.direction(), path) diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index e2237912c..60b89481d 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -18,7 +18,7 @@ impl Sweep for Handle { _: &mut SweepCache, objects: &Objects, ) -> Result { - match self.surface().u() { + match self.surface().geometry().u { GlobalPath::Circle(_) => { // Sweeping a `Curve` creates a `Surface`. The u-axis of that // `Surface` is a `GlobalPath`, which we are computing below. diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 6bd851aae..930e19ccf 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -24,14 +24,14 @@ impl Sweep for Handle { let mut faces = Vec::new(); let is_negative_sweep = { - let u = match self.surface().u() { + let u = match self.surface().geometry().u { GlobalPath::Circle(_) => todo!( "Sweeping from faces defined in round surfaces is not \ supported" ), GlobalPath::Line(line) => line.direction(), }; - let v = self.surface().v(); + let v = self.surface().geometry().v; let normal = u.cross(&v); diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index d5706a1db..f6e622d1e 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -56,7 +56,7 @@ impl Sweep for (Handle, Handle) { // not, we have no way of knowing the surface coordinates of the input // `Vertex` on the `Surface`, and we're going to need to do that further // down. There's no way to check for that, unfortunately. - assert_eq!(path, surface.v()); + assert_eq!(path, surface.geometry().v); // With that out of the way, let's start by creating the `GlobalEdge`, // as that is the most straight-forward part of this operations, and diff --git a/crates/fj-kernel/src/algorithms/transform/surface.rs b/crates/fj-kernel/src/algorithms/transform/surface.rs index f05007520..a42be71e6 100644 --- a/crates/fj-kernel/src/algorithms/transform/surface.rs +++ b/crates/fj-kernel/src/algorithms/transform/surface.rs @@ -15,8 +15,8 @@ impl TransformObject for Handle { objects: &Objects, ) -> Result { Ok(objects.surfaces.insert(Surface::new( - self.u().transform(transform), - transform.transform_vector(&self.v()), + self.geometry().u.transform(transform), + transform.transform_vector(&self.geometry().v), ))?) } } diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index 5280a33e2..262988a22 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -34,14 +34,4 @@ impl Surface { pub fn geometry(&self) -> SurfaceGeometry { self.geometry } - - /// Access the path that defines the u-coordinate of this surface - pub fn u(&self) -> GlobalPath { - self.geometry.u - } - - /// Access the path that defines the v-coordinate of this surface - pub fn v(&self) -> Vector<3> { - self.geometry.v - } } From fb9786a728f1686e29f3c3924141d2d611c47fcf Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:40:44 +0100 Subject: [PATCH 07/17] Add `PartialSurface` --- crates/fj-kernel/src/partial/mod.rs | 1 + crates/fj-kernel/src/partial/objects/mod.rs | 1 + .../fj-kernel/src/partial/objects/surface.rs | 44 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 crates/fj-kernel/src/partial/objects/surface.rs diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index 2f81c0d25..19289522b 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -47,6 +47,7 @@ pub use self::{ cycle::PartialCycle, edge::{PartialGlobalEdge, PartialHalfEdge}, face::PartialFace, + surface::PartialSurface, vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, }, traits::{HasPartial, Partial}, diff --git a/crates/fj-kernel/src/partial/objects/mod.rs b/crates/fj-kernel/src/partial/objects/mod.rs index 917f53a56..7109d9611 100644 --- a/crates/fj-kernel/src/partial/objects/mod.rs +++ b/crates/fj-kernel/src/partial/objects/mod.rs @@ -2,6 +2,7 @@ pub mod curve; pub mod cycle; pub mod edge; pub mod face; +pub mod surface; pub mod vertex; use crate::objects::{ diff --git a/crates/fj-kernel/src/partial/objects/surface.rs b/crates/fj-kernel/src/partial/objects/surface.rs new file mode 100644 index 000000000..534bf50ba --- /dev/null +++ b/crates/fj-kernel/src/partial/objects/surface.rs @@ -0,0 +1,44 @@ +use crate::{ + geometry::surface::SurfaceGeometry, + objects::{Objects, Surface}, + partial::MergeWith, + validate::ValidationError, +}; + +/// A partial [`Surface`] +/// +/// See [`crate::partial`] for more information +#[derive(Clone, Debug, Default)] +pub struct PartialSurface { + /// The geometry that defines the [`Surface`] + pub geometry: Option, +} + +impl PartialSurface { + /// Build a full [`Surface`] from the partial surface + pub fn build(self, _: &Objects) -> Result { + let geometry = self + .geometry + .expect("Can't build `Surface` without geometry"); + + Ok(Surface::new(geometry.u, geometry.v)) + } +} + +impl MergeWith for PartialSurface { + fn merge_with(self, other: impl Into) -> Self { + let other = other.into(); + + Self { + geometry: self.geometry.merge_with(other.geometry), + } + } +} + +impl From<&Surface> for PartialSurface { + fn from(surface: &Surface) -> Self { + Self { + geometry: Some(surface.geometry()), + } + } +} From 5a50d112188cc26dde84ad46abc22c57dd78be5a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:47:09 +0100 Subject: [PATCH 08/17] Integrate `PartialCurve` into `partial` --- .../src/algorithms/transform/surface.rs | 21 +++++++++++-------- crates/fj-kernel/src/partial/objects/mod.rs | 5 +++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/surface.rs b/crates/fj-kernel/src/algorithms/transform/surface.rs index a42be71e6..10b6d1d6f 100644 --- a/crates/fj-kernel/src/algorithms/transform/surface.rs +++ b/crates/fj-kernel/src/algorithms/transform/surface.rs @@ -1,22 +1,25 @@ use fj_math::Transform; use crate::{ - objects::{Objects, Surface}, - storage::Handle, - validate::ValidationError, + geometry::surface::SurfaceGeometry, objects::Objects, + partial::PartialSurface, validate::ValidationError, }; use super::TransformObject; -impl TransformObject for Handle { +impl TransformObject for PartialSurface { fn transform( self, transform: &Transform, - objects: &Objects, + _: &Objects, ) -> Result { - Ok(objects.surfaces.insert(Surface::new( - self.geometry().u.transform(transform), - transform.transform_vector(&self.geometry().v), - ))?) + let geometry = self.geometry.map(|geometry| { + let u = geometry.u.transform(transform); + let v = transform.transform_vector(&geometry.v); + + SurfaceGeometry { u, v } + }); + + Ok(Self { geometry }) } } diff --git a/crates/fj-kernel/src/partial/objects/mod.rs b/crates/fj-kernel/src/partial/objects/mod.rs index 7109d9611..a4acf77a6 100644 --- a/crates/fj-kernel/src/partial/objects/mod.rs +++ b/crates/fj-kernel/src/partial/objects/mod.rs @@ -7,13 +7,13 @@ pub mod vertex; use crate::objects::{ Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, - Objects, SurfaceVertex, Vertex, + Objects, Surface, SurfaceVertex, Vertex, }; use super::{ HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle, PartialFace, PartialGlobalCurve, PartialGlobalEdge, PartialGlobalVertex, - PartialHalfEdge, PartialSurfaceVertex, PartialVertex, + PartialHalfEdge, PartialSurface, PartialSurfaceVertex, PartialVertex, }; macro_rules! impl_traits { @@ -53,6 +53,7 @@ impl_traits!( GlobalEdge, PartialGlobalEdge; GlobalVertex, PartialGlobalVertex; HalfEdge, PartialHalfEdge; + Surface, PartialSurface; SurfaceVertex, PartialSurfaceVertex; Vertex, PartialVertex; ); From 4717721e50e7f4a1dbe777c03763125f157894df Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:58:21 +0100 Subject: [PATCH 09/17] Make use of `Insert` to insert `Surface`s --- .../fj-kernel/src/algorithms/approx/curve.rs | 20 ++++++++----------- .../fj-kernel/src/algorithms/sweep/curve.rs | 4 +++- crates/fj-kernel/src/builder/shell.rs | 5 ++--- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index e6494571e..8e3af08f0 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -213,9 +213,8 @@ mod tests { fn approx_line_on_flat_surface() -> anyhow::Result<()> { let objects = Objects::new(); - let surface = objects - .surfaces - .insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?; + let surface = Surface::new(GlobalPath::x_axis(), [0., 0., 1.]) + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface), ..Default::default() @@ -235,10 +234,9 @@ mod tests { { let objects = Objects::new(); - let surface = objects.surfaces.insert(Surface::new( - GlobalPath::circle_from_radius(1.), - [0., 0., 1.], - ))?; + let surface = + Surface::new(GlobalPath::circle_from_radius(1.), [0., 0., 1.]) + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface), ..Default::default() @@ -258,8 +256,7 @@ mod tests { let objects = Objects::new(); let path = GlobalPath::circle_from_radius(1.); - let surface = - objects.surfaces.insert(Surface::new(path, [0., 0., 1.]))?; + let surface = Surface::new(path, [0., 0., 1.]).insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() @@ -291,9 +288,8 @@ mod tests { fn approx_circle_on_flat_surface() -> anyhow::Result<()> { let objects = Objects::new(); - let surface = objects - .surfaces - .insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?; + let surface = Surface::new(GlobalPath::x_axis(), [0., 0., 1.]) + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface), ..Default::default() diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index 60b89481d..a4ffe64fd 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -2,6 +2,7 @@ use fj_math::{Circle, Line, Vector}; use crate::{ geometry::path::{GlobalPath, SurfacePath}, + insert::Insert, objects::{Curve, Objects, Surface}, storage::Handle, validate::ValidationError, @@ -77,6 +78,7 @@ impl Sweep for Handle { } }; - Ok(objects.surfaces.insert(Surface::new(u, path))?) + let surface = Surface::new(u, path).insert(objects)?; + Ok(surface) } } diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 343b45857..1c3da78ca 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -78,9 +78,8 @@ impl<'a> ShellBuilder<'a> { .map(|vertex| vertex.global_form().position()); let c = a + [Z, Z, edge_length]; - self.objects - .surfaces - .insert(Surface::plane_from_points([a, b, c])) + Surface::plane_from_points([a, b, c]) + .insert(self.objects) .unwrap() }) .collect::>(); From f664ee125328292b3ede8bc024ab76de758d8eba Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 20:56:09 +0100 Subject: [PATCH 10/17] Add `SurfaceBuilder` --- crates/fj-kernel/src/builder/mod.rs | 2 ++ crates/fj-kernel/src/builder/surface.rs | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 crates/fj-kernel/src/builder/surface.rs diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index 1d96e73d7..7a7b4e70a 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -12,6 +12,7 @@ mod curve; mod cycle; mod edge; mod face; +mod surface; mod vertex; pub use self::{ @@ -22,5 +23,6 @@ pub use self::{ shell::ShellBuilder, sketch::SketchBuilder, solid::SolidBuilder, + surface::SurfaceBuilder, vertex::{GlobalVertexBuilder, SurfaceVertexBuilder, VertexBuilder}, }; diff --git a/crates/fj-kernel/src/builder/surface.rs b/crates/fj-kernel/src/builder/surface.rs new file mode 100644 index 000000000..3375d0bc8 --- /dev/null +++ b/crates/fj-kernel/src/builder/surface.rs @@ -0,0 +1,22 @@ +use fj_math::Vector; + +use crate::{ + geometry::{path::GlobalPath, surface::SurfaceGeometry}, + partial::PartialSurface, +}; + +/// Builder API for [`PartialSurface`] +pub trait SurfaceBuilder { + /// Build a surface from its two axes + fn from_axes(u: GlobalPath, v: impl Into>) -> Self; +} + +impl SurfaceBuilder for PartialSurface { + fn from_axes(u: GlobalPath, v: impl Into>) -> Self { + let v = v.into(); + + Self { + geometry: Some(SurfaceGeometry { u, v }), + } + } +} From 07e24ccf56609b093acf49b1451485f7de6455dd Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 21:10:12 +0100 Subject: [PATCH 11/17] Make use of `SurfaceBuilder` --- .../fj-kernel/src/algorithms/approx/curve.rs | 31 ++++++++++++------- .../fj-kernel/src/algorithms/sweep/curve.rs | 6 +++- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 8e3af08f0..00e77f588 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -200,11 +200,11 @@ mod tests { use crate::{ algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint}, - builder::CurveBuilder, + builder::{CurveBuilder, SurfaceBuilder}, geometry::path::GlobalPath, insert::Insert, - objects::{Objects, Surface}, - partial::PartialCurve, + objects::Objects, + partial::{PartialCurve, PartialSurface}, }; use super::CurveApprox; @@ -213,8 +213,10 @@ mod tests { fn approx_line_on_flat_surface() -> anyhow::Result<()> { let objects = Objects::new(); - let surface = Surface::new(GlobalPath::x_axis(), [0., 0., 1.]) - .insert(&objects)?; + let surface = + PartialSurface::from_axes(GlobalPath::x_axis(), [0., 0., 1.]) + .build(&objects)? + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface), ..Default::default() @@ -234,9 +236,12 @@ mod tests { { let objects = Objects::new(); - let surface = - Surface::new(GlobalPath::circle_from_radius(1.), [0., 0., 1.]) - .insert(&objects)?; + let surface = PartialSurface::from_axes( + GlobalPath::circle_from_radius(1.), + [0., 0., 1.], + ) + .build(&objects)? + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface), ..Default::default() @@ -256,7 +261,9 @@ mod tests { let objects = Objects::new(); let path = GlobalPath::circle_from_radius(1.); - let surface = Surface::new(path, [0., 0., 1.]).insert(&objects)?; + let surface = PartialSurface::from_axes(path, [0., 0., 1.]) + .build(&objects)? + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface.clone()), ..Default::default() @@ -288,8 +295,10 @@ mod tests { fn approx_circle_on_flat_surface() -> anyhow::Result<()> { let objects = Objects::new(); - let surface = Surface::new(GlobalPath::x_axis(), [0., 0., 1.]) - .insert(&objects)?; + let surface = + PartialSurface::from_axes(GlobalPath::x_axis(), [0., 0., 1.]) + .build(&objects)? + .insert(&objects)?; let mut curve = PartialCurve { surface: Some(surface), ..Default::default() diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index a4ffe64fd..8ffc6e469 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -1,9 +1,11 @@ use fj_math::{Circle, Line, Vector}; use crate::{ + builder::SurfaceBuilder, geometry::path::{GlobalPath, SurfacePath}, insert::Insert, objects::{Curve, Objects, Surface}, + partial::PartialSurface, storage::Handle, validate::ValidationError, }; @@ -78,7 +80,9 @@ impl Sweep for Handle { } }; - let surface = Surface::new(u, path).insert(objects)?; + let surface = PartialSurface::from_axes(u, path) + .build(objects)? + .insert(objects)?; Ok(surface) } } From ab045760aca584e2a87d5bcf6826feffc280c814 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 21:11:00 +0100 Subject: [PATCH 12/17] Simplify `Surface::new` --- crates/fj-kernel/src/objects/mod.rs | 20 ++++++++++++------- crates/fj-kernel/src/objects/surface.rs | 10 +++------- .../fj-kernel/src/partial/objects/surface.rs | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/crates/fj-kernel/src/objects/mod.rs b/crates/fj-kernel/src/objects/mod.rs index 9ad85435f..221c245ef 100644 --- a/crates/fj-kernel/src/objects/mod.rs +++ b/crates/fj-kernel/src/objects/mod.rs @@ -100,7 +100,7 @@ use std::convert::Infallible; use fj_math::Vector; use crate::{ - geometry::path::GlobalPath, + geometry::{path::GlobalPath, surface::SurfaceGeometry}, storage::{Handle, Store}, validate::{ CycleValidationError, FaceValidationError, HalfEdgeValidationError, @@ -380,12 +380,18 @@ impl Default for Surfaces { fn default() -> Self { let store = Store::new(); - let xy_plane = - store.insert(Surface::new(GlobalPath::x_axis(), Vector::unit_y())); - let xz_plane = - store.insert(Surface::new(GlobalPath::x_axis(), Vector::unit_z())); - let yz_plane = - store.insert(Surface::new(GlobalPath::y_axis(), Vector::unit_z())); + let xy_plane = store.insert(Surface::new(SurfaceGeometry { + u: GlobalPath::x_axis(), + v: Vector::unit_y(), + })); + let xz_plane = store.insert(Surface::new(SurfaceGeometry { + u: GlobalPath::x_axis(), + v: Vector::unit_z(), + })); + let yz_plane = store.insert(Surface::new(SurfaceGeometry { + u: GlobalPath::y_axis(), + v: Vector::unit_z(), + })); Self { store, diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index 262988a22..ffc3bd188 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -1,4 +1,4 @@ -use fj_math::{Line, Point, Vector}; +use fj_math::{Line, Point}; use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry}; @@ -10,12 +10,8 @@ pub struct Surface { impl Surface { /// Construct a `Surface` from two paths that define its coordinate system - pub fn new(u: GlobalPath, v: impl Into>) -> Self { - let v = v.into(); - - Self { - geometry: SurfaceGeometry { u, v }, - } + pub fn new(geometry: SurfaceGeometry) -> Self { + Self { geometry } } /// Construct a plane from 3 points diff --git a/crates/fj-kernel/src/partial/objects/surface.rs b/crates/fj-kernel/src/partial/objects/surface.rs index 534bf50ba..29c4a0ba8 100644 --- a/crates/fj-kernel/src/partial/objects/surface.rs +++ b/crates/fj-kernel/src/partial/objects/surface.rs @@ -21,7 +21,7 @@ impl PartialSurface { .geometry .expect("Can't build `Surface` without geometry"); - Ok(Surface::new(geometry.u, geometry.v)) + Ok(Surface::new(geometry)) } } From b7c32e14698e5c8dcade67cb6155c8edcd3a52b7 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 21:14:14 +0100 Subject: [PATCH 13/17] Add `SurfaceBuilder::plane_from_points` --- crates/fj-kernel/src/builder/shell.rs | 13 +++++++++---- crates/fj-kernel/src/builder/surface.rs | 16 +++++++++++++++- crates/fj-kernel/src/objects/surface.rs | 16 +--------------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 1c3da78ca..838295820 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -6,10 +6,13 @@ use iter_fixed::IntoIteratorFixed; use crate::{ algorithms::transform::TransformObject, - builder::{FaceBuilder, HalfEdgeBuilder}, + builder::{FaceBuilder, HalfEdgeBuilder, SurfaceBuilder}, insert::Insert, - objects::{Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface}, - partial::{HasPartial, PartialCurve, PartialSurfaceVertex, PartialVertex}, + objects::{Cycle, Face, FaceSet, HalfEdge, Objects, Shell}, + partial::{ + HasPartial, PartialCurve, PartialSurface, PartialSurfaceVertex, + PartialVertex, + }, storage::Handle, }; @@ -78,7 +81,9 @@ impl<'a> ShellBuilder<'a> { .map(|vertex| vertex.global_form().position()); let c = a + [Z, Z, edge_length]; - Surface::plane_from_points([a, b, c]) + PartialSurface::plane_from_points([a, b, c]) + .build(self.objects) + .unwrap() .insert(self.objects) .unwrap() }) diff --git a/crates/fj-kernel/src/builder/surface.rs b/crates/fj-kernel/src/builder/surface.rs index 3375d0bc8..cc1d57728 100644 --- a/crates/fj-kernel/src/builder/surface.rs +++ b/crates/fj-kernel/src/builder/surface.rs @@ -1,4 +1,4 @@ -use fj_math::Vector; +use fj_math::{Line, Point, Vector}; use crate::{ geometry::{path::GlobalPath, surface::SurfaceGeometry}, @@ -9,6 +9,9 @@ use crate::{ pub trait SurfaceBuilder { /// Build a surface from its two axes fn from_axes(u: GlobalPath, v: impl Into>) -> Self; + + /// Construct a plane from 3 points + fn plane_from_points(points: [impl Into>; 3]) -> Self; } impl SurfaceBuilder for PartialSurface { @@ -19,4 +22,15 @@ impl SurfaceBuilder for PartialSurface { geometry: Some(SurfaceGeometry { u, v }), } } + + fn plane_from_points(points: [impl Into>; 3]) -> Self { + let [a, b, c] = points.map(Into::into); + + let u = GlobalPath::Line(Line::from_points([a, b])); + let v = c - a; + + Self { + geometry: Some(SurfaceGeometry { u, v }), + } + } } diff --git a/crates/fj-kernel/src/objects/surface.rs b/crates/fj-kernel/src/objects/surface.rs index ffc3bd188..0905a0bef 100644 --- a/crates/fj-kernel/src/objects/surface.rs +++ b/crates/fj-kernel/src/objects/surface.rs @@ -1,6 +1,4 @@ -use fj_math::{Line, Point}; - -use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry}; +use crate::geometry::surface::SurfaceGeometry; /// A two-dimensional shape #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] @@ -14,18 +12,6 @@ impl Surface { Self { geometry } } - /// 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 u = GlobalPath::Line(Line::from_points([a, b])); - let v = c - a; - - Self { - geometry: SurfaceGeometry { u, v }, - } - } - /// Access the surface's geometry pub fn geometry(&self) -> SurfaceGeometry { self.geometry From bbb28312e07b637f9a39aa988796dedf0ff8ceac Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 21:26:43 +0100 Subject: [PATCH 14/17] Add `MaybePartial::geometry` --- crates/fj-kernel/src/partial/maybe_partial.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 64a9aa1d8..cad49c181 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -1,7 +1,7 @@ use fj_math::Point; use crate::{ - geometry::path::SurfacePath, + geometry::{path::SurfacePath, surface::SurfaceGeometry}, insert::Insert, objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, @@ -212,6 +212,16 @@ impl MaybePartial { } } +impl MaybePartial { + /// Access the geometry + pub fn geometry(&self) -> Option { + match self { + Self::Full(full) => Some(full.geometry()), + Self::Partial(partial) => partial.geometry, + } + } +} + impl MaybePartial { /// Access the position pub fn position(&self) -> Option> { From 9c2b67c9bf9a295c8f035e572a99f7565f0863a8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 11 Nov 2022 21:28:51 +0100 Subject: [PATCH 15/17] Use more specific argument in builder method --- crates/fj-kernel/src/builder/vertex.rs | 20 ++++++++++--------- .../fj-kernel/src/partial/objects/vertex.rs | 3 ++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/crates/fj-kernel/src/builder/vertex.rs b/crates/fj-kernel/src/builder/vertex.rs index 7059bc05f..9c3266b00 100644 --- a/crates/fj-kernel/src/builder/vertex.rs +++ b/crates/fj-kernel/src/builder/vertex.rs @@ -1,7 +1,8 @@ use fj_math::Point; use crate::{ - objects::{Curve, GlobalVertex, Surface}, + geometry::surface::SurfaceGeometry, + objects::{Curve, GlobalVertex}, partial::{ HasPartial, MaybePartial, PartialGlobalVertex, PartialSurfaceVertex, PartialVertex, @@ -44,7 +45,7 @@ pub trait GlobalVertexBuilder { /// Update partial global vertex from the given surface and position on it fn from_surface_and_position( - surface: &Surface, + surface: &SurfaceGeometry, position: impl Into>, ) -> Self; } @@ -59,9 +60,12 @@ impl GlobalVertexBuilder for PartialGlobalVertex { let path = curve.path.expect( "Need path to create `GlobalVertex` from curve and position", ); - let surface = curve.surface.expect( - "Need surface to create `GlobalVertex` from curve and position", - ); + let surface = curve + .surface + .expect( + "Need surface to create `GlobalVertex` from curve and position", + ) + .geometry(); let position_surface = path.point_from_path_coords(position); @@ -69,13 +73,11 @@ impl GlobalVertexBuilder for PartialGlobalVertex { } fn from_surface_and_position( - surface: &Surface, + surface: &SurfaceGeometry, position: impl Into>, ) -> Self { PartialGlobalVertex { - position: Some( - surface.geometry().point_from_surface_coords(position), - ), + position: Some(surface.point_from_surface_coords(position)), } } } diff --git a/crates/fj-kernel/src/partial/objects/vertex.rs b/crates/fj-kernel/src/partial/objects/vertex.rs index 111ddf7fc..f442691e3 100644 --- a/crates/fj-kernel/src/partial/objects/vertex.rs +++ b/crates/fj-kernel/src/partial/objects/vertex.rs @@ -108,7 +108,8 @@ impl PartialSurfaceVertex { let global_form = self .global_form .merge_with(PartialGlobalVertex::from_surface_and_position( - &surface, position, + &surface.geometry(), + position, )) .into_full(objects)?; From fe2fa1b8b73eea4ba16d500395a91726dcd1ab82 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Sat, 12 Nov 2022 17:42:23 +0100 Subject: [PATCH 16/17] Rewrite surface selection with merge --- crates/fj-kernel/src/builder/edge.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 74794c131..3d276c505 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -5,8 +5,9 @@ use crate::{ insert::Insert, objects::{Curve, Objects, Surface, Vertex, VerticesInNormalizedOrder}, partial::{ - MaybePartial, PartialCurve, PartialGlobalEdge, PartialGlobalVertex, - PartialHalfEdge, PartialSurfaceVertex, PartialVertex, + MaybePartial, MergeWith, PartialCurve, PartialGlobalEdge, + PartialGlobalVertex, PartialHalfEdge, PartialSurfaceVertex, + PartialVertex, }, storage::Handle, validate::ValidationError, @@ -135,8 +136,8 @@ impl HalfEdgeBuilder for PartialHalfEdge { let surface = self .curve() .surface() - .or_else(|| from_surface.surface()) - .or_else(|| to_surface.surface()) + .merge_with(from_surface.surface()) + .merge_with(to_surface.surface()) .expect("Can't infer line segment without a surface"); let points = [&from_surface, &to_surface].map(|vertex| { vertex From 08a99f49c3ec5b3c6a0be834cfb6396fdfb4d948 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Sat, 12 Nov 2022 17:52:59 +0100 Subject: [PATCH 17/17] Derive fewer traits for `PartialSurfaceVertex` It won't be able to support all of them going forward. --- crates/fj-kernel/src/partial/objects/vertex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/objects/vertex.rs b/crates/fj-kernel/src/partial/objects/vertex.rs index f442691e3..75b6c7539 100644 --- a/crates/fj-kernel/src/partial/objects/vertex.rs +++ b/crates/fj-kernel/src/partial/objects/vertex.rs @@ -80,7 +80,7 @@ impl From<&Vertex> for PartialVertex { /// A partial [`SurfaceVertex`] /// /// See [`crate::partial`] for more information. -#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] +#[derive(Clone, Debug, Default)] pub struct PartialSurfaceVertex { /// The position of the [`SurfaceVertex`] pub position: Option>,