1mod tests;
2pub mod control;
3
4use std::ops::{Mul, Range};
5
6use num::{Float, NumCast};
7use vector2d::Vector2D;
8
9pub use control::{Continuity, Direction, Handle, Validity};
10
11#[macro_export]
12macro_rules! point {
13 ($x : expr,$y : expr) => {
14 Vector2D::new($x, $y)
15 };
16}
17
18pub struct Bezier<F: Float> {
44 handles: Vec<Handle<F>>,
45 detail: usize,
46
47 num_ignored: usize,
48 points: Vec<Vector2D<F>>,
49}
50
51fn interpolate<T: Float>(a: &Vector2D<T>, b: &Vector2D<T>, t: T) -> Vector2D<T> {
52 a.mul(T::one() - t) + b.mul(t)
53}
54
55impl<F: Float> Bezier<F> {
56 pub fn new(detail: usize, expected_handle_num: usize) -> Self {
57 Bezier {
58 handles: Vec::with_capacity(expected_handle_num),
59 detail,
60 points: Vec::with_capacity(expected_handle_num * detail),
61 num_ignored: 0,
62 }
63 }
64
65 fn invalidate_handle(&mut self, handle_index: usize) {
66 if handle_index >= self.handles.len() {
67 return;
68 }
69 self.handles[handle_index as usize].validity = Validity::Invalidated;
70 }
71
72 pub fn push(&mut self, handle: Handle<F>) {
73 self.handles.push(handle);
74 }
75 pub fn insert(&mut self, index: usize, handle: Handle<F>) {
76 if index != 0 {
77 self.invalidate_handle(index - 1);
78 }
79 self.handles.insert(index, handle);
80 }
81 pub fn splice(&mut self, range: Range<usize>, handles: Vec<Handle<F>>) {
82 if range.start != 0 {
83 self.invalidate_handle(range.start - 1);
84 }
85 self.handles.splice(range, handles);
86 }
87
88 pub fn remove(&mut self, index: usize) {
89 if index != 0 {
90 self.invalidate_handle(index - 1);
91 }
92 self.handles.remove(index);
93 }
94 pub fn drain(&mut self, range: Range<usize>) {
95 if range.start != 0 {
96 self.invalidate_handle(range.start - 1);
97 }
98 self.handles.drain(range);
99 }
100
101 pub fn get_handle(&self, index: usize) -> &Handle<F> {
102 &self.handles[index]
103 }
104 pub fn get_handle_mut(&mut self, index: usize) -> &mut Handle<F> {
105 self.invalidate_handle(index);
106 &mut self.handles[index]
107 }
108
109 pub fn knot_insert(&mut self, mut time: F) {
131 let part_index = <usize as NumCast>::from(time).unwrap();
132 if part_index >= self.handles.len() - 1 {
133 panic!("Knot insertion failed because time was out of bounds.")
134 }
135 let points = self.part_points(part_index);
136 time = time - time.floor();
137
138 let center_point = interpolate(points[1], points[2], time);
139
140 let prev_forward = interpolate(points[0], points[1], time);
141 let next_backward = interpolate(points[2], points[3], time);
142 let new_backward = interpolate(&prev_forward, ¢er_point, time);
143 let new_forward = interpolate(¢er_point, &next_backward, time);
144 let new_position = interpolate(&new_backward, &new_forward, time);
145
146 self.handles[part_index].after = prev_forward;
147 self.handles[part_index + 1].before = next_backward;
148
149 let handle = Handle::new(new_backward, new_position, new_forward);
150 self.handles.insert(part_index + 1, handle);
151 }
152
153 fn part_points(&self, part_index: usize) -> [&Vector2D<F>; 4] {
155 if part_index >= self.handles.len() - 1 {
156 panic!("part_index exceeds part length in part_points");
157 }
158 [
159 &self.handles[part_index].position,
160 &self.handles[part_index].after,
161 &self.handles[part_index + 1].before,
162 &self.handles[part_index + 1].position,
163 ]
164 }
165 pub fn all_part_point(&self) -> Vec<Vector2D<F>> {
167 let mut result: Vec<Vector2D<F>> = vec![];
168 for part_index in 0..self.handles.len() - 1 {
169 result.push(self.part_points(part_index)[0].to_owned());
170 result.push(self.part_points(part_index)[1].to_owned());
171 result.push(self.part_points(part_index)[2].to_owned());
172 result.push(self.part_points(part_index)[3].to_owned());
173 }
174 result
175 }
176 fn part_is_empty(&self, part_index: usize) -> bool {
178 if part_index >= self.handles.len() - 1 {
179 panic!("part_index exceeds part length in part_is_empty");
180 }
181 self.handles[part_index].continuity == Continuity::Detached(Direction::Forward)
182 || self.handles[part_index].continuity == Continuity::Detached(Direction::Both)
183 || self.handles[part_index + 1].continuity == Continuity::Detached(Direction::Backward)
184 || self.handles[part_index + 1].continuity == Continuity::Detached(Direction::Both)
185 }
186 fn calculate_part(&mut self, part_index: usize) {
190 if part_index >= self.handles.len() - 1 {
191 panic!("part_index exceeds part length in calculate_part");
192 }
193 let validity = &self.handles[part_index].validity;
194 if self.part_is_empty(part_index) {
195 self.num_ignored += 1;
196 return;
197 }
198 if validity == &Validity::Valid {
199 return;
200 }
201
202 let controls = self.part_points(part_index);
203
204 let f_three = F::from(3.0).unwrap();
205 let f_six = F::from(6.0).unwrap();
206 let coefficients = (
207 *controls[0],
208 controls[0].mul(-f_three) + controls[1].mul(f_three),
209 controls[0].mul(f_three) + controls[1].mul(-f_six) + controls[2].mul(f_three),
210 controls[0].mul(-F::one())
211 + controls[1].mul(f_three)
212 + controls[2].mul(-f_three)
213 + *controls[3],
214 );
215
216 let start_index = (self.detail) * (part_index - self.num_ignored);
217 if validity == &Validity::Uninitialized {
218 self.points.splice(
219 start_index..start_index,
220 vec![Vector2D::new(F::zero(), F::zero()); self.detail],
221 );
222 }
223
224 for point_index in 0..self.detail {
225 let t = F::from(point_index).unwrap() / F::from(self.detail).unwrap();
226 let tpow2 = t * t;
227 let tpow3 = t * tpow2;
228 self.points[start_index + point_index] = coefficients.0
229 + coefficients.1.mul(t)
230 + coefficients.2.mul(tpow2)
231 + coefficients.3.mul(tpow3);
232 }
233 self.handles[part_index].validity = Validity::Valid;
234 }
235
236 pub fn calculate(&mut self) -> &Vec<Vector2D<F>> {
250 self.num_ignored = 0;
251 for part_index in 0..self.handles.len() - 1 {
252 self.calculate_part(part_index);
253 }
254 &self.points
255 }
256}