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

Simplify Cycle #756

Merged
merged 7 commits into from
Jun 30, 2022
Merged
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
10 changes: 3 additions & 7 deletions crates/fj-kernel/src/algorithms/approx/cycles.rs
Original file line number Diff line number Diff line change
@@ -16,17 +16,13 @@ impl CycleApprox {
///
/// `tolerance` defines how far the approximation is allowed to deviate from
/// the actual face.
pub fn new(cycle: &Cycle<2>, tolerance: Tolerance) -> Self {
pub fn new(cycle: &Cycle, tolerance: Tolerance) -> Self {
let mut points = Vec::new();

for edge in &cycle.edges {
let mut edge_points = Vec::new();
approx_curve(
&edge.canonical().curve(),
tolerance,
&mut edge_points,
);
approx_edge(edge.canonical().vertices.clone(), &mut edge_points);
approx_curve(&edge.curve(), tolerance, &mut edge_points);
approx_edge(edge.vertices.clone(), &mut edge_points);

points.extend(edge_points);
}
12 changes: 6 additions & 6 deletions crates/fj-kernel/src/algorithms/reverse.rs
Original file line number Diff line number Diff line change
@@ -24,14 +24,14 @@ pub fn reverse_face(face: &Face) -> Face {

fn reverse_local_coordinates_in_cycle(
cycles: &CyclesInFace,
) -> impl Iterator<Item = Cycle<2>> + '_ {
) -> impl Iterator<Item = Cycle> + '_ {
let cycles = cycles.as_local().map(|cycle| {
let edges = cycle
.edges
.iter()
.map(|edge| {
let curve = {
let local = match *edge.local().curve.local() {
let local = match *edge.curve.local() {
Curve::Circle(Circle { center, a, b }) => {
let center = Point::from([center.u, -center.v]);

@@ -49,12 +49,12 @@ fn reverse_local_coordinates_in_cycle(
}
};

let canonical = *edge.local().curve.canonical();
let canonical = *edge.curve.canonical();
LocalForm::new(local, canonical)
};
let vertices = edge.local().vertices.clone();
let local = Edge { curve, vertices };
LocalForm::new(local, edge.canonical().clone())
let vertices = edge.vertices.clone();

Edge { curve, vertices }
})
.collect();

20 changes: 5 additions & 15 deletions crates/fj-kernel/src/algorithms/sweep.rs
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ pub fn sweep(

for cycle in face.all_cycles() {
for edge in cycle.edges {
if let Some(vertices) = edge.canonical().vertices() {
if let Some(vertices) = edge.vertices() {
create_non_continuous_side_face(
path,
is_sweep_along_negative_direction,
@@ -51,7 +51,7 @@ pub fn sweep(
}

create_continuous_side_face(
edge.local().clone(),
edge.clone(),
path,
tolerance,
color,
@@ -152,18 +152,9 @@ fn create_non_continuous_side_face(
Vertex::new(Point::from([1.]), b.1),
]);

let edge = {
let local = Edge {
curve: curve.clone(),
vertices: vertices.clone(),
};

let global = Edge {
curve: LocalForm::canonical_only(*curve.canonical()),
vertices,
};

LocalForm::new(local, global)
let edge = Edge {
curve: curve.clone(),
vertices: vertices.clone(),
};

edges.push(edge);
@@ -185,7 +176,6 @@ fn create_continuous_side_face(
) {
let translation = Transform::translation(path);

let edge = LocalForm::new(edge.clone(), edge.to_canonical());
let cycle = Cycle { edges: vec![edge] };
let approx = CycleApprox::new(&cycle, tolerance);

16 changes: 4 additions & 12 deletions crates/fj-kernel/src/algorithms/transform.rs
Original file line number Diff line number Diff line change
@@ -53,26 +53,18 @@ pub fn transform_cycles(
.edges
.iter()
.map(|edge| {
let curve_local = *edge.local().curve.local();
let curve_canonical =
edge.canonical().curve().transform(transform);
let curve_local = *edge.curve.local();
let curve_canonical = edge.curve().transform(transform);

let vertices = edge
.canonical()
.clone()
.vertices
.map(|vertex| transform_vertex(&vertex, transform));

let edge_local = Edge {
Edge {
curve: LocalForm::new(curve_local, curve_canonical),
vertices: vertices.clone(),
};
let edge_canonical = Edge {
curve: LocalForm::canonical_only(curve_canonical),
vertices,
};

LocalForm::new(edge_local, edge_canonical)
}
})
.collect();

47 changes: 23 additions & 24 deletions crates/fj-kernel/src/iter.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ pub trait ObjectIters {
fn curve_iter(&self) -> Iter<Curve<3>>;

/// Iterate over all cycles
fn cycle_iter(&self) -> Iter<Cycle<3>>;
fn cycle_iter(&self) -> Iter<Cycle>;

/// Iterate over all edges
fn edge_iter(&self) -> Iter<Edge<3>>;
@@ -36,7 +36,7 @@ impl ObjectIters for Curve<3> {
Iter::from_object(*self)
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
Iter::empty()
}

@@ -61,26 +61,26 @@ impl ObjectIters for Curve<3> {
}
}

impl ObjectIters for Cycle<3> {
impl ObjectIters for Cycle {
fn curve_iter(&self) -> Iter<Curve<3>> {
let mut iter = Iter::empty();

for edge in self.edges() {
iter = iter.with(edge.curve_iter());
iter = iter.with(edge.to_canonical().curve_iter());
}

iter
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
Iter::from_object(self.clone())
}

fn edge_iter(&self) -> Iter<Edge<3>> {
let mut iter = Iter::empty();

for edge in self.edges() {
iter = iter.with(edge.edge_iter());
iter = iter.with(edge.to_canonical().edge_iter());
}

iter
@@ -90,7 +90,7 @@ impl ObjectIters for Cycle<3> {
let mut iter = Iter::empty();

for edge in self.edges() {
iter = iter.with(edge.face_iter());
iter = iter.with(edge.to_canonical().face_iter());
}

iter
@@ -100,7 +100,7 @@ impl ObjectIters for Cycle<3> {
let mut iter = Iter::empty();

for edge in self.edges() {
iter = iter.with(edge.global_vertex_iter());
iter = iter.with(edge.to_canonical().global_vertex_iter());
}

iter
@@ -110,7 +110,7 @@ impl ObjectIters for Cycle<3> {
let mut iter = Iter::empty();

for edge in self.edges() {
iter = iter.with(edge.surface_iter());
iter = iter.with(edge.to_canonical().surface_iter());
}

iter
@@ -120,7 +120,7 @@ impl ObjectIters for Cycle<3> {
let mut iter = Iter::empty();

for edge in self.edges() {
iter = iter.with(edge.vertex_iter());
iter = iter.with(edge.to_canonical().vertex_iter());
}

iter
@@ -138,7 +138,7 @@ impl ObjectIters for Edge<3> {
iter
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
let mut iter = Iter::empty().with(self.curve().cycle_iter());

for vertex in self.vertices().into_iter().flatten() {
@@ -199,7 +199,7 @@ impl ObjectIters for Face {
let mut iter = Iter::empty().with(face.surface().curve_iter());

for cycle in face.all_cycles() {
iter = iter.with(cycle.to_canonical().curve_iter());
iter = iter.with(cycle.curve_iter());
}

return iter;
@@ -208,12 +208,12 @@ impl ObjectIters for Face {
Iter::empty()
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
if let Face::Face(face) = self {
let mut iter = Iter::empty().with(face.surface().cycle_iter());

for cycle in face.all_cycles() {
iter = iter.with(cycle.to_canonical().cycle_iter());
iter = iter.with(cycle.cycle_iter());
}

return iter;
@@ -227,7 +227,7 @@ impl ObjectIters for Face {
let mut iter = Iter::empty().with(face.surface().edge_iter());

for cycle in face.all_cycles() {
iter = iter.with(cycle.to_canonical().edge_iter());
iter = iter.with(cycle.edge_iter());
}

return iter;
@@ -246,7 +246,7 @@ impl ObjectIters for Face {
Iter::empty().with(face.surface().global_vertex_iter());

for cycle in face.all_cycles() {
iter = iter.with(cycle.to_canonical().global_vertex_iter());
iter = iter.with(cycle.global_vertex_iter());
}

return iter;
@@ -260,7 +260,7 @@ impl ObjectIters for Face {
let mut iter = Iter::empty().with(face.surface().surface_iter());

for cycle in face.all_cycles() {
iter = iter.with(cycle.to_canonical().surface_iter());
iter = iter.with(cycle.surface_iter());
}

return iter;
@@ -274,7 +274,7 @@ impl ObjectIters for Face {
let mut iter = Iter::empty().with(face.surface().vertex_iter());

for cycle in face.all_cycles() {
iter = iter.with(cycle.to_canonical().vertex_iter());
iter = iter.with(cycle.vertex_iter());
}

return iter;
@@ -289,7 +289,7 @@ impl ObjectIters for GlobalVertex {
Iter::empty()
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
Iter::empty()
}

@@ -319,7 +319,7 @@ impl ObjectIters for Surface {
Iter::empty()
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
Iter::empty()
}

@@ -349,7 +349,7 @@ impl ObjectIters for Vertex {
Iter::empty()
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
Iter::empty()
}

@@ -394,7 +394,7 @@ where
iter
}

fn cycle_iter(&self) -> Iter<Cycle<3>> {
fn cycle_iter(&self) -> Iter<Cycle> {
let mut iter = Iter::empty();

for object in self.into_iter() {
@@ -519,8 +519,7 @@ mod tests {
let cycle = Cycle::polygon_from_points(
&Surface::xy_plane(),
[[0., 0.], [1., 0.], [0., 1.]],
)
.to_canonical();
);

assert_eq!(3, cycle.curve_iter().count());
assert_eq!(1, cycle.cycle_iter().count());
36 changes: 7 additions & 29 deletions crates/fj-kernel/src/objects/cycle.rs
Original file line number Diff line number Diff line change
@@ -10,39 +10,17 @@ use super::{Curve, Edge, Surface};
/// edge. The end of the last edge must connect to the beginning of the first
/// one.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Cycle<const D: usize> {
pub struct Cycle {
/// The edges that make up the cycle
pub edges: Vec<LocalForm<Edge<D>, Edge<3>>>,
pub edges: Vec<Edge<2>>,
}

impl Cycle<2> {
/// Temporary utility method to aid refactoring
pub fn to_canonical(&self) -> Cycle<3> {
let mut edges = Vec::new();

for edge in &self.edges {
let edge = edge.local().to_canonical();
let edge = LocalForm::canonical_only(edge);
edges.push(edge);
}

Cycle { edges }
}
}

impl Cycle<3> {
/// Construct a `Cycle`
pub fn new(edges: impl IntoIterator<Item = Edge<3>>) -> Self {
let edges = edges.into_iter().map(LocalForm::canonical_only).collect();

Self { edges }
}

impl Cycle {
/// Create a polygon from a list of points
pub fn polygon_from_points(
surface: &Surface,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Cycle<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
@@ -71,7 +49,7 @@ impl Cycle<3> {
vertices: edge_canonical.vertices.clone(),
};

edges.push(LocalForm::new(edge_local, edge_canonical));
edges.push(edge_local);
}

Cycle { edges }
@@ -81,7 +59,7 @@ impl Cycle<3> {
///
/// This is a convenience method that saves the caller from dealing with the
/// [`Handle`]s.
pub fn edges(&self) -> impl Iterator<Item = Edge<3>> + '_ {
self.edges.iter().map(|handle| handle.canonical().clone())
pub fn edges(&self) -> impl Iterator<Item = Edge<2>> + '_ {
self.edges.iter().cloned()
}
}
12 changes: 3 additions & 9 deletions crates/fj-kernel/src/objects/edge.rs
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ impl<const D: usize> Edge<D> {

impl Edge<2> {
/// Create a circle from the given radius
pub fn circle_from_radius(radius: Scalar) -> LocalForm<Edge<2>, Edge<3>> {
pub fn circle_from_radius(radius: Scalar) -> Edge<2> {
let curve_local = Curve::Circle(Circle {
center: Point::origin(),
a: Vector::from([radius, Scalar::ZERO]),
@@ -55,16 +55,10 @@ impl Edge<2> {
b: Vector::from([Scalar::ZERO, radius, Scalar::ZERO]),
});

let edge_local = Edge {
Edge {
curve: LocalForm::new(curve_local, curve_canonical),
vertices: VerticesOfEdge::none(),
};
let edge_canonical = Edge {
curve: LocalForm::canonical_only(curve_canonical),
vertices: VerticesOfEdge::none(),
};

LocalForm::new(edge_local, edge_canonical)
}
}

/// Temporary utility method to aid refactoring
22 changes: 11 additions & 11 deletions crates/fj-kernel/src/objects/face.rs
Original file line number Diff line number Diff line change
@@ -27,8 +27,8 @@ impl Face {
/// Construct a new instance of `Face`
pub fn new(
surface: Surface,
exteriors: impl IntoIterator<Item = Cycle<2>>,
interiors: impl IntoIterator<Item = Cycle<2>>,
exteriors: impl IntoIterator<Item = Cycle>,
interiors: impl IntoIterator<Item = Cycle>,
color: [u8; 4],
) -> Self {
let exteriors = CyclesInFace::new(exteriors);
@@ -70,23 +70,23 @@ impl Face {
///
/// This is a convenience method that saves the caller from dealing with the
/// [`Handle`]s.
pub fn exteriors(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn exteriors(&self) -> impl Iterator<Item = Cycle> + '_ {
self.brep().exteriors()
}

/// Access the interior cycles that the face refers to
///
/// This is a convenience method that saves the caller from dealing with the
/// [`Handle`]s.
pub fn interiors(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn interiors(&self) -> impl Iterator<Item = Cycle> + '_ {
self.brep().interiors()
}

/// Access all cycles that the face refers to
///
/// This is equivalent to chaining the iterators returned by
/// [`Face::exteriors`] and [`Face::interiors`].
pub fn all_cycles(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn all_cycles(&self) -> impl Iterator<Item = Cycle> + '_ {
self.exteriors().chain(self.interiors())
}

@@ -144,39 +144,39 @@ impl FaceBRep {
///
/// This is a convenience method that saves the caller from dealing with the
/// [`Handle`]s.
pub fn exteriors(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn exteriors(&self) -> impl Iterator<Item = Cycle> + '_ {
self.exteriors.as_local()
}

/// Access the interior cycles that the face refers to
///
/// This is a convenience method that saves the caller from dealing with the
/// [`Handle`]s.
pub fn interiors(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn interiors(&self) -> impl Iterator<Item = Cycle> + '_ {
self.interiors.as_local()
}

/// Access all cycles that the face refers to
///
/// This is equivalent to chaining the iterators returned by
/// [`Face::exteriors`] and [`Face::interiors`].
pub fn all_cycles(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn all_cycles(&self) -> impl Iterator<Item = Cycle> + '_ {
self.exteriors().chain(self.interiors())
}
}

/// A list of cycles, as they are stored in `Face`
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct CyclesInFace(Vec<Cycle<2>>);
pub struct CyclesInFace(Vec<Cycle>);

impl CyclesInFace {
/// Create a new instance of `CyclesInFace`
pub fn new(cycles: impl IntoIterator<Item = Cycle<2>>) -> Self {
pub fn new(cycles: impl IntoIterator<Item = Cycle>) -> Self {
Self(cycles.into_iter().collect())
}

/// Access an iterator over the canonical forms of the cycles
pub fn as_local(&self) -> impl Iterator<Item = Cycle<2>> + '_ {
pub fn as_local(&self) -> impl Iterator<Item = Cycle> + '_ {
self.0.iter().cloned()
}
}
22 changes: 8 additions & 14 deletions crates/fj-operations/src/difference_2d.rs
Original file line number Diff line number Diff line change
@@ -91,46 +91,40 @@ impl ToShape for fj::Difference2d {
}
}

fn add_cycle(cycle: Cycle<2>, reverse: bool) -> Cycle<2> {
fn add_cycle(cycle: Cycle, reverse: bool) -> Cycle {
let mut edges = Vec::new();
for edge in cycle.edges {
let curve_local = *edge.local().curve.local();
let curve_local = *edge.curve.local();
let curve_local = if reverse {
curve_local.reverse()
} else {
curve_local
};

let curve_canonical = edge.canonical().curve();
let curve_canonical = edge.curve();
let curve_canonical = if reverse {
curve_canonical.reverse()
} else {
curve_canonical
};

let vertices = if reverse {
edge.local().vertices.clone().reverse()
edge.vertices.clone().reverse()
} else {
edge.local().vertices.clone()
edge.vertices.clone()
};

let edge_local = Edge {
let edge = Edge {
curve: LocalForm::new(curve_local, curve_canonical),
vertices: vertices.clone(),
};
let edge_canonical = Edge {
curve: LocalForm::canonical_only(curve_canonical),
vertices,
};

edges.push(LocalForm::new(edge_local, edge_canonical));
edges.push(edge);
}

if reverse {
edges.reverse();
}

Cycle {
edges: edges.clone(),
}
Cycle { edges }
}