Skip to content

Commit

Permalink
Add ReplaceCurve
Browse files Browse the repository at this point in the history
Provide an initial implementation for `HalfEdge`. Other implementations
will be provided, once the building blocks for them are in place.
  • Loading branch information
hannobraun committed Nov 10, 2023
1 parent 3bf190a commit 7ac67a8
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 1 deletion.
215 changes: 215 additions & 0 deletions crates/fj-core/src/operations/replace/curve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
use crate::{
objects::{Curve, Cycle, Face, HalfEdge, Region, Shell, Sketch, Solid},
operations::{insert::Insert, update::UpdateHalfEdge},
services::Services,
storage::Handle,
};

use super::ReplaceOutput;

/// Replace a [`Curve`] in the referenced object graph
///
/// See [module documentation] for more information.
///
/// [module documentation]: super
pub trait ReplaceCurve: Sized {
/// Replace the curve
#[must_use]
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
services: &mut Services,
) -> ReplaceOutput<Self>;
}

impl ReplaceCurve for Handle<HalfEdge> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
services: &mut Services,
) -> ReplaceOutput<Self> {
if original.id() == self.curve().id() {
ReplaceOutput::Updated(
self.update_curve(|_| replacement).insert(services),
)
} else {
ReplaceOutput::Original(self)
}
}
}

impl ReplaceCurve for Handle<Cycle> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
services: &mut Services,
) -> ReplaceOutput<Self> {
let mut replacement_happened = false;

let mut half_edges = Vec::new();
for half_edge in self.half_edges() {
let half_edge = half_edge.clone().replace_curve(
original,
replacement.clone(),
services,
);
replacement_happened |= half_edge.was_updated();
half_edges.push(half_edge.into_inner());
}

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

impl ReplaceCurve for Handle<Region> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
services: &mut Services,
) -> ReplaceOutput<Self> {
let mut replacement_happened = false;

let exterior = self.exterior().clone().replace_curve(
original,
replacement.clone(),
services,
);
replacement_happened |= exterior.was_updated();

let mut interiors = Vec::new();
for cycle in self.interiors() {
let cycle = cycle.clone().replace_curve(
original,
replacement.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 ReplaceCurve for Handle<Sketch> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
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_curve(
original,
replacement.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 ReplaceCurve for Handle<Face> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
services: &mut Services,
) -> ReplaceOutput<Self> {
let region = self.region().clone().replace_curve(
original,
replacement,
services,
);

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

impl ReplaceCurve for Handle<Shell> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
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_curve(
original,
replacement.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 ReplaceCurve for Handle<Solid> {
fn replace_curve(
self,
original: &Handle<Curve>,
replacement: Handle<Curve>,
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_curve(
original,
replacement.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)
}
}
}
3 changes: 2 additions & 1 deletion crates/fj-core/src/operations/replace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@
//! [`Handle`]: crate::storage::Handle
//! [update operations]: crate::operations::update
mod curve;
mod vertex;

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

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

0 comments on commit 7ac67a8

Please sign in to comment.