1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
mod core;
mod lookup;
mod manipulators;
mod solvers;
mod structs;
mod transform;
pub use structs::*;

use crate::Bezier;

use std::fmt::{Debug, Formatter, Result};
use std::ops::{Index, IndexMut};

/// Structure used to represent a path composed of [Bezier] curves.
#[derive(Clone, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Subpath<ManipulatorGroupId: crate::Identifier> {
	manipulator_groups: Vec<ManipulatorGroup<ManipulatorGroupId>>,
	pub closed: bool,
}

#[cfg(feature = "dyn-any")]
unsafe impl<ManipulatorGroupId: crate::Identifier> dyn_any::StaticType for Subpath<ManipulatorGroupId> {
	type Static = Subpath<ManipulatorGroupId>;
}

/// Iteration structure for iterating across each curve of a `Subpath`, using an intermediate `Bezier` representation.
pub struct SubpathIter<'a, ManipulatorGroupId: crate::Identifier> {
	index: usize,
	subpath: &'a Subpath<ManipulatorGroupId>,
}

impl<ManipulatorGroupId: crate::Identifier> Index<usize> for Subpath<ManipulatorGroupId> {
	type Output = ManipulatorGroup<ManipulatorGroupId>;

	fn index(&self, index: usize) -> &Self::Output {
		assert!(index < self.len(), "Index out of bounds in trait Index of SubPath.");
		&self.manipulator_groups[index]
	}
}

impl<ManipulatorGroupId: crate::Identifier> IndexMut<usize> for Subpath<ManipulatorGroupId> {
	fn index_mut(&mut self, index: usize) -> &mut Self::Output {
		assert!(index < self.len(), "Index out of bounds in trait IndexMut of SubPath.");
		&mut self.manipulator_groups[index]
	}
}

impl<ManipulatorGroupId: crate::Identifier> Iterator for SubpathIter<'_, ManipulatorGroupId> {
	type Item = Bezier;

	// Returns the Bezier representation of each `Subpath` segment, defined between a pair of adjacent manipulator points.
	fn next(&mut self) -> Option<Self::Item> {
		if self.subpath.is_empty() {
			return None;
		}
		let len = self.subpath.len() - 1
			+ match self.subpath.closed {
				true => 1,
				false => 0,
			};
		if self.index >= len {
			return None;
		}
		let start_index = self.index;
		let end_index = (self.index + 1) % self.subpath.len();
		self.index += 1;

		Some(self.subpath[start_index].to_bezier(&self.subpath[end_index]))
	}
}

impl<ManipulatorGroupId: crate::Identifier> Debug for Subpath<ManipulatorGroupId> {
	fn fmt(&self, f: &mut Formatter<'_>) -> Result {
		f.debug_struct("Subpath").field("closed", &self.closed).field("manipulator_groups", &self.manipulator_groups).finish()
	}
}