use super::column_sampled_contour::*;
use super::distance_field::*;
use super::sampled_contour::*;
use super::scaled_contour::*;
use smallvec::*;
use std::ops::{Range};
pub struct ScaledDistanceField<TDistanceField> {
distance_field: TDistanceField,
scale_factor: f64,
offset_x: f64,
offset_y: f64,
size: ContourSize,
}
impl<TDistanceField> ScaledDistanceField<TDistanceField>
where
TDistanceField: SampledSignedDistanceField,
{
#[inline]
pub fn from_distance_field(distance_field: TDistanceField, scale_factor: f64, offset: (f64, f64)) -> Self {
let ContourSize(width, height) = distance_field.field_size();
let width = (width as f64) * scale_factor + offset.0;
let height = (height as f64) * scale_factor + offset.1;
let width = width.ceil();
let height = height.ceil();
let size = ContourSize(width as _, height as _);
let (offset_x, offset_y) = offset;
ScaledDistanceField { distance_field, scale_factor, size, offset_x, offset_y }
}
}
impl<TDistanceField> SampledSignedDistanceField for ScaledDistanceField<TDistanceField>
where
TDistanceField: SampledSignedDistanceField,
{
type Contour = ScaledDistanceField<TDistanceField>;
#[inline]
fn field_size(&self) -> ContourSize {
self.size
}
fn distance_at_point(&self, pos: super::ContourPosition) -> f64 {
let ContourPosition(x, y) = pos;
let x = x as f64 - self.offset_x;
let y = y as f64 - self.offset_y;
let distance_field = &self.distance_field;
let x = x / self.scale_factor;
let y = y / self.scale_factor;
let low_x = x.floor();
let low_y = y.floor();
let high_x = low_x + 1.0;
let high_y = low_y + 1.0;
let distances = [
[distance_field.distance_at_point(ContourPosition(low_x as _, low_y as _)), distance_field.distance_at_point(ContourPosition(low_x as _, high_y as _))],
[distance_field.distance_at_point(ContourPosition(high_x as _, low_y as _)), distance_field.distance_at_point(ContourPosition(high_x as _, high_y as _))]
];
let distance_x1 = ((high_x - x)/(high_x - low_x)) * distances[0][0] + ((x - low_x)/(high_x - low_x)) * distances[1][0];
let distance_x2 = ((high_x - x)/(high_x - low_x)) * distances[0][1] + ((x - low_x)/(high_x - low_x)) * distances[1][1];
let distance = ((high_y - y)/(high_y - low_y)) * distance_x1 + ((y - low_y)/(high_y - low_y)) * distance_x2;
distance * self.scale_factor
}
#[inline]
fn as_contour<'a>(&'a self) -> &'a Self::Contour {
self
}
}
impl<TDistanceField> SampledContour for ScaledDistanceField<TDistanceField>
where
TDistanceField: SampledSignedDistanceField,
{
#[inline]
fn contour_size(&self) -> ContourSize {
self.field_size()
}
#[inline]
fn intercepts_on_line(&self, y: f64) -> SmallVec<[Range<f64>; 4]> {
ScaledContour::from_contour(self.distance_field.as_contour(), self.scale_factor, (self.offset_x, self.offset_y)).intercepts_on_line(y)
}
}
impl<TDistanceField> ColumnSampledContour for ScaledDistanceField<TDistanceField>
where
TDistanceField: SampledSignedDistanceField,
TDistanceField::Contour: ColumnSampledContour,
{
#[inline]
fn intercepts_on_column(&self, x: f64) -> SmallVec<[Range<f64>; 4]> {
ScaledContour::from_contour(self.distance_field.as_contour(), self.scale_factor, (self.offset_x, self.offset_y)).intercepts_on_column(x)
}
}