Skip to content

Commit

Permalink
Add ReplaceHalfEdge
Browse files Browse the repository at this point in the history
  • Loading branch information
hannobraun committed Nov 10, 2023
1 parent 7ac67a8 commit 758fd72
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 1 deletion.
187 changes: 187 additions & 0 deletions crates/fj-core/src/operations/replace/half_edge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
use crate::{
objects::{Cycle, Face, HalfEdge, Region, Shell, Sketch, Solid},
operations::insert::Insert,
services::Services,
storage::Handle,
};

use super::ReplaceOutput;

/// Replace a [`HalfEdge`] in the referenced object graph
///
/// See [module documentation] for more information.
///
/// [module documentation]: super
pub trait ReplaceHalfEdge: Sized {
/// Replace the half-edge
#[must_use]
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self>;
}

impl ReplaceHalfEdge for Handle<Cycle> {
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self> {
if let Some(half_edges) =
self.half_edges().replace(original, replacements)
{
ReplaceOutput::Updated(Cycle::new(half_edges).insert(services))
} else {
ReplaceOutput::Original(self)
}
}
}

impl ReplaceHalfEdge for Handle<Region> {
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self> {
let mut replacement_happened = false;

let exterior = self.exterior().clone().replace_half_edge(
original,
replacements.clone(),
services,
);
replacement_happened |= exterior.was_updated();

let mut interiors = Vec::new();
for cycle in self.interiors() {
let cycle = cycle.clone().replace_half_edge(
original,
replacements.clone(),
services,
);
replacement_happened |= cycle.was_updated();
interiors.push(cycle.into_inner());
}

if replacement_happened {
ReplaceOutput::Updated(
Region::new(exterior.into_inner(), interiors, self.color())
.insert(services),
)
} else {
ReplaceOutput::Original(self)
}
}
}

impl ReplaceHalfEdge for Handle<Sketch> {
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self> {
let mut replacement_happened = false;

let mut regions = Vec::new();
for region in self.regions() {
let region = region.clone().replace_half_edge(
original,
replacements.clone(),
services,
);
replacement_happened |= region.was_updated();
regions.push(region.into_inner());
}

if replacement_happened {
ReplaceOutput::Updated(Sketch::new(regions).insert(services))
} else {
ReplaceOutput::Original(self)
}
}
}

impl ReplaceHalfEdge for Handle<Face> {
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self> {
let region = self.region().clone().replace_half_edge(
original,
replacements,
services,
);

if region.was_updated() {
ReplaceOutput::Updated(
Face::new(self.surface().clone(), region.into_inner())
.insert(services),
)
} else {
ReplaceOutput::Original(self)
}
}
}

impl ReplaceHalfEdge for Handle<Shell> {
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self> {
let mut replacement_happened = false;

let mut faces = Vec::new();
for face in self.faces() {
let face = face.clone().replace_half_edge(
original,
replacements.clone(),
services,
);
replacement_happened |= face.was_updated();
faces.push(face.into_inner());
}

if replacement_happened {
ReplaceOutput::Updated(Shell::new(faces).insert(services))
} else {
ReplaceOutput::Original(self)
}
}
}

impl ReplaceHalfEdge for Handle<Solid> {
fn replace_half_edge<const N: usize>(
self,
original: &Handle<HalfEdge>,
replacements: [Handle<HalfEdge>; N],
services: &mut Services,
) -> ReplaceOutput<Self> {
let mut replacement_happened = false;

let mut shells = Vec::new();
for shell in self.shells() {
let shell = shell.clone().replace_half_edge(
original,
replacements.clone(),
services,
);
replacement_happened |= shell.was_updated();
shells.push(shell.into_inner());
}

if replacement_happened {
ReplaceOutput::Updated(Solid::new(shells).insert(services))
} else {
ReplaceOutput::Original(self)
}
}
}
5 changes: 4 additions & 1 deletion crates/fj-core/src/operations/replace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,12 @@
//! [update operations]: crate::operations::update
mod curve;
mod half_edge;
mod vertex;

pub use self::{curve::ReplaceCurve, vertex::ReplaceVertex};
pub use self::{
curve::ReplaceCurve, half_edge::ReplaceHalfEdge, vertex::ReplaceVertex,
};

/// The output of a replace operation
///
Expand Down

0 comments on commit 758fd72

Please sign in to comment.