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

Extract build operations from builder API #1718

Merged
merged 7 commits into from
Mar 23, 2023
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
46 changes: 3 additions & 43 deletions crates/fj-kernel/src/builder/face.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use fj_interop::{ext::ArrayExt, mesh::Color};
use fj_math::Point;
use fj_interop::mesh::Color;

use crate::{
objects::{Cycle, Face, GlobalEdge, Objects, Surface},
objects::{Face, Objects, Surface},
operations::Insert,
services::Service,
storage::Handle,
};

use super::{CycleBuilder, HalfEdgeBuilder, SurfaceBuilder};
use super::CycleBuilder;

/// Builder API for [`Face`]
pub struct FaceBuilder {
Expand All @@ -28,45 +27,6 @@ impl FaceBuilder {
}
}

/// Create a triangle
pub fn triangle(
points: [impl Into<Point<3>>; 3],
edges: [Option<Handle<GlobalEdge>>; 3],
objects: &mut Service<Objects>,
) -> (Handle<Face>, [Handle<GlobalEdge>; 3]) {
let [a, b, c] = points.map(Into::into);

let surface =
SurfaceBuilder::plane_from_points([a, b, c]).insert(objects);
let (exterior, global_edges) = {
let half_edges = [[a, b], [b, c], [c, a]].zip_ext(edges).map(
|(points, global_form)| {
let mut builder =
HalfEdgeBuilder::line_segment_from_global_points(
points, &surface, None,
);

if let Some(global_form) = global_form {
builder = builder.with_global_form(global_form);
}

builder.build(objects).insert(objects)
},
);

let cycle = Cycle::new(half_edges.clone()).insert(objects);

let global_edges =
half_edges.map(|half_edge| half_edge.global_form().clone());

(cycle, global_edges)
};

let face = Face::new(surface, exterior, [], None).insert(objects);

(face, global_edges)
}

/// Replace the face's exterior cycle
pub fn with_exterior(mut self, exterior: CycleBuilder) -> Self {
self.exterior = exterior;
Expand Down
7 changes: 1 addition & 6 deletions crates/fj-kernel/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,5 @@
mod cycle;
mod edge;
mod face;
mod shell;
mod surface;

pub use self::{
cycle::CycleBuilder, edge::HalfEdgeBuilder, face::FaceBuilder,
shell::ShellBuilder, surface::SurfaceBuilder,
};
pub use self::{cycle::CycleBuilder, edge::HalfEdgeBuilder, face::FaceBuilder};
38 changes: 0 additions & 38 deletions crates/fj-kernel/src/builder/shell.rs

This file was deleted.

66 changes: 66 additions & 0 deletions crates/fj-kernel/src/operations/build/face.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use fj_interop::ext::ArrayExt;
use fj_math::Point;

use crate::{
builder::HalfEdgeBuilder,
objects::{Cycle, Face, GlobalEdge, Objects, Surface},
operations::Insert,
services::Service,
storage::Handle,
};

use super::BuildSurface;

/// Build a [`Face`]
pub trait BuildFace {
/// Build a triangle
fn triangle(
points: [impl Into<Point<3>>; 3],
edges: [Option<Handle<GlobalEdge>>; 3],
objects: &mut Service<Objects>,
) -> Triangle {
let [a, b, c] = points.map(Into::into);

let surface = Surface::plane_from_points([a, b, c]).insert(objects);
let (exterior, edges) = {
let half_edges = [[a, b], [b, c], [c, a]].zip_ext(edges).map(
|(points, global_form)| {
let mut builder =
HalfEdgeBuilder::line_segment_from_global_points(
points, &surface, None,
);

if let Some(global_form) = global_form {
builder = builder.with_global_form(global_form);
}

builder.build(objects).insert(objects)
},
);

let cycle = Cycle::new(half_edges.clone()).insert(objects);

let global_edges =
half_edges.map(|half_edge| half_edge.global_form().clone());

(cycle, global_edges)
};

let face = Face::new(surface, exterior, [], None);

Triangle { face, edges }
}
}

impl BuildFace for Face {}

/// A triangle
///
/// Returned by [`BuildFace::triangle`].
pub struct Triangle {
/// The face that forms the triangle
pub face: Face,

/// The edges of the triangle
pub edges: [Handle<GlobalEdge>; 3],
}
9 changes: 9 additions & 0 deletions crates/fj-kernel/src/operations/build/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod face;
mod shell;
mod surface;

pub use self::{
face::{BuildFace, Triangle},
shell::BuildShell,
surface::BuildSurface,
};
41 changes: 41 additions & 0 deletions crates/fj-kernel/src/operations/build/shell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use fj_math::Point;

use crate::{
objects::{Face, Objects, Shell},
operations::Insert,
services::Service,
};

use super::{BuildFace, Triangle};

/// Build a [`Shell`]
pub trait BuildShell {
/// Build a tetrahedron from the provided points
fn tetrahedron(
points: [impl Into<Point<3>>; 4],
objects: &mut Service<Objects>,
) -> Shell {
let [a, b, c, d] = points.map(Into::into);

let Triangle {
face: base,
edges: [ab, bc, ca],
} = Face::triangle([a, b, c], [None, None, None], objects);
let Triangle {
face: side_a,
edges: [_, bd, da],
} = Face::triangle([a, b, d], [Some(ab), None, None], objects);
let Triangle {
face: side_b,
edges: [_, _, dc],
} = Face::triangle([c, a, d], [Some(ca), Some(da), None], objects);
let Triangle { face: side_c, .. } =
Face::triangle([b, c, d], [Some(bc), Some(dc), Some(bd)], objects);

let faces =
[base, side_a, side_b, side_c].map(|face| face.insert(objects));
Shell::new(faces)
}
}

impl BuildShell for Shell {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ use crate::{
objects::Surface,
};

/// Builder API for [`Surface`]
pub struct SurfaceBuilder {}

impl SurfaceBuilder {
/// Create a plane from the provided points
pub fn plane_from_points(points: [impl Into<Point<3>>; 3]) -> Surface {
/// Build a [`Surface`]
pub trait BuildSurface {
/// Build a plane from the provided points
fn plane_from_points(points: [impl Into<Point<3>>; 3]) -> Surface {
let [a, b, c] = points.map(Into::into);

let geometry = SurfaceGeometry {
Expand All @@ -21,3 +19,5 @@ impl SurfaceBuilder {
Surface::new(geometry)
}
}

impl BuildSurface for Surface {}
6 changes: 5 additions & 1 deletion crates/fj-kernel/src/operations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! Operations to update shapes

mod build;
mod insert;

pub use self::insert::Insert;
pub use self::{
build::{BuildFace, BuildShell, BuildSurface, Triangle},
insert::Insert,
};
8 changes: 4 additions & 4 deletions crates/fj-kernel/src/validate/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ impl ShellValidationError {
mod tests {
use crate::{
assert_contains_err,
builder::{CycleBuilder, FaceBuilder, ShellBuilder},
builder::{CycleBuilder, FaceBuilder},
objects::Shell,
operations::Insert,
operations::{BuildShell, Insert},
services::Services,
validate::{shell::ShellValidationError, Validate, ValidationError},
};
Expand All @@ -204,7 +204,7 @@ mod tests {
fn coincident_not_identical() -> anyhow::Result<()> {
let mut services = Services::new();

let valid = ShellBuilder::tetrahedron(
let valid = Shell::tetrahedron(
[[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
&mut services.objects,
);
Expand Down Expand Up @@ -246,7 +246,7 @@ mod tests {
fn shell_not_watertight() -> anyhow::Result<()> {
let mut services = Services::new();

let valid = ShellBuilder::tetrahedron(
let valid = Shell::tetrahedron(
[[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
&mut services.objects,
);
Expand Down