#[derive(Debug)]
pub struct DDA<const N: usize>
{
index: [isize; N],
index_updates: [isize; N],
step_size: [f32; N],
cumulative_distances: [f32; N],
distance: f32,
}
impl<const N: usize> DDA<N>
{
pub fn new(
position: [f32; N],
box_corner_position: [f32; N],
direction: [f32; N],
index: [isize; N],
cell_width: f32,
) -> Self
{
let mut step_size = [0.0; N];
for i in 0..N
{
step_size[i] = cell_width / direction[i].abs();
}
let mut cumulative_parameter = [0.0; N];
for i in 0..N
{
let box_relative_position = position[i] - box_corner_position[i];
let cell_relative_position =
box_relative_position - index[i] as f32 * cell_width;
cumulative_parameter[i] = if direction[i] < 0.0
{
(cell_relative_position / direction[i]).abs()
}
else
{
(cell_width - cell_relative_position) / direction[i].abs()
};
debug_assert!(cumulative_parameter[i] >= 0.0);
}
let mut index_updates = [0; N];
for i in 0..N
{
index_updates[i] = direction[i].signum() as isize
}
let ret = Self {
distance: 0.0,
step_size,
index,
cumulative_distances: cumulative_parameter,
index_updates,
};
ret
}
}
impl<const N: usize> Iterator for DDA<N>
{
type Item = (f32, [isize; N]);
fn next(&mut self) -> Option<Self::Item>
{
let ret = (self.distance, self.index);
let mut t_next = self.cumulative_distances[0];
let mut distance_index = 0;
for i in 0..N
{
if self.cumulative_distances[i] < t_next
&& !self.cumulative_distances[i].is_infinite()
{
distance_index = i;
t_next = self.cumulative_distances[i];
}
}
self.index[distance_index] += self.index_updates[distance_index];
self.cumulative_distances[distance_index] += self.step_size[distance_index];
self.distance = t_next;
Some(ret)
}
}