From 180ddcfc24dc995baeae739c3510b7689e27a26f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 24 Mar 2022 16:29:04 +0100 Subject: [PATCH 1/7] In `VertexBuilder`, re-use objects, if they exists This makes the builder APIs more flexible, allowing for methods that build a cycle out of points, for example. --- fj-kernel/src/topology/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fj-kernel/src/topology/builder.rs b/fj-kernel/src/topology/builder.rs index 7b55db4e0..1646aa974 100644 --- a/fj-kernel/src/topology/builder.rs +++ b/fj-kernel/src/topology/builder.rs @@ -23,8 +23,8 @@ impl<'r> VertexBuilder<'r> { self, point: impl Into>, ) -> ValidationResult { - let point = self.shape.insert(point.into())?; - let vertex = self.shape.insert(Vertex { point })?; + let point = self.shape.get_handle_or_insert(point.into())?; + let vertex = self.shape.get_handle_or_insert(Vertex { point })?; Ok(vertex) } From 7279ffffdee843ad1ec3308549d607db5c17a120 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 24 Mar 2022 16:29:17 +0100 Subject: [PATCH 2/7] Update doc comment --- fj-kernel/src/topology/builder.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fj-kernel/src/topology/builder.rs b/fj-kernel/src/topology/builder.rs index 1646aa974..216c629b1 100644 --- a/fj-kernel/src/topology/builder.rs +++ b/fj-kernel/src/topology/builder.rs @@ -19,6 +19,9 @@ impl<'r> VertexBuilder<'r> { } /// Build a [`Vertex`] from a point + /// + /// If an identical point or vertex are already part of the shape, those + /// objects are re-used. pub fn from_point( self, point: impl Into>, From 2c7ec90937dddac7aeabf83327127544aa002e03 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 24 Mar 2022 15:32:49 +0100 Subject: [PATCH 3/7] Add `EdgeBuilder::line_segment_from_points` --- fj-kernel/src/topology/builder.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/fj-kernel/src/topology/builder.rs b/fj-kernel/src/topology/builder.rs index 216c629b1..9e5949974 100644 --- a/fj-kernel/src/topology/builder.rs +++ b/fj-kernel/src/topology/builder.rs @@ -58,6 +58,25 @@ impl<'r> EdgeBuilder<'r> { Ok(edge) } + /// Build a line segment from two points + pub fn line_segment_from_points( + self, + vertices: [impl Into>; 2], + ) -> ValidationResult { + // Can be cleaned up with `try_map`, once that is stable: + // https://doc.rust-lang.org/std/primitive.array.html#method.try_map + let vertices = + vertices.map(|point| Vertex::build(self.shape).from_point(point)); + let vertices = match vertices { + [Ok(a), Ok(b)] => Ok([a, b]), + [Err(err), _] | [_, Err(err)] => Err(err), + }?; + + let edge = self.line_segment_from_vertices(vertices)?; + + Ok(edge) + } + /// Build a line segment from two vertices pub fn line_segment_from_vertices( self, From 0755bad8f55e64a5f9abe3864a755d83d220be2d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 18:19:21 +0200 Subject: [PATCH 4/7] Simplify tests --- fj-kernel/src/algorithms/approximation.rs | 17 ++++---------- fj-kernel/src/algorithms/sweep.rs | 28 ++++++++--------------- fj-kernel/src/shape/topology.rs | 6 ++--- 3 files changed, 16 insertions(+), 35 deletions(-) diff --git a/fj-kernel/src/algorithms/approximation.rs b/fj-kernel/src/algorithms/approximation.rs index bb5e5b42e..bdbd6d6fa 100644 --- a/fj-kernel/src/algorithms/approximation.rs +++ b/fj-kernel/src/algorithms/approximation.rs @@ -162,19 +162,10 @@ mod tests { let c = Point::from([3., 5., 8.]); let d = Point::from([5., 8., 13.]); - let v1 = Vertex::build(&mut shape).from_point(a)?; - let v2 = Vertex::build(&mut shape).from_point(b)?; - let v3 = Vertex::build(&mut shape).from_point(c)?; - let v4 = Vertex::build(&mut shape).from_point(d)?; - - let ab = Edge::build(&mut shape) - .line_segment_from_vertices([v1.clone(), v2.clone()])?; - let bc = Edge::build(&mut shape) - .line_segment_from_vertices([v2, v3.clone()])?; - let cd = Edge::build(&mut shape) - .line_segment_from_vertices([v3, v4.clone()])?; - let da = - Edge::build(&mut shape).line_segment_from_vertices([v4, v1])?; + let ab = Edge::build(&mut shape).line_segment_from_points([a, b])?; + let bc = Edge::build(&mut shape).line_segment_from_points([b, c])?; + let cd = Edge::build(&mut shape).line_segment_from_points([c, d])?; + let da = Edge::build(&mut shape).line_segment_from_points([d, a])?; let abcd = shape.insert(Cycle { edges: vec![ab, bc, cd, da], diff --git a/fj-kernel/src/algorithms/sweep.rs b/fj-kernel/src/algorithms/sweep.rs index d99be2976..68bfd9223 100644 --- a/fj-kernel/src/algorithms/sweep.rs +++ b/fj-kernel/src/algorithms/sweep.rs @@ -326,7 +326,7 @@ mod tests { use crate::{ geometry::{Surface, SweptCurve}, shape::{Handle, Shape}, - topology::{Cycle, Edge, Face, Vertex}, + topology::{Cycle, Edge, Face}, }; use super::sweep_shape; @@ -377,32 +377,24 @@ mod tests { } impl Triangle { - fn new([a, b, c]: [impl Into>; 3]) -> anyhow::Result { + fn new(points: [impl Into>; 3]) -> anyhow::Result { let mut shape = Shape::new(); - let a = shape.insert(a.into())?; - let b = shape.insert(b.into())?; - let c = shape.insert(c.into())?; + let [a, b, c] = points.map(|point| point.into()); - let a = shape.insert(Vertex { point: a })?; - let b = shape.insert(Vertex { point: b })?; - let c = shape.insert(Vertex { point: c })?; - - let ab = Edge::build(&mut shape) - .line_segment_from_vertices([a.clone(), b.clone()])?; - let bc = Edge::build(&mut shape) - .line_segment_from_vertices([b.clone(), c.clone()])?; - let ca = Edge::build(&mut shape) - .line_segment_from_vertices([c.clone(), a.clone()])?; + let ab = + Edge::build(&mut shape).line_segment_from_points([a, b])?; + let bc = + Edge::build(&mut shape).line_segment_from_points([b, c])?; + let ca = + Edge::build(&mut shape).line_segment_from_points([c, a])?; let cycles = shape.insert(Cycle { edges: vec![ab, bc, ca], })?; let surface = shape.insert(Surface::SweptCurve( - SweptCurve::plane_from_points( - [a, b, c].map(|vertex| vertex.get().point()), - ), + SweptCurve::plane_from_points([a, b, c]), ))?; let abc = Face::Face { surface, diff --git a/fj-kernel/src/shape/topology.rs b/fj-kernel/src/shape/topology.rs index ec63bdca5..e95622f02 100644 --- a/fj-kernel/src/shape/topology.rs +++ b/fj-kernel/src/shape/topology.rs @@ -194,12 +194,10 @@ mod tests { let vertices = [(); 2].map(|()| { let point = self.next_point; self.next_point.x += Scalar::ONE; - - let point = self.insert(point).unwrap(); - self.insert(Vertex { point }).unwrap() + point }); let edge = Edge::build(&mut self.inner) - .line_segment_from_vertices(vertices)?; + .line_segment_from_points(vertices)?; Ok(edge) } From 354f374dd70afc04f2bc59411b53076a526af389 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 18:19:58 +0200 Subject: [PATCH 5/7] Update variable name --- fj-kernel/src/shape/topology.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fj-kernel/src/shape/topology.rs b/fj-kernel/src/shape/topology.rs index e95622f02..f18e852b5 100644 --- a/fj-kernel/src/shape/topology.rs +++ b/fj-kernel/src/shape/topology.rs @@ -191,13 +191,13 @@ mod tests { } fn add_edge(&mut self) -> anyhow::Result> { - let vertices = [(); 2].map(|()| { + let points = [(); 2].map(|()| { let point = self.next_point; self.next_point.x += Scalar::ONE; point }); let edge = Edge::build(&mut self.inner) - .line_segment_from_points(vertices)?; + .line_segment_from_points(points)?; Ok(edge) } From a1ab7617053ff68d8d34fa43829b5ab66807ef27 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 18:47:45 +0200 Subject: [PATCH 6/7] Add `CycleBuilder` --- fj-kernel/src/topology/builder.rs | 41 ++++++++++++++++++++++++++++++- fj-kernel/src/topology/edges.rs | 7 +++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/fj-kernel/src/topology/builder.rs b/fj-kernel/src/topology/builder.rs index 9e5949974..55ea4e906 100644 --- a/fj-kernel/src/topology/builder.rs +++ b/fj-kernel/src/topology/builder.rs @@ -5,7 +5,7 @@ use crate::{ shape::{Handle, Shape, ValidationResult}, }; -use super::{Edge, Vertex}; +use super::{Cycle, Edge, Vertex}; /// API for building a [`Vertex`] pub struct VertexBuilder<'r> { @@ -93,3 +93,42 @@ impl<'r> EdgeBuilder<'r> { Ok(edge) } } + +/// API for building a [`Cycle`] +pub struct CycleBuilder<'r> { + shape: &'r mut Shape, +} + +impl<'r> CycleBuilder<'r> { + /// Construct a new instance of `CycleBuilder` + pub fn new(shape: &'r mut Shape) -> Self { + Self { shape } + } + + /// Build a polygon from a list of points + pub fn polygon( + self, + points: impl IntoIterator>>, + ) -> ValidationResult { + // A polygon is closed, so we need to add the first point at the end + // again, for the next step. + let mut points: Vec<_> = points.into_iter().map(Into::into).collect(); + if let Some(point) = points.first().cloned() { + points.push(point); + } + + let mut edges = Vec::new(); + for ab in points.windows(2) { + // Can't panic, as we passed `2` to `windows`. + // + // Can be cleaned up, once `array_windows` is stable. + let points = [ab[0], ab[1]]; + + let edge = + Edge::build(self.shape).line_segment_from_points(points)?; + edges.push(edge); + } + + self.shape.insert(Cycle { edges }) + } +} diff --git a/fj-kernel/src/topology/edges.rs b/fj-kernel/src/topology/edges.rs index 7871481ba..cf5aad58c 100644 --- a/fj-kernel/src/topology/edges.rs +++ b/fj-kernel/src/topology/edges.rs @@ -5,7 +5,7 @@ use crate::{ shape::{Handle, Shape}, }; -use super::{vertices::Vertex, EdgeBuilder}; +use super::{builder::CycleBuilder, vertices::Vertex, EdgeBuilder}; /// A cycle of connected edges /// @@ -29,6 +29,11 @@ pub struct Cycle { } impl Cycle { + /// Build a cycle using the [`CycleBuilder`] API + pub fn build(shape: &mut Shape) -> CycleBuilder { + CycleBuilder::new(shape) + } + /// Access the edges that this cycle refers to /// /// This is a convenience method that saves the caller from dealing with the From cdf7b3c97da66dc10c7ad30c678785e4cda0ba9c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 18:48:04 +0200 Subject: [PATCH 7/7] Simplify test --- fj-kernel/src/algorithms/approximation.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/fj-kernel/src/algorithms/approximation.rs b/fj-kernel/src/algorithms/approximation.rs index bdbd6d6fa..047bb2fb6 100644 --- a/fj-kernel/src/algorithms/approximation.rs +++ b/fj-kernel/src/algorithms/approximation.rs @@ -120,7 +120,7 @@ mod tests { use crate::{ geometry::Surface, shape::Shape, - topology::{Cycle, Edge, Face, Vertex}, + topology::{Cycle, Face, Vertex}, }; use super::Approximation; @@ -162,14 +162,7 @@ mod tests { let c = Point::from([3., 5., 8.]); let d = Point::from([5., 8., 13.]); - let ab = Edge::build(&mut shape).line_segment_from_points([a, b])?; - let bc = Edge::build(&mut shape).line_segment_from_points([b, c])?; - let cd = Edge::build(&mut shape).line_segment_from_points([c, d])?; - let da = Edge::build(&mut shape).line_segment_from_points([d, a])?; - - let abcd = shape.insert(Cycle { - edges: vec![ab, bc, cd, da], - })?; + let abcd = Cycle::build(&mut shape).polygon([a, b, c, d])?; let surface = shape.insert(Surface::x_y_plane())?; let face = Face::Face {