diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index 78c2dcade..6d858e381 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -138,7 +138,6 @@ mod tests { algorithms::intersect::{face_point::FacePointIntersection, Intersect}, builder::FaceBuilder, insert::Insert, - iter::ObjectIters, partial::{Partial, PartialFace, PartialObject}, services::Services, }; @@ -292,7 +291,8 @@ mod tests { let intersection = (&face, &point).intersect(); let edge = face - .half_edge_iter() + .exterior() + .half_edges() .find(|edge| { let [a, b] = edge.vertices(); a.global_form().position() == Point::from([0., 0., 0.]) @@ -321,7 +321,9 @@ mod tests { let intersection = (&face, &point).intersect(); let vertex = face - .vertex_iter() + .exterior() + .half_edges() + .flat_map(|half_edge| half_edge.vertices()) .find(|vertex| { vertex.global_form().position() == Point::from([1., 0., 0.]) }) diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index f4e1f03e0..e992bea77 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -154,7 +154,6 @@ mod tests { }, builder::FaceBuilder, insert::Insert, - iter::ObjectIters, partial::{Partial, PartialFace, PartialObject}, services::Services, }; @@ -252,7 +251,8 @@ mod tests { .translate([1., 1., 0.], &mut services.objects); let edge = face - .half_edge_iter() + .exterior() + .half_edges() .find(|edge| { let [a, b] = edge.vertices(); a.global_form().position() == Point::from([1., 0., 1.]) @@ -286,7 +286,9 @@ mod tests { .translate([1., 1., 1.], &mut services.objects); let vertex = face - .vertex_iter() + .exterior() + .half_edges() + .flat_map(|half_edge| half_edge.vertices()) .find(|vertex| { vertex.global_form().position() == Point::from([1., 0., 0.]) }) diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs deleted file mode 100644 index 8a7353747..000000000 --- a/crates/fj-kernel/src/iter.rs +++ /dev/null @@ -1,652 +0,0 @@ -//! API for iterating over the objects of a shape, or part of a shape - -use std::collections::VecDeque; - -use crate::{ - objects::{ - Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Shell, Sketch, - Solid, Surface, Vertex, - }, - storage::Handle, -}; - -/// Access iterators over all objects of a shape, or part of it -/// -/// Implemented for all object types. An implementation must return itself, in -/// addition to any other objects it references. -pub trait ObjectIters<'r> { - /// Return all objects that this one references - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters>; - - /// Iterate over all curves - fn curve_iter(&'r self) -> Iter<&'r Curve> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.curve_iter()); - } - - iter - } - - /// Iterate over all cycles - fn cycle_iter(&'r self) -> Iter<&'r Cycle> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.cycle_iter()); - } - - iter - } - - /// Iterate over all faces - fn face_iter(&'r self) -> Iter<&'r Face> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.face_iter()); - } - - iter - } - - /// Iterate over all global curves - fn global_curve_iter(&'r self) -> Iter<&'r Handle> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with_handles(object.global_curve_iter()); - } - - iter - } - - /// Iterate over all global vertices - fn global_vertex_iter(&'r self) -> Iter<&'r GlobalVertex> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.global_vertex_iter()); - } - - iter - } - - /// Iterate over all half-edges - fn half_edge_iter(&'r self) -> Iter<&'r Handle> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.half_edge_iter()); - } - - iter - } - - /// Iterate over all shells - fn shell_iter(&'r self) -> Iter<&'r Shell> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.shell_iter()); - } - - iter - } - - /// Iterate over all sketches - fn sketch_iter(&'r self) -> Iter<&'r Sketch> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.sketch_iter()); - } - - iter - } - - /// Iterate over all solids - fn solid_iter(&'r self) -> Iter<&'r Solid> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.solid_iter()); - } - - iter - } - - /// Iterate over all surfaces - fn surface_iter(&'r self) -> Iter<&'r Surface> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.surface_iter()); - } - - iter - } - - /// Iterator over all vertices - fn vertex_iter(&'r self) -> Iter<&'r Handle> { - let mut iter = Iter::empty(); - - for object in self.referenced_objects() { - iter = iter.with(object.vertex_iter()); - } - - iter - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - vec![self.global_form() as &dyn ObjectIters] - } - - fn curve_iter(&'r self) -> Iter<&'r Curve> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = Vec::new(); - - for half_edge in self.half_edges() { - objects.push(half_edge as &dyn ObjectIters); - } - - objects - } - - fn cycle_iter(&'r self) -> Iter<&'r Cycle> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = vec![self.surface() as &dyn ObjectIters]; - - for cycle in self.all_cycles() { - objects.push(cycle); - } - - objects - } - - fn face_iter(&'r self) -> Iter<&'r Face> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - Vec::new() - } - - fn global_curve_iter(&'r self) -> Iter<&'r Handle> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - Vec::new() - } - - fn global_vertex_iter(&'r self) -> Iter<&'r GlobalVertex> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = vec![self.curve() as &dyn ObjectIters]; - - for vertex in self.vertices().iter() { - objects.push(vertex); - } - - objects - } - - fn half_edge_iter(&'r self) -> Iter<&'r Handle> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = Vec::new(); - - for face in self.faces() { - objects.push(face as &dyn ObjectIters); - } - - objects - } - - fn shell_iter(&'r self) -> Iter<&'r Shell> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Sketch { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = Vec::new(); - - for face in self.faces() { - objects.push(face as &dyn ObjectIters); - } - - objects - } - - fn sketch_iter(&'r self) -> Iter<&'r Sketch> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Solid { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = Vec::new(); - - for shell in self.shells() { - objects.push(shell as &dyn ObjectIters); - } - - objects - } - - fn solid_iter(&'r self) -> Iter<&'r Solid> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - Vec::new() - } - - fn surface_iter(&'r self) -> Iter<&'r Surface> { - Iter::from_object(self) - } -} - -impl<'r> ObjectIters<'r> for Handle { - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - vec![ - self.curve() as &dyn ObjectIters, - self.global_form() as &dyn ObjectIters, - ] - } - - fn vertex_iter(&'r self) -> Iter<&'r Handle> { - Iter::from_object(self) - } -} - -// This implementation is useful for test code. -impl<'r, T, O> ObjectIters<'r> for T -where - T: 'r, - O: ObjectIters<'r> + 'r, - &'r T: IntoIterator, -{ - fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - let mut objects = Vec::new(); - - for object in self { - objects.push(object as &dyn ObjectIters); - } - - objects - } -} - -/// An iterator over objects -/// -/// See [`ObjectIters`]. -pub struct Iter(VecDeque); - -impl Iter { - fn empty() -> Self { - Self(VecDeque::new()) - } - - fn from_object(object: T) -> Self { - let mut objects = VecDeque::new(); - objects.push_back(object); - Self(objects) - } - - fn with(mut self, other: Self) -> Self - where - T: PartialEq, - { - for object in other { - if !self.0.contains(&object) { - self.0.push_back(object); - } - } - - self - } -} - -impl Iter<&'_ Handle> { - fn with_handles(mut self, other: Self) -> Self { - for handle in other { - if !self.0.iter().any(|h| h.id() == handle.id()) { - self.0.push_back(handle); - } - } - - self - } -} - -impl Iterator for Iter { - type Item = T; - - fn next(&mut self) -> Option { - self.0.pop_front() - } -} - -#[cfg(test)] -mod tests { - use crate::{ - builder::{ - CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder, - ShellBuilder, SolidBuilder, - }, - insert::Insert, - objects::{GlobalCurve, GlobalVertex, Objects, SurfaceVertex, Vertex}, - partial::{ - Partial, PartialCurve, PartialCycle, PartialFace, PartialHalfEdge, - PartialObject, PartialShell, PartialSketch, PartialSolid, - }, - services::Services, - }; - - use super::ObjectIters as _; - - #[test] - fn curve() { - let mut services = Services::new(); - - let surface = services.objects.surfaces.xy_plane(); - let mut object = PartialCurve { - surface: Partial::from(surface), - ..Default::default() - }; - object.update_as_u_axis(); - let object = object - .build(&mut services.objects) - .insert(&mut services.objects); - - assert_eq!(1, object.curve_iter().count()); - assert_eq!(0, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(1, object.global_curve_iter().count()); - assert_eq!(0, object.global_vertex_iter().count()); - assert_eq!(0, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(0, object.surface_iter().count()); - assert_eq!(0, object.vertex_iter().count()); - } - - #[test] - fn cycle() { - let mut services = Services::new(); - - let surface = services.objects.surfaces.xy_plane(); - let object = { - let mut cycle = PartialCycle { - surface: surface.into(), - ..Default::default() - }; - cycle.update_as_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]); - cycle - .build(&mut services.objects) - .insert(&mut services.objects) - }; - - assert_eq!(3, object.curve_iter().count()); - assert_eq!(1, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(3, object.global_curve_iter().count()); - assert_eq!(3, object.global_vertex_iter().count()); - assert_eq!(3, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(0, object.surface_iter().count()); - assert_eq!(6, object.vertex_iter().count()); - } - - #[test] - fn face() { - let mut services = Services::new(); - - let mut object = PartialFace::default(); - object.exterior.write().surface = - Partial::from(services.objects.surfaces.xy_plane()); - object.update_exterior_as_polygon([[0., 0.], [1., 0.], [0., 1.]]); - let object = object - .build(&mut services.objects) - .insert(&mut services.objects); - - assert_eq!(3, object.curve_iter().count()); - assert_eq!(1, object.cycle_iter().count()); - assert_eq!(1, object.face_iter().count()); - assert_eq!(3, object.global_curve_iter().count()); - assert_eq!(3, object.global_vertex_iter().count()); - assert_eq!(3, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(1, object.surface_iter().count()); - assert_eq!(6, object.vertex_iter().count()); - } - - #[test] - fn global_curve() { - let mut services = Services::new(); - - let object = GlobalCurve.insert(&mut services.objects); - - assert_eq!(0, object.curve_iter().count()); - assert_eq!(0, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(1, object.global_curve_iter().count()); - assert_eq!(0, object.global_vertex_iter().count()); - assert_eq!(0, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(0, object.surface_iter().count()); - assert_eq!(0, object.vertex_iter().count()); - } - - #[test] - fn global_vertex() { - let mut services = Services::new(); - - let object = - GlobalVertex::new([0., 0., 0.]).insert(&mut services.objects); - - assert_eq!(0, object.curve_iter().count()); - assert_eq!(0, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(0, object.global_curve_iter().count()); - assert_eq!(1, object.global_vertex_iter().count()); - assert_eq!(0, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(0, object.surface_iter().count()); - assert_eq!(0, object.vertex_iter().count()); - } - - #[test] - fn half_edge() { - let mut services = Services::new(); - - let object = { - let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points( - services.objects.surfaces.xy_plane(), - [[0., 0.], [1., 0.]], - ); - - half_edge - .build(&mut services.objects) - .insert(&mut services.objects) - }; - - assert_eq!(1, object.curve_iter().count()); - assert_eq!(0, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(1, object.global_curve_iter().count()); - assert_eq!(2, object.global_vertex_iter().count()); - assert_eq!(1, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(0, object.surface_iter().count()); - assert_eq!(2, object.vertex_iter().count()); - } - - #[test] - fn shell() { - let mut services = Services::new(); - - let object = PartialShell::create_cube_from_edge_length( - 1., - &mut services.objects, - ) - .build(&mut services.objects) - .insert(&mut services.objects); - - assert_eq!(24, object.curve_iter().count()); - assert_eq!(6, object.cycle_iter().count()); - assert_eq!(6, object.face_iter().count()); - assert_eq!(12, object.global_curve_iter().count()); - assert_eq!(8, object.global_vertex_iter().count()); - assert_eq!(24, object.half_edge_iter().count()); - assert_eq!(1, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(6, object.surface_iter().count()); - assert_eq!(48, object.vertex_iter().count()); - } - - #[test] - fn sketch() { - let mut services = Services::new(); - - let mut face = PartialFace::default(); - face.exterior.write().surface = - Partial::from(services.objects.surfaces.xy_plane()); - face.update_exterior_as_polygon([[0., 0.], [1., 0.], [0., 1.]]); - let object = PartialSketch { - faces: vec![Partial::from_partial(face)], - } - .build(&mut services.objects); - - assert_eq!(3, object.curve_iter().count()); - assert_eq!(1, object.cycle_iter().count()); - assert_eq!(1, object.face_iter().count()); - assert_eq!(3, object.global_curve_iter().count()); - assert_eq!(3, object.global_vertex_iter().count()); - assert_eq!(3, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(1, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(1, object.surface_iter().count()); - assert_eq!(6, object.vertex_iter().count()); - } - - #[test] - fn solid() { - let mut services = Services::new(); - - let object = { - let mut solid = PartialSolid::default(); - solid.with_cube_from_edge_length(1., &mut services.objects); - solid.build(&mut services.objects) - }; - - assert_eq!(24, object.curve_iter().count()); - assert_eq!(6, object.cycle_iter().count()); - assert_eq!(6, object.face_iter().count()); - assert_eq!(12, object.global_curve_iter().count()); - assert_eq!(8, object.global_vertex_iter().count()); - assert_eq!(24, object.half_edge_iter().count()); - assert_eq!(1, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(1, object.solid_iter().count()); - assert_eq!(6, object.surface_iter().count()); - assert_eq!(48, object.vertex_iter().count()); - } - - #[test] - fn surface() { - let objects = Objects::new(); - - let object = objects.surfaces.xy_plane(); - - assert_eq!(0, object.curve_iter().count()); - assert_eq!(0, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(0, object.global_curve_iter().count()); - assert_eq!(0, object.global_vertex_iter().count()); - assert_eq!(0, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(1, object.surface_iter().count()); - assert_eq!(0, object.vertex_iter().count()); - } - - #[test] - fn vertex() { - let mut services = Services::new(); - - let surface = services.objects.surfaces.xy_plane(); - let mut curve = PartialCurve { - surface: Partial::from(surface.clone()), - ..Default::default() - }; - curve.update_as_u_axis(); - let curve = curve - .build(&mut services.objects) - .insert(&mut services.objects); - let global_vertex = - GlobalVertex::new([0., 0., 0.]).insert(&mut services.objects); - let surface_vertex = - SurfaceVertex::new([0., 0.], surface, global_vertex) - .insert(&mut services.objects); - let object = Vertex::new([0.], curve, surface_vertex) - .insert(&mut services.objects); - - assert_eq!(1, object.curve_iter().count()); - assert_eq!(0, object.cycle_iter().count()); - assert_eq!(0, object.face_iter().count()); - assert_eq!(1, object.global_curve_iter().count()); - assert_eq!(1, object.global_vertex_iter().count()); - assert_eq!(0, object.half_edge_iter().count()); - assert_eq!(0, object.shell_iter().count()); - assert_eq!(0, object.sketch_iter().count()); - assert_eq!(0, object.solid_iter().count()); - assert_eq!(0, object.surface_iter().count()); - assert_eq!(1, object.vertex_iter().count()); - } -} diff --git a/crates/fj-kernel/src/lib.rs b/crates/fj-kernel/src/lib.rs index 0a1b20ea8..032417f44 100644 --- a/crates/fj-kernel/src/lib.rs +++ b/crates/fj-kernel/src/lib.rs @@ -96,7 +96,6 @@ pub mod algorithms; pub mod builder; pub mod geometry; pub mod insert; -pub mod iter; pub mod objects; pub mod partial; pub mod services; diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index 300cd1c76..898b07e21 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -4,7 +4,6 @@ use fj_interop::{debug::DebugInfo, ext::ArrayExt, mesh::Color}; use fj_kernel::{ algorithms::reverse::Reverse, insert::Insert, - iter::ObjectIters, objects::{Objects, Sketch}, partial::{Partial, PartialFace, PartialObject, PartialSketch}, services::Service, @@ -34,12 +33,12 @@ impl Shape for fj::Difference2d { .each_ref_ext() .map(|shape| shape.compute_brep(objects, debug_info)); - if let Some(face) = a.face_iter().next() { + if let Some(face) = a.faces().into_iter().next() { // If there's at least one face to subtract from, we can proceed. let surface = face.surface(); - for face in a.face_iter() { + for face in a.faces() { assert_eq!( surface, face.surface(), @@ -53,7 +52,7 @@ impl Shape for fj::Difference2d { } } - for face in b.face_iter() { + for face in b.faces() { assert_eq!( surface, face.surface(),