Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up HalfEdgeBuilder, make it more flexible #1128

Merged
merged 7 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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