use super::{
density::{Density, ScalarField, Coordinate},
structs::Block,
voxel_coordinates::{HighResolutionVoxelIndex, RegularVoxelIndex},
};
pub trait VoxelSource<D: Density> {
fn get_density(&self, voxel_index: &RegularVoxelIndex) -> D;
fn get_transition_density(&self, index: &HighResolutionVoxelIndex) -> D;
}
pub struct WorldMappingVoxelSource<'b, S, C>
where C: Coordinate,
{
pub field: S,
pub block: &'b Block<C>,
}
impl<'a, 'b, S, D, C> VoxelSource<D> for WorldMappingVoxelSource<'b, S, C>
where
D: Density,
S: ScalarField<D, C>,
C: Coordinate,
{
fn get_density(&self, voxel_index: &RegularVoxelIndex) -> D {
let x = self.block.dims.base[0]
+ self.block.dims.size * C::from_ratio(voxel_index.x, self.block.subdivisions);
let y = self.block.dims.base[1]
+ self.block.dims.size * C::from_ratio(voxel_index.y, self.block.subdivisions);
let z = self.block.dims.base[2]
+ self.block.dims.size * C::from_ratio(voxel_index.z, self.block.subdivisions);
let d = self.field.get_density(x, y, z);
d
}
fn get_transition_density(&self, index: &HighResolutionVoxelIndex) -> D {
let rotation = super::implementation::rotation::Rotation::for_side(index.cell.side);
let position_in_block = rotation.to_position_in_block::<C>(self.block.subdivisions, index);
let x = self.block.dims.base[0]
+ self.block.dims.size * position_in_block.x;
let y = self.block.dims.base[1]
+ self.block.dims.size * position_in_block.y;
let z = self.block.dims.base[2]
+ self.block.dims.size * position_in_block.z;
self.field.get_density(x, y, z)
}
}
impl<D, F> VoxelSource<D> for &mut F
where
D: Density,
F: VoxelSource<D> + ?Sized,
{
fn get_density(&self, voxel_index: &RegularVoxelIndex) -> D {
(**self).get_density(voxel_index)
}
fn get_transition_density(&self, index: &HighResolutionVoxelIndex) -> D {
(**self).get_transition_density(index)
}
}