Add Point3Normalizer
This commit is contained in:
parent
259505e93f
commit
49bef6f0f4
|
|
@ -1,7 +1,11 @@
|
||||||
|
use super::axis_aligned_bounding_box::BoundingBox;
|
||||||
use super::Interval;
|
use super::Interval;
|
||||||
|
|
||||||
use nalgebra::{clamp, RealField};
|
use nalgebra::{clamp, Point3, RealField};
|
||||||
|
|
||||||
|
use itertools::izip;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct RealFieldNormalizer<T: RealField> {
|
pub struct RealFieldNormalizer<T: RealField> {
|
||||||
min: T,
|
min: T,
|
||||||
range: T,
|
range: T,
|
||||||
|
|
@ -23,6 +27,51 @@ impl<T: RealField> RealFieldNormalizer<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Point3Normalizer<T: RealField> {
|
||||||
|
dimension_normalizers: [RealFieldNormalizer<T>; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RealField> Point3Normalizer<T> {
|
||||||
|
pub fn new(bounds: BoundingBox<T>) -> Self {
|
||||||
|
let mut normalizer = Point3Normalizer {
|
||||||
|
dimension_normalizers: [RealFieldNormalizer::new(Interval::empty()); 3],
|
||||||
|
};
|
||||||
|
for (normalizer, &bounds) in normalizer
|
||||||
|
.dimension_normalizers
|
||||||
|
.iter_mut()
|
||||||
|
.zip(bounds.bounds.iter())
|
||||||
|
{
|
||||||
|
*normalizer = RealFieldNormalizer::new(bounds);
|
||||||
|
}
|
||||||
|
normalizer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn normalize(&self, point: Point3<T>) -> Point3<T> {
|
||||||
|
let mut result = Point3::new(T::zero(), T::zero(), T::zero());
|
||||||
|
for (value_out, &value_in, normalizer) in izip!(
|
||||||
|
result.iter_mut(),
|
||||||
|
point.iter(),
|
||||||
|
self.dimension_normalizers.iter()
|
||||||
|
) {
|
||||||
|
*value_out = normalizer.normalize(value_in);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn normalize_and_clamp(&self, point: Point3<T>) -> Point3<T> {
|
||||||
|
let mut result = Point3::new(T::zero(), T::zero(), T::zero());
|
||||||
|
for (value_out, &value_in, normalizer) in izip!(
|
||||||
|
result.iter_mut(),
|
||||||
|
point.iter(),
|
||||||
|
self.dimension_normalizers.iter()
|
||||||
|
) {
|
||||||
|
*value_out = normalizer.normalize_and_clamp(value_in);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -94,4 +143,48 @@ mod test {
|
||||||
let target = RealFieldNormalizer::new(Interval::new(2.0, 4.0));
|
let target = RealFieldNormalizer::new(Interval::new(2.0, 4.0));
|
||||||
target.normalize_and_clamp(value) == target.normalize(value) || value < 2.0 || value > 4.0
|
target.normalize_and_clamp(value) == target.normalize(value) || value < 2.0 || value > 4.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn normalize_point3_is_the_same_as_normalize_each_dimension(
|
||||||
|
a: Point3<f64>,
|
||||||
|
b: Point3<f64>,
|
||||||
|
c: Point3<f64>,
|
||||||
|
) -> bool {
|
||||||
|
let x_normalizer = RealFieldNormalizer::new(Interval::new(a.x.min(b.x), a.x.max(b.x)));
|
||||||
|
let y_normalizer = RealFieldNormalizer::new(Interval::new(a.y.min(b.y), a.y.max(b.y)));
|
||||||
|
let z_normalizer = dbg!(RealFieldNormalizer::new(Interval::new(
|
||||||
|
a.z.min(b.z),
|
||||||
|
a.z.max(b.z)
|
||||||
|
)));
|
||||||
|
let xyz_normalizer = Point3Normalizer::new(BoundingBox::from_corners(a, b));
|
||||||
|
let normalized_point = xyz_normalizer.normalize(c);
|
||||||
|
x_normalizer.normalize(c.x) == normalized_point.x
|
||||||
|
&& y_normalizer.normalize(c.y) == normalized_point.y
|
||||||
|
&& z_normalizer.normalize(c.z) == normalized_point.z
|
||||||
|
}
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn normalize_and_clamp_point3_is_the_same_as_normalize_and_clamp_each_dimension(
|
||||||
|
a: Point3<f64>,
|
||||||
|
b: Point3<f64>,
|
||||||
|
c: Point3<f64>,
|
||||||
|
) -> bool {
|
||||||
|
let x_normalizer = dbg!(RealFieldNormalizer::new(Interval::new(
|
||||||
|
a.x.min(b.x),
|
||||||
|
a.x.max(b.x)
|
||||||
|
)));
|
||||||
|
let y_normalizer = dbg!(RealFieldNormalizer::new(Interval::new(
|
||||||
|
a.y.min(b.y),
|
||||||
|
a.y.max(b.y)
|
||||||
|
)));
|
||||||
|
let z_normalizer = dbg!(RealFieldNormalizer::new(Interval::new(
|
||||||
|
a.z.min(b.z),
|
||||||
|
a.z.max(b.z)
|
||||||
|
)));
|
||||||
|
let xyz_normalizer = dbg!(Point3Normalizer::new(BoundingBox::from_corners(a, b)));
|
||||||
|
let normalized_point = xyz_normalizer.normalize_and_clamp(c);
|
||||||
|
dbg!(x_normalizer.normalize_and_clamp(c.x)) == dbg!(normalized_point.x)
|
||||||
|
&& y_normalizer.normalize_and_clamp(c.y) == normalized_point.y
|
||||||
|
&& z_normalizer.normalize_and_clamp(c.z) == normalized_point.z
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue