Skip to content

Commit

Permalink
Merge pull request #1128 from hannobraun/ready/builder
Browse files Browse the repository at this point in the history
Clean up `HalfEdgeBuilder`, make it more flexible
  • Loading branch information
hannobraun authored Sep 21, 2022
2 parents 2c817c4 + 133575c commit afe7481
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 34 deletions.
12 changes: 8 additions & 4 deletions crates/fj-kernel/src/algorithms/intersect/curve_edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ mod tests {
let surface = Surface::xy_plane();
let curve = Curve::builder(&stores, surface).build_u_axis();
let half_edge = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[1., -1.], [1., 1.]]);
.as_line_segment_from_points([[1., -1.], [1., 1.]])
.build();

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);

Expand All @@ -107,7 +108,8 @@ mod tests {
let surface = Surface::xy_plane();
let curve = Curve::builder(&stores, surface).build_u_axis();
let half_edge = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[-1., -1.], [-1., 1.]]);
.as_line_segment_from_points([[-1., -1.], [-1., 1.]])
.build();

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);

Expand All @@ -126,7 +128,8 @@ mod tests {
let surface = Surface::xy_plane();
let curve = Curve::builder(&stores, surface).build_u_axis();
let half_edge = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[-1., -1.], [1., -1.]]);
.as_line_segment_from_points([[-1., -1.], [1., -1.]])
.build();

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);

Expand All @@ -140,7 +143,8 @@ mod tests {
let surface = Surface::xy_plane();
let curve = Curve::builder(&stores, surface).build_u_axis();
let half_edge = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[-1., 0.], [1., 0.]]);
.as_line_segment_from_points([[-1., 0.], [1., 0.]])
.build();

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);

Expand Down
15 changes: 10 additions & 5 deletions crates/fj-kernel/src/algorithms/sweep/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,23 +192,28 @@ mod tests {
let stores = Stores::new();

let half_edge = HalfEdge::builder(&stores, Surface::xy_plane())
.build_line_segment_from_points([[0., 0.], [1., 0.]]);
.as_line_segment_from_points([[0., 0.], [1., 0.]])
.build();

let face = (half_edge, Color::default()).sweep([0., 0., 1.], &stores);

let expected_face = {
let surface = Surface::xz_plane();

let bottom = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[0., 0.], [1., 0.]]);
.as_line_segment_from_points([[0., 0.], [1., 0.]])
.build();
let top = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[0., 1.], [1., 1.]])
.as_line_segment_from_points([[0., 1.], [1., 1.]])
.build()
.reverse();
let left = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[0., 0.], [0., 1.]])
.as_line_segment_from_points([[0., 0.], [0., 1.]])
.build()
.reverse();
let right = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[1., 0.], [1., 1.]]);
.as_line_segment_from_points([[1., 0.], [1., 1.]])
.build();

let cycle = Cycle::new(surface, [bottom, right, top, left]);

Expand Down
6 changes: 4 additions & 2 deletions crates/fj-kernel/src/algorithms/sweep/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ mod tests {
let [a, b] = [window[0], window[1]];

let half_edge = HalfEdge::builder(&stores, Surface::xy_plane())
.build_line_segment_from_points([a, b]);
.as_line_segment_from_points([a, b])
.build();
(half_edge, Color::default()).sweep(UP, &stores)
});

Expand Down Expand Up @@ -148,7 +149,8 @@ mod tests {
let [a, b] = [window[0], window[1]];

let half_edge = HalfEdge::builder(&stores, Surface::xy_plane())
.build_line_segment_from_points([a, b])
.as_line_segment_from_points([a, b])
.build()
.reverse();
(half_edge, Color::default()).sweep(DOWN, &stores)
});
Expand Down
3 changes: 2 additions & 1 deletion crates/fj-kernel/src/algorithms/sweep/vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ mod tests {
let half_edge = (vertex, surface).sweep([0., 0., 1.], &stores);

let expected_half_edge = HalfEdge::builder(&stores, surface)
.build_line_segment_from_points([[0., 0.], [0., 1.]]);
.as_line_segment_from_points([[0., 0.], [0., 1.]])
.build();
assert_eq!(half_edge, expected_half_edge);
}

Expand Down
6 changes: 4 additions & 2 deletions crates/fj-kernel/src/builder/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ impl<'a> CycleBuilder<'a> {

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

Expand All @@ -74,7 +75,8 @@ impl<'a> CycleBuilder<'a> {
[last, first].map(|vertex| vertex.surface_form().position());
self.half_edges.push(
HalfEdge::builder(self.stores, self.surface)
.build_line_segment_from_points(vertices),
.as_line_segment_from_points(vertices)
.build(),
);
}

Expand Down
74 changes: 58 additions & 16 deletions crates/fj-kernel/src/builder/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,50 @@ use crate::{
stores::Stores,
};

/// API for building an [`HalfEdge`]
/// API for building a [`HalfEdge`]
///
/// Also see [`HalfEdge::builder`].
pub struct HalfEdgeBuilder<'a> {
/// The stores that the created objects are put in
pub stores: &'a Stores,

/// The surface that the [`HalfEdge`] is defined in
/// The surface that the [`HalfEdge`]'s [`Curve`] is defined in
pub surface: Surface,

/// The curve that the [`HalfEdge`] is defined in
pub curve: Option<Curve>,

/// The vertices that bound this [`HalfEdge`] in the [`Curve`]
pub vertices: Option<[Vertex; 2]>,

/// The global form of the [`HalfEdge`]
///
/// Can be provided to the builder, if available, or computed by one of the
/// build methods.
pub global_form: Option<GlobalEdge>,
}

impl<'a> HalfEdgeBuilder<'a> {
/// Build a circle from the given radius
pub fn build_circle_from_radius(
self,
radius: impl Into<Scalar>,
) -> HalfEdge {
/// Build the [`HalfEdge`] with the given curve
pub fn with_curve(mut self, curve: Curve) -> Self {
self.curve = Some(curve);
self
}

/// Build the [`HalfEdge`] with the given vertices
pub fn with_vertices(mut self, vertices: [Vertex; 2]) -> Self {
self.vertices = Some(vertices);
self
}

/// Build the [`HalfEdge`] with the provided global form
pub fn with_global_form(mut self, global_form: GlobalEdge) -> Self {
self.global_form = Some(global_form);
self
}

/// Build the [`HalfEdge`] as a circle from the given radius
pub fn as_circle_from_radius(mut self, radius: impl Into<Scalar>) -> Self {
let curve = Curve::builder(self.stores, self.surface)
.build_circle_from_radius(radius);

Expand Down Expand Up @@ -57,17 +84,17 @@ impl<'a> HalfEdgeBuilder<'a> {
)
};

let global_form = GlobalEdge::builder()
.build_from_curve_and_vertices(&curve, &vertices);
self.curve = Some(curve);
self.vertices = Some(vertices);

HalfEdge::new(curve, vertices, global_form)
self
}

/// Build a line segment from two points
pub fn build_line_segment_from_points(
self,
/// Build the [`HalfEdge`] as a line segment from the given points
pub fn as_line_segment_from_points(
mut self,
points: [impl Into<Point<2>>; 2],
) -> HalfEdge {
) -> Self {
let points = points.map(Into::into);

let global_vertices = points.map(|position| {
Expand Down Expand Up @@ -124,8 +151,23 @@ impl<'a> HalfEdgeBuilder<'a> {
]
};

let global_form = GlobalEdge::builder()
.build_from_curve_and_vertices(&curve, &vertices);
self.curve = Some(curve);
self.vertices = Some(vertices);

self
}

/// Finish building the [`HalfEdge`]
pub fn build(self) -> HalfEdge {
let curve = self.curve.expect("Can't build `HalfEdge` without curve");
let vertices = self
.vertices
.expect("Can't build `HalfEdge` without vertices");

let global_form = self.global_form.unwrap_or_else(|| {
GlobalEdge::builder()
.build_from_curve_and_vertices(&curve, &vertices)
});

HalfEdge::new(curve, vertices, global_form)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/builder/vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl VertexBuilder {
self
}

/// Build a vertex from a curve position
/// Finish building the [`Vertex`]
pub fn build(self) -> Vertex {
let surface_form = self.surface_form.unwrap_or_else(|| {
SurfaceVertexBuilder {
Expand Down
3 changes: 2 additions & 1 deletion crates/fj-kernel/src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ mod tests {
let stores = Stores::new();

let object = HalfEdge::builder(&stores, Surface::xy_plane())
.build_line_segment_from_points([[0., 0.], [1., 0.]]);
.as_line_segment_from_points([[0., 0.], [1., 0.]])
.build();

assert_eq!(1, object.curve_iter().count());
assert_eq!(0, object.cycle_iter().count());
Expand Down
8 changes: 7 additions & 1 deletion crates/fj-kernel/src/objects/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ pub struct HalfEdge {
impl HalfEdge {
/// Build a `HalfEdge` using [`HalfEdgeBuilder`]
pub fn builder(stores: &Stores, surface: Surface) -> HalfEdgeBuilder {
HalfEdgeBuilder { stores, surface }
HalfEdgeBuilder {
stores,
surface,
curve: None,
vertices: None,
global_form: None,
}
}

/// Create a new instance of `HalfEdge`
Expand Down
3 changes: 2 additions & 1 deletion crates/fj-operations/src/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ impl Shape for fj::Sketch {
// none need to be added here.

let half_edge = HalfEdge::builder(stores, surface)
.build_circle_from_radius(circle.radius());
.as_circle_from_radius(circle.radius())
.build();
let cycle = Cycle::new(surface, [half_edge]);

Face::from_exterior(cycle).with_color(Color(self.color()))
Expand Down

0 comments on commit afe7481

Please sign in to comment.