use std::collections::VecDeque;
use crate::{
objects::{
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Shell, Sketch,
Solid, Surface, Vertex,
},
stores::Handle,
};
pub trait ObjectIters<'r> {
fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters>;
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
}
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
}
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
}
fn global_curve_iter(&'r self) -> Iter<&'r Handle<GlobalCurve>> {
let mut iter = Iter::empty();
for object in self.referenced_objects() {
iter = iter.with_handles(object.global_curve_iter());
}
iter
}
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
}
fn half_edge_iter(&'r self) -> Iter<&'r HalfEdge> {
let mut iter = Iter::empty();
for object in self.referenced_objects() {
iter = iter.with(object.half_edge_iter());
}
iter
}
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
}
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
}
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
}
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
}
fn vertex_iter(&'r self) -> Iter<&'r Vertex> {
let mut iter = Iter::empty();
for object in self.referenced_objects() {
iter = iter.with(object.vertex_iter());
}
iter
}
}
impl<'r> ObjectIters<'r> for Handle<Curve> {
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 Cycle {
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 Face {
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<GlobalCurve> {
fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> {
Vec::new()
}
fn global_curve_iter(&'r self) -> Iter<&'r Handle<GlobalCurve>> {
Iter::from_object(self)
}
}
impl<'r> ObjectIters<'r> for Handle<GlobalVertex> {
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 HalfEdge {
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 HalfEdge> {
Iter::from_object(self)
}
}
impl<'r> ObjectIters<'r> for Shell {
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 face in self.shells() {
objects.push(face as &dyn ObjectIters);
}
objects
}
fn solid_iter(&'r self) -> Iter<&'r Solid> {
Iter::from_object(self)
}
}
impl<'r> ObjectIters<'r> for Handle<Surface> {
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 Vertex {
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 Vertex> {
Iter::from_object(self)
}
}
impl<'r, T, O> ObjectIters<'r> for T
where
T: 'r,
O: ObjectIters<'r> + 'r,
&'r T: IntoIterator<Item = &'r O>,
{
fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> {
let mut objects = Vec::new();
for object in self.into_iter() {
objects.push(object as &dyn ObjectIters);
}
objects
}
}
pub struct Iter<T>(VecDeque<T>);
impl<T> Iter<T> {
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<T> Iter<&'_ Handle<T>> {
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<T> Iterator for Iter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop_front()
}
}
#[cfg(test)]
mod tests {
use crate::{
objects::{
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Shell,
Sketch, Solid, Surface, SurfaceVertex, Vertex,
},
partial::HasPartial,
stores::{Handle, Stores},
};
use super::ObjectIters as _;
#[test]
fn curve() {
let stores = Stores::new();
let surface = stores.surfaces.insert(Surface::xy_plane());
let object = Handle::<Curve>::partial()
.with_surface(Some(surface))
.as_u_axis()
.build(&stores);
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 stores = Stores::new();
let surface = stores.surfaces.insert(Surface::xy_plane());
let object = Cycle::partial()
.with_surface(Some(surface))
.with_poly_chain_from_points([[0., 0.], [1., 0.], [0., 1.]])
.close_with_line_segment()
.build(&stores);
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 stores = Stores::new();
let surface = stores.surfaces.insert(Surface::xy_plane());
let object = Face::builder(&stores, surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]])
.build();
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 stores = Stores::new();
let object = GlobalCurve::new(&stores);
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 stores = Stores::new();
let object = GlobalVertex::from_position([0., 0., 0.], &stores);
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 stores = Stores::new();
let object = HalfEdge::partial()
.with_surface(Some(stores.surfaces.insert(Surface::xy_plane())))
.as_line_segment_from_points([[0., 0.], [1., 0.]])
.build(&stores);
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 stores = Stores::new();
let object = Shell::builder(&stores).build_cube_from_edge_length(1.);
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 stores = Stores::new();
let surface = stores.surfaces.insert(Surface::xy_plane());
let face = Face::builder(&stores, surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]])
.build();
let object = Sketch::new().with_faces([face]);
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 stores = Stores::new();
let object = Solid::builder(&stores).build_cube_from_edge_length(1.);
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 stores = Stores::new();
let object = stores.surfaces.insert(Surface::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 stores = Stores::new();
let surface = stores.surfaces.insert(Surface::xy_plane());
let curve = Handle::<Curve>::partial()
.with_surface(Some(surface.clone()))
.as_u_axis()
.build(&stores);
let global_vertex = GlobalVertex::from_position([0., 0., 0.], &stores);
let surface_vertex =
SurfaceVertex::new([0., 0.], surface, global_vertex);
let object = Vertex::new([0.], curve, surface_vertex);
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());
}
}