diff --git a/src/kernel/algorithms/approximation.rs b/src/kernel/algorithms/approximation.rs index 6b01c7912..f7accdc1c 100644 --- a/src/kernel/algorithms/approximation.rs +++ b/src/kernel/algorithms/approximation.rs @@ -150,10 +150,7 @@ mod tests { kernel::{ geometry::Surface, shape::Shape, - topology::{ - edges::{Cycle, Edge}, - faces::Face, - }, + topology::{edges::Cycle, faces::Face}, }, math::{Point, Scalar, Segment}, }; @@ -214,11 +211,9 @@ mod tests { let v2 = shape.vertices().add(b); let v3 = shape.vertices().add(c); - let ab = shape - .edges() - .add(Edge::line_segment([v1.clone(), v2.clone()])); - let bc = shape.edges().add(Edge::line_segment([v2, v3.clone()])); - let ca = shape.edges().add(Edge::line_segment([v3, v1])); + let ab = shape.edges().add_line_segment([v1.clone(), v2.clone()]); + let bc = shape.edges().add_line_segment([v2, v3.clone()]); + let ca = shape.edges().add_line_segment([v3, v1]); let cycle = Cycle { edges: vec![ab, bc, ca], @@ -255,19 +250,18 @@ mod tests { let v3 = shape.vertices().add(c); let v4 = shape.vertices().add(d); - let ab = shape - .edges() - .add(Edge::line_segment([v1.clone(), v2.clone()])); - let bc = shape.edges().add(Edge::line_segment([v2, v3.clone()])); - let cd = shape.edges().add(Edge::line_segment([v3, v4.clone()])); - let da = shape.edges().add(Edge::line_segment([v4, v1])); + let ab = shape.edges().add_line_segment([v1.clone(), v2.clone()]); + let bc = shape.edges().add_line_segment([v2, v3.clone()]); + let cd = shape.edges().add_line_segment([v3, v4.clone()]); + let da = shape.edges().add_line_segment([v4, v1]); let abcd = shape.cycles().add(Cycle { edges: vec![ab, bc, cd, da], }); + let surface = shape.surfaces().add(Surface::x_y_plane()); let face = Face::Face { - surface: Surface::x_y_plane(), + surface, cycles: vec![abcd], }; diff --git a/src/kernel/algorithms/sweep.rs b/src/kernel/algorithms/sweep.rs index b5e123b01..be4e8932a 100644 --- a/src/kernel/algorithms/sweep.rs +++ b/src/kernel/algorithms/sweep.rs @@ -71,10 +71,7 @@ mod tests { kernel::{ geometry::{surfaces::Swept, Surface}, shape::{handle::Handle, Shape}, - topology::{ - edges::{Cycle, Edge}, - faces::Face, - }, + topology::{edges::Cycle, faces::Face}, }, math::{Point, Scalar, Vector}, }; @@ -115,24 +112,22 @@ mod tests { let b = shape.vertices().add(b.into()); let c = shape.vertices().add(c.into()); - let ab = shape - .edges() - .add(Edge::line_segment([a.clone(), b.clone()])); - let bc = shape - .edges() - .add(Edge::line_segment([b.clone(), c.clone()])); - let ca = shape - .edges() - .add(Edge::line_segment([c.clone(), a.clone()])); + let ab = shape.edges().add_line_segment([a.clone(), b.clone()]); + let bc = shape.edges().add_line_segment([b.clone(), c.clone()]); + let ca = shape.edges().add_line_segment([c.clone(), a.clone()]); let cycles = shape.cycles().add(Cycle { edges: vec![ab, bc, ca], }); + let surface = + shape + .surfaces() + .add(Surface::Swept(Swept::plane_from_points( + [a, b, c].map(|vertex| vertex.point()), + ))); let abc = Face::Face { - surface: Surface::Swept(Swept::plane_from_points( - [a, b, c].map(|vertex| vertex.point()), - )), + surface, cycles: vec![cycles], }; diff --git a/src/kernel/algorithms/transform.rs b/src/kernel/algorithms/transform.rs index 31ab73d17..7cb6ae16f 100644 --- a/src/kernel/algorithms/transform.rs +++ b/src/kernel/algorithms/transform.rs @@ -44,6 +44,9 @@ pub fn transform_face( let mut edges = Vec::new(); for edge in &cycle.edges { + let curve = + shape.curves().add(edge.curve.transform(transform)); + let vertices = edge.vertices.clone().map(|vertices| { vertices.map(|vertex| { let point = @@ -53,10 +56,7 @@ pub fn transform_face( }) }); - let edge = Edge { - curve: edge.curve.transform(transform), - vertices, - }; + let edge = Edge { curve, vertices }; let edge = shape.edges().add(edge); edges.push(edge); @@ -65,9 +65,11 @@ pub fn transform_face( cycles_trans.push(shape.cycles().add(Cycle { edges })); } + let surface = shape.surfaces().add(surface.transform(transform)); + Face::Face { cycles: cycles_trans, - surface: surface.transform(transform), + surface, } } Face::Triangles(mut triangles) => { diff --git a/src/kernel/shape/curves.rs b/src/kernel/shape/curves.rs new file mode 100644 index 000000000..4d891936f --- /dev/null +++ b/src/kernel/shape/curves.rs @@ -0,0 +1,13 @@ +use crate::kernel::geometry::Curve; + +use super::handle::{Handle, Storage}; + +/// API to access the curves of a shape +pub struct Curves; + +impl Curves { + /// Add a curve to the shape + pub fn add(&mut self, curve: Curve) -> Handle { + Storage::new(curve).handle() + } +} diff --git a/src/kernel/shape/edges.rs b/src/kernel/shape/edges.rs index 625ebfff9..921b5250c 100644 --- a/src/kernel/shape/edges.rs +++ b/src/kernel/shape/edges.rs @@ -1,9 +1,20 @@ -use crate::kernel::topology::edges::Edge; +use crate::{ + kernel::{ + geometry::{Circle, Curve, Line}, + topology::{edges::Edge, vertices::Vertex}, + }, + math::{Point, Scalar, Vector}, +}; -use super::handle::{Handle, Storage}; +use super::{ + curves::Curves, + handle::{Handle, Storage}, +}; /// The edges of a shape -pub struct Edges; +pub struct Edges { + pub(super) curves: Curves, +} impl Edges { /// Add an edge to the shape @@ -23,4 +34,36 @@ impl Edges { pub fn add(&mut self, edge: Edge) -> Handle { Storage::new(edge).handle() } + + /// Add a circle to the shape + /// + /// Calls [`Edges::add`] internally, and is subject to the same + /// restrictions. + pub fn add_circle(&mut self, radius: Scalar) -> Handle { + let curve = self.curves.add(Curve::Circle(Circle { + center: Point::origin(), + radius: Vector::from([radius, Scalar::ZERO]), + })); + self.add(Edge { + curve, + vertices: None, + }) + } + + /// Add a line segment to the shape + /// + /// Calls [`Edges::add`] internally, and is subject to the same + /// restrictions. + pub fn add_line_segment( + &mut self, + vertices: [Handle; 2], + ) -> Handle { + let curve = self.curves.add(Curve::Line(Line::from_points( + vertices.clone().map(|vertex| vertex.point()), + ))); + self.add(Edge { + curve, + vertices: Some(vertices), + }) + } } diff --git a/src/kernel/shape/mod.rs b/src/kernel/shape/mod.rs index 265fab1a4..75fe2bfcd 100644 --- a/src/kernel/shape/mod.rs +++ b/src/kernel/shape/mod.rs @@ -1,7 +1,9 @@ +pub mod curves; pub mod cycles; pub mod edges; pub mod faces; pub mod handle; +pub mod surfaces; pub mod vertices; use crate::math::Scalar; @@ -9,8 +11,8 @@ use crate::math::Scalar; use super::topology::{edges::Cycle, faces::Face, vertices::Vertex}; use self::{ - cycles::Cycles, edges::Edges, faces::Faces, handle::Storage, - vertices::Vertices, + curves::Curves, cycles::Cycles, edges::Edges, faces::Faces, + handle::Storage, surfaces::Surfaces, vertices::Vertices, }; /// The boundary representation of a shape @@ -56,6 +58,16 @@ impl Shape { self } + /// Access the shape's curves + pub fn curves(&mut self) -> Curves { + Curves + } + + /// Access the shape's surfaces + pub fn surfaces(&mut self) -> Surfaces { + Surfaces + } + /// Access the shape's vertices pub fn vertices(&mut self) -> Vertices { Vertices { @@ -66,7 +78,7 @@ impl Shape { /// Access the shape's edges pub fn edges(&mut self) -> Edges { - Edges + Edges { curves: Curves } } /// Access the shape's cycles diff --git a/src/kernel/shape/surfaces.rs b/src/kernel/shape/surfaces.rs new file mode 100644 index 000000000..2de37daff --- /dev/null +++ b/src/kernel/shape/surfaces.rs @@ -0,0 +1,13 @@ +use crate::kernel::geometry::Surface; + +use super::handle::{Handle, Storage}; + +/// API to access the surfaces of a shape +pub struct Surfaces; + +impl Surfaces { + /// Add a surface to the shape + pub fn add(&mut self, surface: Surface) -> Handle { + Storage::new(surface).handle() + } +} diff --git a/src/kernel/shapes/circle.rs b/src/kernel/shapes/circle.rs index 3cf0a37bc..5ce6c3441 100644 --- a/src/kernel/shapes/circle.rs +++ b/src/kernel/shapes/circle.rs @@ -3,10 +3,7 @@ use crate::{ kernel::{ geometry::Surface, shape::Shape, - topology::{ - edges::{Cycle, Edge}, - faces::Face, - }, + topology::{edges::Cycle, faces::Face}, }, math::{Aabb, Point, Scalar}, }; @@ -20,16 +17,12 @@ impl ToShape for fj::Circle { // Circles have just a single round edge with no vertices. So none need // to be added here. - let edge = shape - .edges() - .add(Edge::circle(Scalar::from_f64(self.radius))); + let edge = shape.edges().add_circle(Scalar::from_f64(self.radius)); shape.cycles().add(Cycle { edges: vec![edge] }); let cycles = shape.cycles().all().collect(); - shape.faces().add(Face::Face { - cycles, - surface: Surface::x_y_plane(), - }); + let surface = shape.surfaces().add(Surface::x_y_plane()); + shape.faces().add(Face::Face { cycles, surface }); shape } diff --git a/src/kernel/shapes/sketch.rs b/src/kernel/shapes/sketch.rs index de13b0a1e..d69b4ddc2 100644 --- a/src/kernel/shapes/sketch.rs +++ b/src/kernel/shapes/sketch.rs @@ -3,10 +3,7 @@ use crate::{ kernel::{ geometry::Surface, shape::Shape, - topology::{ - edges::{Cycle, Edge}, - faces::Face, - }, + topology::{edges::Cycle, faces::Face}, }, math::{Aabb, Point, Scalar}, }; @@ -40,16 +37,17 @@ impl ToShape for fj::Sketch { let a = window[0].clone(); let b = window[1].clone(); - let edge = shape.edges().add(Edge::line_segment([a, b])); + let edge = shape.edges().add_line_segment([a, b]); edges.push(edge); } shape.cycles().add(Cycle { edges }); }; + let surface = shape.surfaces().add(Surface::x_y_plane()); let face = Face::Face { cycles: shape.cycles().all().collect(), - surface: Surface::x_y_plane(), + surface, }; shape.faces().add(face); diff --git a/src/kernel/topology/edges.rs b/src/kernel/topology/edges.rs index e07a04288..20265ffdf 100644 --- a/src/kernel/topology/edges.rs +++ b/src/kernel/topology/edges.rs @@ -1,10 +1,4 @@ -use crate::{ - kernel::{ - geometry::{Circle, Curve, Line}, - shape::handle::Handle, - }, - math::{Point, Scalar, Vector}, -}; +use crate::kernel::{geometry::Curve, shape::handle::Handle}; use super::vertices::Vertex; @@ -26,7 +20,7 @@ pub struct Edge { /// The edge can be a segment of the curve that is bounded by two vertices, /// or if the curve is continuous (i.e. connects to itself), the edge could /// be defined by the whole curve, and have no bounding vertices. - pub curve: Curve, + pub curve: Handle, /// Access the vertices that bound the edge on the curve /// @@ -44,26 +38,3 @@ pub struct Edge { /// and store 1D vertices again, at some point. pub vertices: Option<[Handle; 2]>, } - -impl Edge { - /// Create a line segment - pub fn line_segment(vertices: [Handle; 2]) -> Self { - Edge { - curve: Curve::Line(Line::from_points( - vertices.clone().map(|vertex| vertex.point()), - )), - vertices: Some(vertices), - } - } - - /// Create a circle - pub fn circle(radius: Scalar) -> Self { - Edge { - curve: Curve::Circle(Circle { - center: Point::origin(), - radius: Vector::from([radius, Scalar::ZERO]), - }), - vertices: None, - } - } -} diff --git a/src/kernel/topology/faces.rs b/src/kernel/topology/faces.rs index 6aebcfcf2..bfe394287 100644 --- a/src/kernel/topology/faces.rs +++ b/src/kernel/topology/faces.rs @@ -26,7 +26,7 @@ pub enum Face { /// surface. Face { /// The surface that defines this face - surface: Surface, + surface: Handle, /// The cycles that bound the face ///