我对样条线数据 struct 做了以下定义:
#[derive(Clone, Debug)]
pub struct BSpline
{
knots: Vec<f32>,
control_points: Vec<Vec3>,
/// Internal helper variable. Used to optimize repetetitive samplings on close
/// $t$ values.
last_t_index: usize,
order: usize,
}
impl BSpline
{
pub fn sample(&self, t: f32) -> Vec3
{
debug_assert!(self.control_points.len() >= self.order);
let t = f32::clamp(t, self.knots[0], *self.knots.last().unwrap());
let mut t_index = self.last_t_index;
while !(t >= self.knots[t_index] && t <= self.knots[t_index + 1])
{
t_index = (t_index + 1) % self.knots.len();
}
// TODO(low): find a better way than this hack.
let ptr = &self.last_t_index as *const usize as *mut usize;
unsafe {
ptr.write(usize::min(t_index, self.order - 1));
};
// Create the cache to compute the pyramid of intermediate evaluations.
let order = self.order;
let degree = order - 1;
let mut evaluation = Vec::new();
for i in 0..order
{
evaluation.push(self.control_points[t_index - degree + i]);
}
for l in 0..degree
{
for j in ((l + 1)..=degree).rev()
{
let alpha = (t - self.knots[t_index - degree + j])
/ (self.knots[t_index - l + j] - self.knots[t_index - degree + j]);
evaluation[j] = (1.0 - alpha) * evaluation[j - 1] + alpha * evaluation[j];
}
}
evaluation[degree]
}
}
请注意,为了使示例方法接受引用而不是可变引用,我需要做一个非常糟糕的修改.这当然会使整个数据 struct 变得不合理.
黑客攻击的原因:
-
我需要在样条线上计算许多一般定义的微分运算符,将这些运算符定义为取FnMut而不是Fn会导致大量多余的克隆,这是有问题的.
-
我需要速度快,我不想要来自互斥锁的开销,甚至不想来自原子布尔判断.
-
UnsafeCells不可克隆.
该代码仅用于单线程代码,在这种情况下应该可以正常工作,但这仍然是一个危险信号.我能做些什么来改善它吗?