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

Require surface coordinates when building faces or cycles #665

Merged
merged 3 commits into from
Jun 3, 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
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