Skip to content

Commit

Permalink
Merge pull request #1126 from hannobraun/ready/builder/cycle
Browse files Browse the repository at this point in the history
Clean up `CycleBuilder`, make it more flexible
hannobraun authored Sep 21, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 14de1ad + 239a208 commit b22d416
Showing 4 changed files with 68 additions and 18 deletions.
68 changes: 54 additions & 14 deletions crates/fj-kernel/src/builder/cycle.rs
Original file line number Diff line number Diff line change
@@ -14,35 +14,75 @@ pub struct CycleBuilder<'a> {

/// The surface that the [`Cycle`] is defined in
pub surface: Surface,

/// The half-edges that make up the [`Cycle`]
pub half_edges: Vec<HalfEdge>,
}

impl<'a> CycleBuilder<'a> {
/// Create a polygon from a list of points
pub fn build_polygon_from_points(
self,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Cycle {
let mut points: Vec<_> = points.into_iter().map(Into::into).collect();
/// Build the [`Cycle`] with the given half-edge
pub fn with_half_edges(
mut self,
half_edge: impl IntoIterator<Item = HalfEdge>,
) -> Self {
self.half_edges.extend(half_edge);
self
}

// A polygon is closed, so we need to add the first point at the end
// again, for the next step.
if let Some(point) = points.first().cloned() {
points.push(point);
}
/// Build the [`Cycle`] with a polygonal chain from the provided points
pub fn with_poly_chain_from_points(
mut self,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
let points = self
.half_edges
.last()
.map(|half_edge| {
let [_, last] = half_edge.vertices();
last.surface_form().position()
})
.into_iter()
.chain(points.into_iter().map(Into::into))
.collect::<Vec<_>>();

let mut half_edges = Vec::new();
for points in points.windows(2) {
// Can't panic, as we passed `2` to `windows`.
//
// Can be cleaned up, once `array_windows` is stable.
let points = [points[0], points[1]];

half_edges.push(
self.half_edges.push(
HalfEdge::builder(self.stores, self.surface)
.build_line_segment_from_points(points),
);
}

Cycle::new(self.surface, half_edges)
self
}

/// Close the [`Cycle`] with a line segment
///
/// Builds a line segment from the last and first vertex, closing the cycle.
pub fn close_with_line_segment(mut self) -> Self {
let first = self.half_edges.first();
let last = self.half_edges.last();

if let [Some([first, _]), Some([_, last])] = [first, last]
.map(|option| option.map(|half_edge| half_edge.vertices()))
{
let vertices =
[last, first].map(|vertex| vertex.surface_form().position());
self.half_edges.push(
HalfEdge::builder(self.stores, self.surface)
.build_line_segment_from_points(vertices),
);
}

self
}

/// Create a polygon from a list of points
pub fn build(self) -> Cycle {
Cycle::new(self.surface, self.half_edges)
}
}
8 changes: 6 additions & 2 deletions crates/fj-kernel/src/builder/face.rs
Original file line number Diff line number Diff line change
@@ -33,7 +33,9 @@ impl<'a> FaceBuilder<'a> {
) -> Self {
self.exterior = Some(
Cycle::builder(self.stores, self.surface)
.build_polygon_from_points(points),
.with_poly_chain_from_points(points)
.close_with_line_segment()
.build(),
);
self
}
@@ -45,7 +47,9 @@ impl<'a> FaceBuilder<'a> {
) -> Self {
self.interiors.push(
Cycle::builder(self.stores, self.surface)
.build_polygon_from_points(points),
.with_poly_chain_from_points(points)
.close_with_line_segment()
.build(),
);
self
}
4 changes: 3 additions & 1 deletion crates/fj-kernel/src/iter.rs
Original file line number Diff line number Diff line change
@@ -382,7 +382,9 @@ mod tests {
let stores = Stores::new();

let object = Cycle::builder(&stores, Surface::xy_plane())
.build_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]);
.with_poly_chain_from_points([[0., 0.], [1., 0.], [0., 1.]])
.close_with_line_segment()
.build();

assert_eq!(3, object.curve_iter().count());
assert_eq!(1, object.cycle_iter().count());
6 changes: 5 additions & 1 deletion crates/fj-kernel/src/objects/cycle.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,11 @@ pub struct Cycle {
impl Cycle {
/// Build a `Cycle` using [`CycleBuilder`]
pub fn builder(stores: &Stores, surface: Surface) -> CycleBuilder {
CycleBuilder { stores, surface }
CycleBuilder {
stores,
surface,
half_edges: Vec::new(),
}
}

/// Create a new cycle

0 comments on commit b22d416

Please sign in to comment.