Skip to content

Commit

Permalink
Merge pull request #665 from hannobraun/builder
Browse files Browse the repository at this point in the history
Require surface coordinates when building faces or cycles
  • Loading branch information
hannobraun authored Jun 3, 2022
2 parents a5456d2 + 89fd88d commit 4494207
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 38 deletions.
25 changes: 17 additions & 8 deletions crates/fj-kernel/src/algorithms/approx/faces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,30 @@ mod tests {

let mut shape = Shape::new();

let a = Point::from([0., 0., 0.]);
let b = Point::from([3., 0., 0.]);
let c = Point::from([3., 3., 0.]);
let d = Point::from([0., 3., 0.]);
let a = Point::from([0., 0.]);
let b = Point::from([3., 0.]);
let c = Point::from([3., 3.]);
let d = Point::from([0., 3.]);

let e = Point::from([1., 1., 0.]);
let f = Point::from([2., 1., 0.]);
let g = Point::from([2., 2., 0.]);
let h = Point::from([1., 2., 0.]);
let e = Point::from([1., 1.]);
let f = Point::from([2., 1.]);
let g = Point::from([2., 2.]);
let h = Point::from([1., 2.]);

let face = Face::builder(Surface::xy_plane(), &mut shape)
.with_exterior_polygon([a, b, c, d])
.with_interior_polygon([e, f, g, h])
.build()?;

let a = a.to_xyz();
let b = b.to_xyz();
let c = c.to_xyz();
let d = d.to_xyz();
let e = e.to_xyz();
let f = f.to_xyz();
let g = g.to_xyz();
let h = h.to_xyz();

let a = geometry::Point::new(a, a);
let b = geometry::Point::new(b, b);
let c = geometry::Point::new(c, c);
Expand Down
36 changes: 24 additions & 12 deletions crates/fj-kernel/src/algorithms/triangulation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,20 @@ mod tests {
fn simple() -> anyhow::Result<()> {
let mut shape = Shape::new();

let a = [0., 0., 0.];
let b = [2., 0., 0.];
let c = [2., 2., 0.];
let d = [0., 1., 0.];
let a = [0., 0.];
let b = [2., 0.];
let c = [2., 2.];
let d = [0., 1.];

Face::builder(Surface::xy_plane(), &mut shape)
.with_exterior_polygon([a, b, c, d])
.build()?;

let a = Point::from(a).to_xyz();
let b = Point::from(b).to_xyz();
let c = Point::from(c).to_xyz();
let d = Point::from(d).to_xyz();

let triangles = triangulate(shape)?;
assert!(triangles.contains_triangle([a, b, d]));
assert!(triangles.contains_triangle([b, c, d]));
Expand All @@ -117,15 +122,15 @@ mod tests {
fn simple_hole() -> anyhow::Result<()> {
let mut shape = Shape::new();

let a = [0., 0., 0.];
let b = [4., 0., 0.];
let c = [4., 4., 0.];
let d = [0., 4., 0.];
let a = [0., 0.];
let b = [4., 0.];
let c = [4., 4.];
let d = [0., 4.];

let e = [1., 1., 0.];
let f = [3., 1., 0.];
let g = [3., 3., 0.];
let h = [1., 2., 0.];
let e = [1., 1.];
let f = [3., 1.];
let g = [3., 3.];
let h = [1., 2.];

Face::builder(Surface::xy_plane(), &mut shape)
.with_exterior_polygon([a, b, c, d])
Expand All @@ -134,6 +139,13 @@ mod tests {

let triangles = triangulate(shape)?;

let a = Point::from(a).to_xyz();
let d = Point::from(d).to_xyz();
let e = Point::from(e).to_xyz();
let f = Point::from(f).to_xyz();
let g = Point::from(g).to_xyz();
let h = Point::from(h).to_xyz();

// Should contain some triangles from the polygon. Don't need to test
// them all.
assert!(triangles.contains_triangle([a, e, h]));
Expand Down
26 changes: 16 additions & 10 deletions crates/fj-kernel/src/topology/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,25 @@ impl<'r> EdgeBuilder<'r> {
/// API for building a [`Cycle`]
#[must_use]
pub struct CycleBuilder<'r> {
surface: Surface,
shape: &'r mut Shape,
}

impl<'r> CycleBuilder<'r> {
/// Construct a new instance of `CycleBuilder`
pub fn new(shape: &'r mut Shape) -> Self {
Self { shape }
pub fn new(surface: Surface, shape: &'r mut Shape) -> Self {
Self { surface, shape }
}

/// Build a polygon from a list of points
pub fn build_polygon(
self,
points: impl IntoIterator<Item = impl Into<Point<3>>>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> ValidationResult<Cycle<3>> {
let mut points: Vec<_> = points.into_iter().map(Into::into).collect();
let mut points: Vec<_> = points
.into_iter()
.map(|point| self.surface.point_from_surface_coords(point))
.collect();

// A polygon is closed, so we need to add the first point at the end
// again, for the next step.
Expand Down Expand Up @@ -144,8 +148,8 @@ impl<'r> CycleBuilder<'r> {
#[must_use]
pub struct FaceBuilder<'r> {
surface: Surface,
exterior: Option<Vec<Point<3>>>,
interiors: Vec<Vec<Point<3>>>,
exterior: Option<Vec<Point<2>>>,
interiors: Vec<Vec<Point<2>>>,

shape: &'r mut Shape,
}
Expand All @@ -165,7 +169,7 @@ impl<'r> FaceBuilder<'r> {
/// Make the exterior or the face a polygon
pub fn with_exterior_polygon(
self,
points: impl IntoIterator<Item = impl Into<Point<3>>>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
let points = points.into_iter().map(Into::into).collect();

Expand All @@ -178,7 +182,7 @@ impl<'r> FaceBuilder<'r> {
/// Add an interior polygon to the face
pub fn with_interior_polygon(
self,
points: impl IntoIterator<Item = impl Into<Point<3>>>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
let points = points.into_iter().map(Into::into).collect();

Expand All @@ -194,13 +198,15 @@ impl<'r> FaceBuilder<'r> {

let mut exteriors = Vec::new();
if let Some(points) = self.exterior {
let cycle = Cycle::builder(self.shape).build_polygon(points)?;
let cycle = Cycle::builder(self.surface, self.shape)
.build_polygon(points)?;
exteriors.push(cycle);
}

let mut interiors = Vec::new();
for points in self.interiors {
let cycle = Cycle::builder(self.shape).build_polygon(points)?;
let cycle = Cycle::builder(self.surface, self.shape)
.build_polygon(points)?;
interiors.push(cycle);
}

Expand Down
9 changes: 6 additions & 3 deletions crates/fj-kernel/src/topology/cycle.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::shape::{Handle, LocalForm, Shape};
use crate::{
geometry::Surface,
shape::{Handle, LocalForm, Shape},
};

use super::{CycleBuilder, Edge};

Expand Down Expand Up @@ -32,8 +35,8 @@ impl Cycle<3> {
}

/// Build a cycle using the [`CycleBuilder`] API
pub fn builder(shape: &mut Shape) -> CycleBuilder {
CycleBuilder::new(shape)
pub fn builder(surface: Surface, shape: &mut Shape) -> CycleBuilder {
CycleBuilder::new(surface, shape)
}

/// Access the edges that this cycle refers to
Expand Down
6 changes: 1 addition & 5 deletions crates/fj-operations/src/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ impl ToShape for fj::Sketch {
let mut shape = Shape::new();

let surface = Surface::xy_plane();
let points = self
.to_points()
.into_iter()
.map(Point::from)
.map(|point| surface.point_from_surface_coords(point));
let points = self.to_points().into_iter().map(Point::from);

Face::builder(surface, &mut shape)
.with_exterior_polygon(points)
Expand Down

0 comments on commit 4494207

Please sign in to comment.