1 use std::convert::{AsRef, AsMut, From};
2 use std::cell::{Cell, RefCell};
3 use std::marker::PhantomData;
4 use std::fmt::{Debug, Formatter};
5 use std::ops::Range;
6
7
8 use super::{BezCurve, Point2d, Float, Point, lerp};
9
10 /// A struct that contains range information for slicing, used for slicing into the global factor
11 /// vector. The reason this is used instead of stdlib's `Range` struct is that `Range` does not
12 /// implement Copy, which means we have to use `RefCell`s instead of `Cell`s for interior mutability.
13 #[derive(Copy, Clone)]
14 struct RangeSlice {
15 start: usize,
16 end: usize
17 }
18
19 impl RangeSlice {
20 #[inline]
new(start: usize, end: usize) -> RangeSlice21 fn new(start: usize, end: usize) -> RangeSlice {
22 RangeSlice {
23 start: start,
24 end: end
25 }
26 }
27
as_range(&self) -> Range<usize>28 fn as_range(&self) -> Range<usize> {
29 self.start..self.end
30 }
31
len(&self) -> usize32 fn len(&self) -> usize {
33 self.end - self.start
34 }
35 }
36
combination(n: u64, k: u64) -> u6437 fn combination(n: u64, k: u64) -> u64 {
38 factorial(n) / (factorial(k) * factorial(n - k))
39 }
40
factorial(mut n: u64) -> u6441 fn factorial(mut n: u64) -> u64 {
42 let mut accumulator: u64 = 1;
43 while n > 0 {
44 accumulator = accumulator.checked_mul(n).expect("Attempted to create Bézier curve with combination that overflow u64; decrease curve order");
45 n -= 1;
46 }
47 accumulator
48 }
49
50 /// Given the `order` and references to the `factors`, `dfactors`, and `vec` cells, update the
51 /// cells to contain accurate information about the factors of the order.
update_factors(order: usize, factors: &Cell<RangeSlice>, dfactors: &Cell<RangeSlice>, vec: &RefCell<Vec<u64>>)52 fn update_factors(order: usize, factors: &Cell<RangeSlice>, dfactors: &Cell<RangeSlice>, vec: &RefCell<Vec<u64>>) {
53 if factors.get().len() != order + 1 {
54 let mut vec = vec.borrow_mut();
55 // Remove everything from the vector without freeing memory
56 unsafe{ vec.set_len(0) };
57
58 // The vector stores both the factors of the order and the order's derivative, and this is the
59 // length necessary to contain those factors.
60 let new_len = (order + 1) * 2 - 1;
61 if vec.capacity() < new_len {
62 let reserve_amount = new_len - vec.capacity();
63 vec.reserve(reserve_amount);
64 }
65
66 {
67 let order = order as u64;
68
69 for k in 0..order + 1 {
70 vec.push(combination(order, k));
71 }
72
73 for k in 0..order {
74 vec.push(combination(order - 1, k));
75 }
76 }
77
78 factors.set(RangeSlice::new(0, order + 1));
79 dfactors.set(RangeSlice::new(order + 1, vec.len()));
80 }
81 }
82
83
84 /// An n-order bezier curve. The `from_slice`, `split`, and `split_unbounded` functions currently do not work.
85 #[derive(Clone)]
86 pub struct NBez<F, P = Point2d<F>, C = Vec<P>>
87 where F: Float,
88 P: Point<F>,
89 C: AsRef<[P]> + AsMut<[P]> {
90 points: C,
91 factor_vec: RefCell<Vec<u64>>,
92 factors: Cell<RangeSlice>,
93 dfactors: Cell<RangeSlice>,
94 phantom: PhantomData<(F, P)>
95 }
96
97 impl<F, P, C> From<C> for NBez<F, P, C>
98 where F: Float,
99 P: Point<F>,
100 C: AsRef<[P]> + AsMut<[P]> {
from(container: C) -> NBez<F, P, C>101 fn from(container: C) -> NBez<F, P, C> {
102 NBez::from_container(container)
103 }
104 }
105
106 impl<F, P, C> NBez<F, P, C>
107 where F: Float,
108 P: Point<F>,
109 C: AsRef<[P]> + AsMut<[P]> {
110 #[inline]
from_container(points: C) -> NBez<F, P, C>111 pub fn from_container(points: C) -> NBez<F, P, C> {
112 if points.as_ref().len() >= 22 {
113 panic!("Cannot create Bézier polynomials with an order >= 21")
114 }
115
116 NBez {
117 points: points,
118 factor_vec: RefCell::new(Vec::new()),
119 factors: Cell::new(RangeSlice::new(0, 0)),
120 dfactors: Cell::new(RangeSlice::new(0, 0)),
121 phantom: PhantomData
122 }
123 }
124
125 #[inline]
unwrap(self) -> C126 pub fn unwrap(self) -> C {
127 self.points
128 }
129 }
130
131 impl<F, P, C> BezCurve<F> for NBez<F, P, C>
132 where F: Float,
133 P: Point<F>,
134 C: AsRef<[P]> + AsMut<[P]> {
135 type Point = P;
136 type Elevated = NBez<F, P, Vec<P>>;
137
138 /// Currently non-functional; returns `None`
from_slice(_: &[P]) -> Option<NBez<F, P, C>>139 fn from_slice(_: &[P]) -> Option<NBez<F, P, C>> {
140 None
141 }
142
interp_unbounded(&self, t: F) -> P143 fn interp_unbounded(&self, t: F) -> P {
144 let points = self.points.as_ref();
145 update_factors(self.order(), &self.factors, &self.dfactors, &self.factor_vec);
146 let factors = &self.factor_vec.borrow()[self.factors.get().as_range()];
147
148
149 let t1 = F::from_f32(1.0).unwrap() - t;
150 let order = factors.len() - 1;
151 let mut acc = P::zero();
152 let mut factor = 0;
153
154 for point in points.iter() {
155 acc = acc + *point *
156 t.powi(factor as i32) *
157 t1.powi((order - factor) as i32) *
158 F::from_u64(factors[factor]).unwrap();
159 factor += 1;
160 }
161 acc
162 }
163
slope_unbounded(&self, t: F) -> P::Vector164 fn slope_unbounded(&self, t: F) -> P::Vector {
165 let points = self.points.as_ref();
166 update_factors(self.order(), &self.factors, &self.dfactors, &self.factor_vec);
167 let dfactors = &self.factor_vec.borrow()[self.dfactors.get().as_range()];
168
169 let t1 = F::from_f32(1.0).unwrap() - t;
170 let order = dfactors.len() - 1;
171 let mut acc = P::zero();
172 let mut factor = 0;
173 let mut point_last = points[0].clone();
174
175 for point in points[1..].iter().map(|p| *p) {
176 acc = acc + (point - point_last) *
177 t.powi(factor as i32) *
178 t1.powi((order-factor) as i32) *
179 F::from_u64(dfactors[factor] * (order + 1) as u64).unwrap();
180 point_last = point;
181 factor += 1;
182 }
183 acc.into()
184 }
185
elevate(&self) -> NBez<F, P, Vec<P>>186 fn elevate(&self) -> NBez<F, P, Vec<P>> {
187 let points = self.points.as_ref();
188 let order = self.order() + 1;
189 let order_f = F::from_usize(order).unwrap();
190
191 // Elevated points
192 let mut el_points = Vec::with_capacity(order + 1);
193 el_points.push(points[0]);
194
195 let mut prev_p = points[0];
196 for (i, p) in points.iter().map(|p| *p).enumerate().skip(1) {
197 el_points.push(lerp(p, prev_p, F::from_usize(i).unwrap()/order_f));
198
199 prev_p = p;
200 }
201
202 el_points.push(points[self.order()]);
203 NBez::from_container(el_points)
204 }
205
206 /// Currently non-functional; returns `None`
split(&self, _: F) -> Option<(NBez<F, P, C>, NBez<F, P, C>)>207 fn split(&self, _: F) -> Option<(NBez<F, P, C>, NBez<F, P, C>)> {
208 None
209 }
210
211 /// Currently non-functional; panics with unimplemented
split_unbounded(&self, _: F) -> (NBez<F, P, C>, NBez<F, P, C>)212 fn split_unbounded(&self, _: F) -> (NBez<F, P, C>, NBez<F, P, C>) {
213 unimplemented!()
214 }
215
order(&self) -> usize216 fn order(&self) -> usize {
217 self.points.as_ref().len()-1
218 }
219 }
220
221 impl<F, P, C> AsRef<C> for NBez<F, P, C>
222 where F: Float,
223 P: Point<F>,
224 C: AsRef<[P]> + AsMut<[P]> {
as_ref(&self) -> &C225 fn as_ref(&self) -> &C {
226 &self.points
227 }
228 }
229
230 impl<F, P, C> AsMut<C> for NBez<F, P, C>
231 where F: Float,
232 P: Point<F>,
233 C: AsRef<[P]> + AsMut<[P]> {
as_mut(&mut self) -> &mut C234 fn as_mut(&mut self) -> &mut C {
235 &mut self.points
236 }
237 }
238
239 impl<F, P, C> AsRef<[P]> for NBez<F, P, C>
240 where F: Float,
241 P: Point<F>,
242 C: AsRef<[P]> + AsMut<[P]> {
as_ref(&self) -> &[P]243 fn as_ref(&self) -> &[P] {
244 self.points.as_ref()
245 }
246 }
247
248 impl<F, P, C> AsMut<[P]> for NBez<F, P, C>
249 where F: Float,
250 P: Point<F>,
251 C: AsRef<[P]> + AsMut<[P]> {
as_mut(&mut self) -> &mut [P]252 fn as_mut(&mut self) -> &mut [P] {
253 self.points.as_mut()
254 }
255 }
256
257 impl<F, P, C> Debug for NBez<F, P, C>
258 where F: Float,
259 P: Point<F>,
260 C: AsRef<[P]> + AsMut<[P]> + Debug {
fmt(&self, f: &mut Formatter) -> Result<(), ::std::fmt::Error>261 fn fmt(&self, f: &mut Formatter) -> Result<(), ::std::fmt::Error> {
262 f.debug_tuple("NBez")
263 .field(&self.points)
264 .finish()
265 }
266 }
267