diff --git a/crates/fj-core/src/operations/holes.rs b/crates/fj-core/src/operations/holes.rs index 519305263..f46980348 100644 --- a/crates/fj-core/src/operations/holes.rs +++ b/crates/fj-core/src/operations/holes.rs @@ -75,6 +75,7 @@ impl AddHole for Shell { entry.clone(), *core.layers.geometry.of_half_edge(&entry), )], + location.face.surface().clone(), core, )], core, @@ -150,6 +151,7 @@ impl AddHole for Shell { entry.clone(), *core.layers.geometry.of_half_edge(&entry), )], + entry_location.face.surface().clone(), core, )], core, @@ -171,6 +173,7 @@ impl AddHole for Shell { exit.clone(), *core.layers.geometry.of_half_edge(exit), )], + exit_location.face.surface().clone(), core, )], core, diff --git a/crates/fj-core/src/operations/join/cycle.rs b/crates/fj-core/src/operations/join/cycle.rs index 037b823c2..45122513b 100644 --- a/crates/fj-core/src/operations/join/cycle.rs +++ b/crates/fj-core/src/operations/join/cycle.rs @@ -3,7 +3,7 @@ use std::ops::RangeInclusive; use itertools::Itertools; use crate::{ - geometry::HalfEdgeGeom, + geometry::{HalfEdgeGeom, LocalCurveGeom}, operations::{ build::BuildHalfEdge, geometry::UpdateHalfEdgeGeometry, @@ -11,15 +11,28 @@ use crate::{ update::{UpdateCycle, UpdateHalfEdge}, }, storage::Handle, - topology::{Cycle, HalfEdge}, + topology::{Cycle, HalfEdge, Surface}, Core, }; /// Join a [`Cycle`] to another pub trait JoinCycle { - /// Add half-edges to the cycle that are joined to the provided ones + /// Add new half-edges to the cycle that are joined to the provided ones + /// + /// This method creates a new half-edge for each half-edge that is provided, + /// joins the new half-edge to the provided one, and adds the new half-edge + /// to the cycle. + /// + /// The geometry for each new half-edge needs to be provided as well. + /// + /// Also requires the surface that the cycle is defined in. #[must_use] - fn add_joined_edges(&self, edges: Es, core: &mut Core) -> Self + fn add_joined_edges( + &self, + edges: Es, + surface: Handle, + core: &mut Core, + ) -> Self where Es: IntoIterator, HalfEdgeGeom)>, Es::IntoIter: Clone + ExactSizeIterator; @@ -76,7 +89,12 @@ pub trait JoinCycle { } impl JoinCycle for Cycle { - fn add_joined_edges(&self, edges: Es, core: &mut Core) -> Self + fn add_joined_edges( + &self, + edges: Es, + surface: Handle, + core: &mut Core, + ) -> Self where Es: IntoIterator, HalfEdgeGeom)>, Es::IntoIter: Clone + ExactSizeIterator, @@ -85,14 +103,24 @@ impl JoinCycle for Cycle { .into_iter() .circular_tuple_windows() .map(|((prev_half_edge, _), (half_edge, geometry))| { - HalfEdge::unjoined(core) + let half_edge = HalfEdge::unjoined(core) .update_curve(|_, _| half_edge.curve().clone(), core) .update_start_vertex( |_, _| prev_half_edge.start_vertex().clone(), core, ) .insert(core) - .set_geometry(geometry, &mut core.layers.geometry) + .set_geometry(geometry, &mut core.layers.geometry); + + core.layers.geometry.define_curve( + half_edge.curve().clone(), + surface.clone(), + LocalCurveGeom { + path: geometry.path, + }, + ); + + half_edge }) .collect::>(); self.add_half_edges(half_edges, core) diff --git a/crates/fj-core/src/operations/sweep/cycle.rs b/crates/fj-core/src/operations/sweep/cycle.rs index 0b7b1ffef..4d00d294a 100644 --- a/crates/fj-core/src/operations/sweep/cycle.rs +++ b/crates/fj-core/src/operations/sweep/cycle.rs @@ -39,6 +39,7 @@ pub trait SweepCycle { fn sweep_cycle( &self, surface: Handle, + top_surface: Handle, color: Option, path: impl Into>, cache: &mut SweepCache, @@ -50,6 +51,7 @@ impl SweepCycle for Cycle { fn sweep_cycle( &self, surface: Handle, + top_surface: Handle, color: Option, path: impl Into>, cache: &mut SweepCache, @@ -64,7 +66,7 @@ impl SweepCycle for Cycle { let (bottom_half_edge, bottom_half_edge_next) = bottom_half_edge_pair; - let (side_face, top_edge) = bottom_half_edge.sweep_half_edge( + let (side_face, top_half_edge) = bottom_half_edge.sweep_half_edge( bottom_half_edge_next.start_vertex().clone(), surface.clone(), color, @@ -76,12 +78,13 @@ impl SweepCycle for Cycle { faces.push(side_face); top_edges.push(( - top_edge, + top_half_edge, *core.layers.geometry.of_half_edge(bottom_half_edge), )); } - let top_cycle = Cycle::empty().add_joined_edges(top_edges, core); + let top_cycle = + Cycle::empty().add_joined_edges(top_edges, top_surface, core); SweptCycle { faces, top_cycle } } diff --git a/crates/fj-core/src/operations/sweep/region.rs b/crates/fj-core/src/operations/sweep/region.rs index 05af614b7..b3be68d8b 100644 --- a/crates/fj-core/src/operations/sweep/region.rs +++ b/crates/fj-core/src/operations/sweep/region.rs @@ -52,9 +52,12 @@ impl SweepRegion for Region { let mut faces = Vec::new(); + let top_surface = surface.translate(path, core).insert(core); + let top_exterior = sweep_cycle( self.exterior(), surface.clone(), + top_surface.clone(), color, &mut faces, path, @@ -69,6 +72,7 @@ impl SweepRegion for Region { sweep_cycle( bottom_cycle, surface.clone(), + top_surface.clone(), color, &mut faces, path, @@ -79,7 +83,6 @@ impl SweepRegion for Region { .collect::>(); let top_face = { - let top_surface = surface.translate(path, core).insert(core); let top_region = Region::new(top_exterior, top_interiors).insert(core); @@ -93,9 +96,11 @@ impl SweepRegion for Region { } } +#[allow(clippy::too_many_arguments)] fn sweep_cycle( bottom_cycle: &Cycle, bottom_surface: Handle, + top_surface: Handle, color: Option, faces: &mut Vec, path: Vector<3>, @@ -104,6 +109,7 @@ fn sweep_cycle( ) -> Handle { let swept_cycle = bottom_cycle.reverse(core).sweep_cycle( bottom_surface, + top_surface, color, path, cache,