Skip to content

Commit

Permalink
Merge pull request #1457 from hannobraun/builder
Browse files Browse the repository at this point in the history
Continue cleaning up builder API
  • Loading branch information
hannobraun authored Dec 16, 2022
2 parents 6d5cf8f + be09ca5 commit 79bb37a
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 35 deletions.
78 changes: 54 additions & 24 deletions crates/fj-kernel/src/builder/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ use super::HalfEdgeBuilder;
/// Builder API for [`PartialCycle`]
pub trait CycleBuilder {
/// Create a cycle as a polygonal chain from the provided points
fn update_as_polygon(
fn update_as_polygon_from_points(
&mut self,
surface: impl Into<Partial<Surface>>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Vec<Partial<HalfEdge>>;

/// Update cycle to be a polygon
///
/// Will update each half-edge in the cycle to be a line segment.
fn update_as_polygon(&mut self);

/// Add a new half-edge to the cycle
///
/// Creates a half-edge and adds it to the cycle. The new half-edge is
Expand All @@ -26,41 +31,52 @@ pub trait CycleBuilder {
/// If this is the first half-edge being added, it is connected to itself,
/// meaning its front and back vertices are the same.
fn add_half_edge(&mut self) -> Partial<HalfEdge>;

/// Add a new half-edge that starts at the provided point
///
/// Opens the cycle between the last and first edge, updates the last edge
/// to go the provided point, and adds a new half-edge from the provided
/// point the the first edge.
///
/// If the cycle doesn't have any edges yet, the new edge connects to
/// itself, starting and ending at the provided point.
fn add_half_edge_from_point_to_start(
&mut self,
point: impl Into<Point<2>>,
) -> Partial<HalfEdge>;
}

impl CycleBuilder for PartialCycle {
fn update_as_polygon(
fn update_as_polygon_from_points(
&mut self,
surface: impl Into<Partial<Surface>>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Vec<Partial<HalfEdge>> {
let surface = surface.into();
let mut points = points.into_iter().map(Into::into);

let mut half_edges = Vec::new();

for point in points.into_iter().map(Into::into) {
let mut half_edge = self.add_half_edge();

{
let mut half_edge = half_edge.write();

half_edge.curve().write().surface = surface.clone();

let mut back = half_edge.back_mut().write();
let mut back_surface = back.surface_form.write();

back_surface.position = Some(point);
back_surface.surface = surface.clone();
}
if let Some(point) = points.next() {
let mut half_edge = self.add_half_edge_from_point_to_start(point);
half_edge.write().replace_surface(surface);
half_edges.push(half_edge);
}

for point in points {
let half_edge = self.add_half_edge_from_point_to_start(point);
half_edges.push(half_edge);
}

self.update_as_polygon();

half_edges
}

fn update_as_polygon(&mut self) {
for half_edge in &mut self.half_edges {
half_edge.write().update_as_line_segment();
}

half_edges
}

fn add_half_edge(&mut self) -> Partial<HalfEdge> {
Expand All @@ -81,34 +97,48 @@ impl CycleBuilder for PartialCycle {
None => (new_half_edge.clone(), new_half_edge.clone()),
};

let shared_surface =
first_half_edge.read().curve().read().surface.clone();

{
let shared_surface_vertex =
new_half_edge.read().back().read().surface_form.clone();

let mut last_half_edge = last_half_edge.write();
last_half_edge.curve().write().surface = shared_surface.clone();

last_half_edge.front_mut().write().surface_form =
shared_surface_vertex;

last_half_edge.infer_global_form();
}

{
let shared_surface_vertex =
first_half_edge.read().back().read().surface_form.clone();
let shared_surface = shared_surface_vertex.read().surface.clone();

let mut new_half_edge = new_half_edge.write();

new_half_edge.curve().write().surface = shared_surface;
new_half_edge.front_mut().write().surface_form =
shared_surface_vertex;
new_half_edge.replace_surface(shared_surface);
new_half_edge.infer_global_form();
}

self.half_edges.push(new_half_edge.clone());
new_half_edge
}

fn add_half_edge_from_point_to_start(
&mut self,
point: impl Into<Point<2>>,
) -> Partial<HalfEdge> {
let mut half_edge = self.add_half_edge();

half_edge
.write()
.back_mut()
.write()
.surface_form
.write()
.position = Some(point.into());

half_edge
}
}
20 changes: 19 additions & 1 deletion crates/fj-kernel/src/builder/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@ use crate::{
partial::{Partial, PartialGlobalEdge, PartialHalfEdge},
};

use super::CurveBuilder;
use super::{CurveBuilder, VertexBuilder};

/// Builder API for [`PartialHalfEdge`]
pub trait HalfEdgeBuilder {
/// Completely replace the surface in this half-edge's object graph
///
/// Please note that this operation will write to both vertices that the
/// half-edge references. If any of them were created from full objects,
/// this will break the connection to those, meaning that building the
/// partial objects won't result in those full objects again. This will be
/// the case, even if those full objects already referenced the provided
/// surface.
fn replace_surface(&mut self, surface: impl Into<Partial<Surface>>);

/// Update partial half-edge to be a circle, from the given radius
fn update_as_circle_from_radius(&mut self, radius: impl Into<Scalar>);

Expand All @@ -31,6 +41,14 @@ pub trait HalfEdgeBuilder {
}

impl HalfEdgeBuilder for PartialHalfEdge {
fn replace_surface(&mut self, surface: impl Into<Partial<Surface>>) {
let surface = surface.into();

for vertex in &mut self.vertices {
vertex.write().replace_surface(surface.clone());
}
}

fn update_as_circle_from_radius(&mut self, radius: impl Into<Scalar>) {
let mut curve = self.curve();
curve.write().update_as_circle_from_radius(radius);
Expand Down
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/builder/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl FaceBuilder for PartialFace {
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Vec<Partial<HalfEdge>> {
let mut cycle = PartialCycle::default();
let half_edges = cycle.update_as_polygon(surface, points);
let half_edges = cycle.update_as_polygon_from_points(surface, points);

self.exterior = Partial::from_partial(cycle);

Expand All @@ -44,7 +44,7 @@ impl FaceBuilder for PartialFace {
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) {
let mut cycle = PartialCycle::default();
cycle.update_as_polygon(surface, points);
cycle.update_as_polygon_from_points(surface, points);

self.interiors.push(Partial::from_partial(cycle));
}
Expand Down
27 changes: 22 additions & 5 deletions crates/fj-kernel/src/builder/vertex.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
use fj_math::Point;

use crate::partial::{
PartialGlobalVertex, PartialSurfaceVertex, PartialVertex,
use crate::{
objects::Surface,
partial::{
Partial, PartialGlobalVertex, PartialSurfaceVertex, PartialVertex,
},
};

/// Builder API for [`PartialVertex`]
pub trait VertexBuilder {
// No methods are currently defined. This trait serves as a placeholder, to
// make it clear where to add such methods, once necessary.
/// Completely replace the surface in this vertex' object graph
///
/// Please note that this operation will write to every partial object that
/// the vertex references. If any of them were created from full objects,
/// this will break the connection to those, meaning that building the
/// partial objects won't result in those full objects again. This will be
/// the case, even if those full objects already referenced the provided
/// surface.
fn replace_surface(&mut self, surface: impl Into<Partial<Surface>>);
}

impl VertexBuilder for PartialVertex {}
impl VertexBuilder for PartialVertex {
fn replace_surface(&mut self, surface: impl Into<Partial<Surface>>) {
let surface = surface.into();

self.curve.write().surface = surface.clone();
self.surface_form.write().surface = surface;
}
}

/// Builder API for [`PartialSurfaceVertex`]
pub trait SurfaceVertexBuilder {
Expand Down
5 changes: 4 additions & 1 deletion crates/fj-kernel/src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,10 @@ mod tests {
let surface = services.objects.surfaces.xy_plane();
let object = {
let mut cycle = PartialCycle::default();
cycle.update_as_polygon(surface, [[0., 0.], [1., 0.], [0., 1.]]);
cycle.update_as_polygon_from_points(
surface,
[[0., 0.], [1., 0.], [0., 1.]],
);
cycle
.build(&mut services.objects)
.insert(&mut services.objects)
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/validate/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ mod tests {

let valid = {
let mut cycle = PartialCycle::default();
cycle.update_as_polygon(
cycle.update_as_polygon_from_points(
services.objects.surfaces.xy_plane(),
[[0., 0.], [1., 0.], [0., 1.]],
);
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/validate/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ mod tests {
};
let invalid = {
let mut cycle = PartialCycle::default();
cycle.update_as_polygon(
cycle.update_as_polygon_from_points(
services.objects.surfaces.xz_plane(),
[[1., 1.], [1., 2.], [2., 1.]],
);
Expand Down

0 comments on commit 79bb37a

Please sign in to comment.