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

Standardize all update methods #2031

Merged
merged 29 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
03e4353
Add missing assertion
hannobraun Sep 26, 2023
88a63f3
Update doc comment
hannobraun Sep 26, 2023
c3e5199
Update trait method name
hannobraun Sep 26, 2023
e3c4792
Switch `UpdateEdge::update_path` to new style
hannobraun Sep 26, 2023
7db42f7
Refactor
hannobraun Sep 26, 2023
9a0f303
Update trait method name
hannobraun Sep 26, 2023
ac52473
Switch `UpdateEdge::update_boundary` to new style
hannobraun Sep 26, 2023
a6b0baf
Refactor
hannobraun Sep 26, 2023
e19a45a
Update trait method name
hannobraun Sep 26, 2023
a7fe1bf
Switch `UpdateEdge::update_curve` to new style
hannobraun Sep 26, 2023
dd16cad
Inline redundant variable
hannobraun Sep 26, 2023
a393bf4
Update trait method name
hannobraun Sep 26, 2023
c30421c
Switch `update_start_vertex` to new style
hannobraun Sep 26, 2023
ee0f5cc
Update documentation of `UpdateEdge`
hannobraun Sep 26, 2023
dbb4812
Update doc comment
hannobraun Sep 26, 2023
9f3d97f
Rename argument to increase consistency
hannobraun Sep 26, 2023
d023113
Fix typo in doc comment
hannobraun Sep 26, 2023
eb746ed
Rename argument to increase consistency
hannobraun Sep 26, 2023
c28f768
Update trait method name
hannobraun Sep 26, 2023
18c57ad
Implement `IntoIterator` for `Handles`
hannobraun Sep 26, 2023
80fc3b2
Add `Handles::update`
hannobraun Sep 26, 2023
4811a0d
Update doc comment
hannobraun Sep 26, 2023
b0a1489
Rename argument to prepare for follow-on change
hannobraun Sep 26, 2023
eecabd4
Rename argument to increase consistency
hannobraun Sep 26, 2023
78d4173
Switch `UpdateShell::update_face` to new style
hannobraun Sep 26, 2023
d48cf69
Refactor
hannobraun Sep 26, 2023
979c1b4
Refactor
hannobraun Sep 26, 2023
119bf9d
Refactor
hannobraun Sep 26, 2023
d38a235
Update doc comment
hannobraun Sep 26, 2023
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
4 changes: 2 additions & 2 deletions crates/fj-core/src/algorithms/sweep/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ impl Sweep for (&Edge, &Handle<Vertex>, &Surface, Option<Color>) {
Some(boundary),
services,
)
.replace_start_vertex(start_vertex);
.update_start_vertex(|_| start_vertex);

let edge = if let Some(curve) = curve {
edge.replace_curve(curve)
edge.update_curve(|_| curve)
} else {
edge
};
Expand Down
45 changes: 44 additions & 1 deletion crates/fj-core/src/objects/handles.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::BTreeSet, fmt::Debug, slice};
use std::{collections::BTreeSet, fmt::Debug, slice, vec};

use itertools::Itertools;

Expand Down Expand Up @@ -98,6 +98,40 @@ impl<T> Handles<T> {
pub fn pairs(&self) -> impl Iterator<Item = (&Handle<T>, &Handle<T>)> {
self.iter().circular_tuple_windows()
}

/// Create a new instance in which the provided item is updated
///
/// # Panics
///
/// Panics, if the provided item is not present.
/// Panics, if the update results in a duplicate item.
#[must_use]
pub fn update(
&self,
handle: &Handle<T>,
update: impl FnOnce(&Handle<T>) -> Handle<T>,
) -> Self
where
T: Debug + Ord,
{
let mut updated = Some(update(handle));

let items = self.iter().map(|h| {
if h.id() == handle.id() {
updated
.take()
.expect("`Handles` should not contain same item twice")
} else {
h.clone()
}
});

let handles = items.collect();

assert!(updated.is_none(), "Edge not found in cycle");

handles
}
}

impl<O> FromIterator<Handle<O>> for Handles<O>
Expand All @@ -109,6 +143,15 @@ where
}
}

impl<T> IntoIterator for Handles<T> {
type Item = Handle<T>;
type IntoIter = vec::IntoIter<Handle<T>>;

fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}

impl<'r, T> IntoIterator for &'r Handles<T> {
// You might wonder why we're returning references to handles here, when
// `Handle` already is kind of reference, and easily cloned.
Expand Down
18 changes: 9 additions & 9 deletions crates/fj-core/src/operations/join/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ impl JoinCycle for Cycle {
self.add_edges(edges.into_iter().circular_tuple_windows().map(
|((prev, _, _), (edge, curve, boundary))| {
Edge::unjoined(curve, boundary, services)
.replace_curve(edge.curve().clone())
.replace_start_vertex(prev.start_vertex().clone())
.update_curve(|_| edge.curve().clone())
.update_start_vertex(|_| prev.start_vertex().clone())
.insert(services)
},
))
Expand All @@ -111,20 +111,20 @@ impl JoinCycle for Cycle {

cycle
.update_edge(self.edges().nth_circular(index), |edge| {
edge.replace_curve(edge_other.curve().clone())
.replace_start_vertex(
edge.update_curve(|_| edge_other.curve().clone())
.update_start_vertex(|_| {
other
.edges()
.nth_circular(index_other + 1)
.start_vertex()
.clone(),
)
.clone()
})
.insert(services)
})
.update_edge(self.edges().nth_circular(index + 1), |edge| {
edge.replace_start_vertex(
edge_other.start_vertex().clone(),
)
edge.update_start_vertex(|_| {
edge_other.start_vertex().clone()
})
.insert(services)
})
},
Expand Down
19 changes: 7 additions & 12 deletions crates/fj-core/src/operations/update/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ pub trait UpdateCycle {
fn add_edges(&self, edges: impl IntoIterator<Item = Handle<Edge>>) -> Self;

/// Update the provided edge
///
/// # Panics
///
/// Uses [`Handles::update`] internally, and panics for the same reasons.
///
/// [`Handles::update`]: crate::objects::Handles::update
#[must_use]
fn update_edge(
&self,
Expand All @@ -29,18 +35,7 @@ impl UpdateCycle for Cycle {
edge: &Handle<Edge>,
update: impl FnOnce(&Handle<Edge>) -> Handle<Edge>,
) -> Self {
let mut updated = Some(update(edge));

let edges = self.edges().iter().map(|e| {
if e.id() == edge.id() {
updated
.take()
.expect("Cycle should not contain same edge twice")
} else {
e.clone()
}
});

let edges = self.edges().update(edge, update);
Cycle::new(edges)
}
}
56 changes: 40 additions & 16 deletions crates/fj-core/src/operations/update/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,81 @@ use crate::{

/// Update a [`Edge`]
pub trait UpdateEdge {
/// Replace the path of the edge
/// Update the path of the edge
#[must_use]
fn replace_path(&self, path: SurfacePath) -> Self;
fn update_path(
&self,
update: impl FnOnce(SurfacePath) -> SurfacePath,
) -> Self;

/// Replace the boundary of the edge
/// Update the boundary of the edge
#[must_use]
fn replace_boundary(&self, boundary: CurveBoundary<Point<1>>) -> Self;
fn update_boundary(
&self,
update: impl FnOnce(CurveBoundary<Point<1>>) -> CurveBoundary<Point<1>>,
) -> Self;

/// Replace the curve of the edge
/// Update the curve of the edge
#[must_use]
fn replace_curve(&self, curve: Handle<Curve>) -> Self;
fn update_curve(
&self,
update: impl FnOnce(&Handle<Curve>) -> Handle<Curve>,
) -> Self;

/// Replace the start vertex of the edge
/// Update the start vertex of the edge
#[must_use]
fn replace_start_vertex(&self, start_vertex: Handle<Vertex>) -> Self;
fn update_start_vertex(
&self,
update: impl FnOnce(&Handle<Vertex>) -> Handle<Vertex>,
) -> Self;
}

impl UpdateEdge for Edge {
fn replace_path(&self, path: SurfacePath) -> Self {
fn update_path(
&self,
update: impl FnOnce(SurfacePath) -> SurfacePath,
) -> Self {
Edge::new(
path,
update(self.path()),
self.boundary(),
self.curve().clone(),
self.start_vertex().clone(),
)
}

fn replace_boundary(&self, boundary: CurveBoundary<Point<1>>) -> Self {
fn update_boundary(
&self,
update: impl FnOnce(CurveBoundary<Point<1>>) -> CurveBoundary<Point<1>>,
) -> Self {
Edge::new(
self.path(),
boundary,
update(self.boundary()),
self.curve().clone(),
self.start_vertex().clone(),
)
}

fn replace_curve(&self, curve: Handle<Curve>) -> Self {
fn update_curve(
&self,
update: impl FnOnce(&Handle<Curve>) -> Handle<Curve>,
) -> Self {
Edge::new(
self.path(),
self.boundary(),
curve,
update(self.curve()),
self.start_vertex().clone(),
)
}

fn replace_start_vertex(&self, start_vertex: Handle<Vertex>) -> Self {
fn update_start_vertex(
&self,
update: impl FnOnce(&Handle<Vertex>) -> Handle<Vertex>,
) -> Self {
Edge::new(
self.path(),
self.boundary(),
self.curve().clone(),
start_vertex,
update(self.start_vertex()),
)
}
}
12 changes: 6 additions & 6 deletions crates/fj-core/src/operations/update/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ use crate::{

/// Update a [`Face`]
pub trait UpdateFace {
/// Replace the region of the face
/// Update the region of the face
#[must_use]
fn update_region(
&self,
f: impl FnOnce(&Handle<Region>) -> Handle<Region>,
update: impl FnOnce(&Handle<Region>) -> Handle<Region>,
) -> Self;
}

impl UpdateFace for Face {
fn update_region(
&self,
f: impl FnOnce(&Handle<Region>) -> Handle<Region>,
update: impl FnOnce(&Handle<Region>) -> Handle<Region>,
) -> Self {
let region = f(self.region());
let region = update(self.region());
Face::new(self.surface().clone(), region)
}
}

impl<const D: usize> UpdateFace for Polygon<D> {
fn update_region(
&self,
f: impl FnOnce(&Handle<Region>) -> Handle<Region>,
update: impl FnOnce(&Handle<Region>) -> Handle<Region>,
) -> Self {
self.replace_face(self.face.update_region(f))
self.replace_face(self.face.update_region(update))
}
}
8 changes: 4 additions & 4 deletions crates/fj-core/src/operations/update/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ pub trait UpdateRegion {
#[must_use]
fn update_exterior(
&self,
f: impl FnOnce(&Handle<Cycle>) -> Handle<Cycle>,
update: impl FnOnce(&Handle<Cycle>) -> Handle<Cycle>,
) -> Self;

/// Add the provides interiors to the region
/// Add the provided interiors to the region
#[must_use]
fn add_interiors(
&self,
Expand All @@ -23,9 +23,9 @@ pub trait UpdateRegion {
impl UpdateRegion for Region {
fn update_exterior(
&self,
f: impl FnOnce(&Handle<Cycle>) -> Handle<Cycle>,
update: impl FnOnce(&Handle<Cycle>) -> Handle<Cycle>,
) -> Self {
let exterior = f(self.exterior());
let exterior = update(self.exterior());
Region::new(exterior, self.interiors().iter().cloned(), self.color())
}

Expand Down
29 changes: 14 additions & 15 deletions crates/fj-core/src/operations/update/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ pub trait UpdateShell {
#[must_use]
fn add_faces(&self, faces: impl IntoIterator<Item = Handle<Face>>) -> Self;

/// Replace a face of the shell
/// Update a face of the shell
///
/// # Panics
///
/// Uses [`Handles::update`] internally, and panics for the same reasons.
///
/// [`Handles::update`]: crate::objects::Handles::update
#[must_use]
fn replace_face(
fn update_face(
&self,
original: &Handle<Face>,
replacement: Handle<Face>,
face: &Handle<Face>,
update: impl FnOnce(&Handle<Face>) -> Handle<Face>,
) -> Self;

/// Remove a face from the shell
Expand All @@ -28,19 +34,12 @@ impl UpdateShell for Shell {
Shell::new(faces)
}

fn replace_face(
fn update_face(
&self,
original: &Handle<Face>,
replacement: Handle<Face>,
face: &Handle<Face>,
update: impl FnOnce(&Handle<Face>) -> Handle<Face>,
) -> Self {
let faces = self.faces().iter().map(|face| {
if face.id() == original.id() {
replacement.clone()
} else {
face.clone()
}
});

let faces = self.faces().update(face, update);
Shell::new(faces)
}

Expand Down
Loading