Skip to content

Commit

Permalink
Merge pull request #866 from hannobraun/builder
Browse files Browse the repository at this point in the history
Add new builder API
  • Loading branch information
hannobraun authored Jul 22, 2022
2 parents 02d53b0 + e294b31 commit 8cb928b
Show file tree
Hide file tree
Showing 18 changed files with 358 additions and 226 deletions.
14 changes: 4 additions & 10 deletions crates/fj-kernel/src/algorithms/approx/faces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ mod tests {

use crate::{
local::Local,
objects::{Cycle, Face, Surface},
objects::{Face, Surface},
};

use super::{CycleApprox, FaceApprox, Tolerance};
Expand All @@ -107,15 +107,9 @@ mod tests {
let h = Point::from([1., 2.]);

let surface = Surface::xy_plane();
let face = Face::new(surface)
.with_exteriors([Cycle::polygon_from_points(
&surface,
[a, b, c, d],
)])
.with_interiors([Cycle::polygon_from_points(
&surface,
[e, f, g, h],
)]);
let face = Face::build(surface)
.polygon_from_points([a, b, c, d])
.with_hole([e, f, g, h]);

let a = Local::new(a, a.to_xyz());
let b = Local::new(b, b.to_xyz());
Expand Down
8 changes: 4 additions & 4 deletions crates/fj-kernel/src/algorithms/intersection/curve_face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub type CurveFaceIntersection = [Scalar; 2];
mod tests {
use fj_math::{Line, Point, Vector};

use crate::objects::{Curve, Cycle, Face, Surface};
use crate::objects::{Curve, Face, Surface};

use super::CurveFaceIntersectionList;

Expand All @@ -211,9 +211,9 @@ mod tests {
];

let surface = Surface::xy_plane();
let face = Face::new(surface)
.with_exteriors([Cycle::polygon_from_points(&surface, exterior)])
.with_interiors([Cycle::polygon_from_points(&surface, interior)]);
let face = Face::build(surface)
.polygon_from_points(exterior)
.with_hole(interior);

let expected =
CurveFaceIntersectionList::from_intervals([[1., 2.], [4., 5.]]);
Expand Down
20 changes: 9 additions & 11 deletions crates/fj-kernel/src/algorithms/reverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,23 @@ fn reverse_local_coordinates_in_cycle<'r>(
mod tests {
use pretty_assertions::assert_eq;

use crate::objects::{Cycle, Face, Surface};
use crate::objects::{Face, Surface};

#[test]
fn reverse_face() {
let surface = Surface::xy_plane();
let original =
Face::new(surface).with_exteriors([Cycle::polygon_from_points(
&surface,
[[0., 0.], [1., 0.], [0., 1.]],
)]);
let original = Face::build(surface).polygon_from_points([
[0., 0.],
[1., 0.],
[0., 1.],
]);

let reversed = super::reverse_face(&original);

let surface = Surface::xy_plane().reverse();
let expected =
Face::new(surface).with_exteriors([Cycle::polygon_from_points(
&surface,
[[0., 0.], [1., 0.], [0., -1.]],
)]);
let expected = Face::build(surface)
.polygon_from_points([[0., 0.], [1., 0.], [0., -1.]])
.into_face();

assert_eq!(expected, reversed);
}
Expand Down
19 changes: 9 additions & 10 deletions crates/fj-kernel/src/algorithms/sweep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ mod tests {
use crate::{
algorithms::Tolerance,
iter::ObjectIters,
objects::{Cycle, Face, Sketch, Surface},
objects::{Face, Sketch, Surface},
};

#[test]
Expand Down Expand Up @@ -295,11 +295,11 @@ mod tests {
let tolerance = Tolerance::from_scalar(Scalar::ONE)?;

let surface = Surface::xy_plane();
let face =
Face::new(surface).with_exteriors([Cycle::polygon_from_points(
&surface,
[[0., 0.], [1., 0.], [0., 1.]],
)]);
let face = Face::build(surface).polygon_from_points([
[0., 0.],
[1., 0.],
[0., 1.],
]);
let sketch = Sketch::from_faces([face]);

let solid =
Expand All @@ -313,10 +313,9 @@ mod tests {
let faces = expected_surfaces.into_iter().map(|surface| {
let surface = Surface::plane_from_points(surface);

Face::new(surface).with_exteriors([Cycle::polygon_from_points(
&surface,
expected_vertices.clone(),
)])
Face::build(surface)
.polygon_from_points(expected_vertices.clone())
.into_face()
});

for face in faces {
Expand Down
34 changes: 12 additions & 22 deletions crates/fj-kernel/src/algorithms/triangulate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ mod tests {

use crate::{
algorithms::Tolerance,
objects::{Cycle, Face, Surface},
objects::{Face, Surface},
};

#[test]
Expand All @@ -78,11 +78,7 @@ mod tests {
let d = [0., 1.];

let surface = Surface::xy_plane();
let face =
Face::new(surface).with_exteriors([Cycle::polygon_from_points(
&surface,
[a, b, c, d],
)]);
let face = Face::build(surface).polygon_from_points([a, b, c, d]);

let a = Point::from(a).to_xyz();
let b = Point::from(b).to_xyz();
Expand Down Expand Up @@ -112,15 +108,9 @@ mod tests {
let h = [1., 2.];

let surface = Surface::xy_plane();
let face = Face::new(surface)
.with_exteriors([Cycle::polygon_from_points(
&surface,
[a, b, c, d],
)])
.with_interiors([Cycle::polygon_from_points(
&surface,
[e, f, g, h],
)]);
let face = Face::build(surface)
.polygon_from_points([a, b, c, d])
.with_hole([e, f, g, h]);

let triangles = triangulate(face)?;

Expand Down Expand Up @@ -168,11 +158,7 @@ mod tests {
let e = Point::from([0., 0.8]);

let surface = Surface::xy_plane();
let face =
Face::new(surface).with_exteriors([Cycle::polygon_from_points(
&surface,
[a, b, c, d, e],
)]);
let face = Face::build(surface).polygon_from_points([a, b, c, d, e]);

let triangles = triangulate(face)?;

Expand All @@ -191,10 +177,14 @@ mod tests {
Ok(())
}

fn triangulate(face: Face) -> anyhow::Result<Mesh<Point<3>>> {
fn triangulate(face: impl Into<Face>) -> anyhow::Result<Mesh<Point<3>>> {
let tolerance = Tolerance::from_scalar(Scalar::ONE)?;

let mut debug_info = DebugInfo::new();
Ok(super::triangulate(vec![face], tolerance, &mut debug_info))
Ok(super::triangulate(
vec![face.into()],
tolerance,
&mut debug_info,
))
}
}
45 changes: 45 additions & 0 deletions crates/fj-kernel/src/builder/cycle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use fj_math::Point;

use crate::objects::{Cycle, Edge, Surface};

/// API for building a [`Cycle`]
pub struct CycleBuilder {
surface: Surface,
}

impl CycleBuilder {
/// Construct an instance of `CycleBuilder`
///
/// Also see [`Cycle::build`].
pub fn new(surface: Surface) -> Self {
Self { surface }
}

/// Create a polygon from a list of points
pub fn polygon_from_points(
&self,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Cycle {
let mut points: Vec<_> = points.into_iter().map(Into::into).collect();

// 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);
}

let mut 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]];

edges.push(
Edge::build().line_segment_from_points(&self.surface, points),
);
}

Cycle::new().with_edges(edges)
}
}
64 changes: 64 additions & 0 deletions crates/fj-kernel/src/builder/edge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use fj_math::{Circle, Line, Point, Scalar, Vector};

use crate::{
local::Local,
objects::{Curve, Edge, GlobalVertex, Surface, Vertex, VerticesOfEdge},
};

/// API for building an [`Edge`]
pub struct EdgeBuilder;

impl EdgeBuilder {
/// Create a circle from the given radius
pub fn circle_from_radius(&self, radius: Scalar) -> Edge {
let curve_local = Curve::Circle(Circle {
center: Point::origin(),
a: Vector::from([radius, Scalar::ZERO]),
b: Vector::from([Scalar::ZERO, radius]),
});
let curve_canonical = Curve::Circle(Circle {
center: Point::origin(),
a: Vector::from([radius, Scalar::ZERO, Scalar::ZERO]),
b: Vector::from([Scalar::ZERO, radius, Scalar::ZERO]),
});

Edge::new(
Local::new(curve_local, curve_canonical),
VerticesOfEdge::none(),
)
}

/// Create a line segment from two points
pub fn line_segment_from_points(
&self,
surface: &Surface,
points: [impl Into<Point<2>>; 2],
) -> Edge {
let points = points.map(Into::into);

let global_vertices = points.map(|position| {
let position = surface.point_from_surface_coords(position);
GlobalVertex::from_position(position)
});

let curve_local = Curve::Line(Line::from_points(points));
let curve_canonical = {
let points =
global_vertices.map(|global_vertex| global_vertex.position());
Curve::Line(Line::from_points(points))
};

let vertices = {
let [a, b] = global_vertices;
[
Vertex::new(Point::from([0.]), a),
Vertex::new(Point::from([1.]), b),
]
};

Edge::new(
Local::new(curve_local, curve_canonical),
VerticesOfEdge::from_vertices(vertices),
)
}
}
72 changes: 72 additions & 0 deletions crates/fj-kernel/src/builder/face.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::ops::Deref;

use fj_math::Point;

use crate::objects::{Cycle, Face, Surface};

/// API for building a [`Face`]
pub struct FaceBuilder {
surface: Surface,
}

impl FaceBuilder {
/// Construct an instance of `FaceBuilder`
///
/// Also see [`Face::build`].
pub fn new(surface: Surface) -> Self {
Self { surface }
}

/// Construct a polygon from a list of points
pub fn polygon_from_points(
&self,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> FacePolygon {
let face = Face::new(self.surface)
.with_exteriors([
Cycle::build(self.surface).polygon_from_points(points)
]);

FacePolygon { face }
}
}

/// A polygon
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct FacePolygon {
face: Face,
}

impl FacePolygon {
/// Add a hole to the polygon
pub fn with_hole(
mut self,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
let surface = *self.face.surface();
self.face = self.face.with_interiors([
Cycle::build(surface).polygon_from_points(points)
]);

self
}

/// Consume the `Polygon` and return the [`Face`] it wraps
pub fn into_face(self) -> Face {
self.face
}
}

impl From<FacePolygon> for Face {
fn from(polygon: FacePolygon) -> Self {
polygon.into_face()
}
}

impl Deref for FacePolygon {
type Target = Face;

fn deref(&self) -> &Self::Target {
&self.face
}
}
13 changes: 13 additions & 0 deletions crates/fj-kernel/src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! API for building objects
mod cycle;
mod edge;
mod face;
mod solid;

pub use self::{
cycle::CycleBuilder,
edge::EdgeBuilder,
face::{FaceBuilder, FacePolygon},
solid::SolidBuilder,
};
Loading

0 comments on commit 8cb928b

Please sign in to comment.