diff --git a/Cargo.lock b/Cargo.lock index dcdac5d..ecd1fe5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -873,6 +873,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if 1.0.0", + "libc 0.2.153", + "wasi", +] + [[package]] name = "gif" version = "0.11.4" @@ -908,6 +919,10 @@ name = "glam" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" +dependencies = [ + "approx", + "rand", +] [[package]] name = "glob" @@ -1634,6 +1649,12 @@ dependencies = [ "miniz_oxide 0.3.7", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -1667,6 +1688,45 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc 0.2.153", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core", +] + [[package]] name = "raw-window-handle" version = "0.3.4" @@ -1724,6 +1784,8 @@ dependencies = [ "flo_draw", "glam", "itertools-num", + "rand", + "rand_pcg", ] [[package]] @@ -2114,6 +2176,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wayland-client" version = "0.28.6" diff --git a/Cargo.toml b/Cargo.toml index 7b8cfd7..2ad40d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,10 +12,12 @@ panic = 'abort' opt-level = 3 [dependencies] -glam = "0.27.0" +glam = { version = "0.27.0", features = ["approx", "fast-math", "rand"] } flo_draw = "0.3.1" flo_canvas = "0.3.1" itertools-num = "0.1.3" [dev-dependencies] approx = "0.5.1" +rand = "0.8.5" +rand_pcg = "0.3.1" diff --git a/src/bin/flat/riemann.rs b/src/bin/flat/riemann.rs index 24b154f..a06ae24 100644 --- a/src/bin/flat/riemann.rs +++ b/src/bin/flat/riemann.rs @@ -1,5 +1,6 @@ use glam::*; +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Decomp2 { pub ortho: Mat2, pub diag: Vec2, @@ -13,7 +14,7 @@ impl Decomp2 { } } - pub(crate) fn inverse(&self) -> Self { + pub fn inverse(&self) -> Self { Self { ortho: self.ortho, diag: Vec2::splat(1.0) / self.diag, @@ -146,3 +147,49 @@ fn t2() { assert_eq!(t[0].col(1)[1], 6.0); assert_eq!(t[1].col(1)[1], 7.0); } + +pub mod samples { + use glam::{Mat2, Vec2}; + + use super::{Decomp2, Metric}; + + pub struct ScaledMetric { + pub scale: Vec2, + } + + impl Metric for ScaledMetric { + fn sqrt_at(&self, _pos: Vec2) -> Decomp2 { + Decomp2 { + diag: self.scale, + ortho: Mat2::IDENTITY, + } + } + } +} + +#[cfg(test)] +mod tests { + use glam::{Mat2, mat2, vec2}; + use rand::{Rng, SeedableRng}; + + use super::{Decomp2, Metric, samples}; + + #[test] + fn uniform_scaled_metric() { + let mut rng = rand_pcg::Pcg64Mcg::seed_from_u64(17); + let metric = samples::ScaledMetric { scale: vec2(3., 4.) }; + assert_eq!(metric.sqrt_at(rng.gen()), Decomp2 { ortho: Mat2::IDENTITY, diag: vec2(3., 4.) }); + assert_eq!(metric.at(rng.gen()), Mat2::from_cols_array(&[9., 0., 0., 16.])); + assert_eq!(metric.inverse_at(rng.gen()), Mat2::from_cols_array(&[1. / 9., 0., 0., 1. / 16.])); + assert_eq!(metric.part_derivs_at(rng.gen()), [Mat2::ZERO, Mat2::ZERO]); + assert_eq!(metric.vec_length_at(rng.gen(), vec2(1., 0.)), 3.); + assert_eq!(metric.vec_length_at(rng.gen(), vec2(0., 1.)), 4.); + assert_eq!(metric.vec_length_at(rng.gen(), vec2(1., 1.)), 5.); + assert_eq!(metric.normalize_vec_at(rng.gen(), vec2(1., 0.)), vec2(1. / 3., 0.)); + assert_eq!(metric.normalize_vec_at(rng.gen(), vec2(0., 1.)), vec2(0., 1. / 4.)); + assert_eq!(metric.normalize_vec_at(rng.gen(), vec2(1., 1.)), vec2(1. / 5., 1. / 5.)); + assert_eq!(metric.globalize(rng.gen(), vec2(1., 0.)), vec2(1. / 3., 0.)); + assert_eq!(metric.globalize(rng.gen(), vec2(0., 1.)), vec2(0., 1. / 4.)); + assert_eq!(metric.globalize(rng.gen(), vec2(1., 1.)), vec2(1. / 3., 1. / 4.)); + } +} diff --git a/src/bin/flat/tube/coords.rs b/src/bin/flat/tube/coords.rs index de2e614..cd5ba46 100644 --- a/src/bin/flat/tube/coords.rs +++ b/src/bin/flat/tube/coords.rs @@ -113,13 +113,34 @@ impl FlatRegion for OuterCS { } #[cfg(test)] -mod test { +mod tests { use approx::{AbsDiffEq, assert_abs_diff_eq}; - use glam::{Mat2, vec2, Vec2}; + use glam::{Mat2, mat2, vec2, Vec2}; use itertools_num::linspace; + use crate::riemann::samples; + use super::*; + #[test] + fn uniform_scaled_metric() { + struct Scaled(samples::ScaledMetric, Vec2); + impl FlatCoordinateSystem for Scaled { + fn flat_to_global(&self, pos: Vec2) -> Vec2 { (pos - self.1) / self.0.scale } + fn global_to_flat(&self, pos: Vec2) -> Vec2 { pos * self.0.scale + self.1 } + } + impl MetricCS for Scaled { + fn global_metric(&self) -> &impl Metric { &self.0 } + } + let cs = Scaled(samples::ScaledMetric { scale: vec2(3., 4.) }, vec2(2., 3.)); + assert_eq!(cs.global_to_flat(vec2(7., 3.)), vec2(23., 15.)); + assert_eq!(cs.flat_to_global(vec2(8., 7.)), vec2(2., 1.)); + assert_eq!(cs.global_to_flat(Ray { pos: vec2(7., 3.), dir: vec2(3., 2.) }), Ray { pos: vec2(23., 15.), dir: vec2(9., 8.) }); + assert_eq!(cs.flat_to_global(Ray { pos: vec2(23., 15.), dir: vec2(9., 8.) }), Ray { pos: vec2(7., 3.), dir: vec2(3., 2.) }); + assert_eq!(cs.global_to_flat(Location { pos: vec2(2., 1.), rot: mat2(vec2(0., 1.), vec2(-1., 0.)) }), Location { pos: vec2(8., 7.), rot: mat2(vec2(0., 4.), vec2(-3., 0.)) }); + assert_eq!(cs.flat_to_global(Location { pos: vec2(2., 1.), rot: mat2(vec2(0., 1.), vec2(-1., 0.)) }), Location { pos: vec2(0., -0.5), rot: mat2(vec2(0., 0.25), vec2(-1. / 3., 0.)) }); + } + fn test_flat_region(region: &impl FlatRegion, range_global: (Vec2, Vec2), range_flat: (Vec2, Vec2)) { const ε: f32 = 1e-3; macro_rules! assert_eq_at { diff --git a/src/bin/flat/tube/metric.rs b/src/bin/flat/tube/metric.rs index 03ab641..308a8ee 100644 --- a/src/bin/flat/tube/metric.rs +++ b/src/bin/flat/tube/metric.rs @@ -168,7 +168,6 @@ mod test { let Δ = vec2(0.0, 2.0 * (space.tube.internal_halflength + off)); let dir = Δ / (steps as f32); let traced = space.trace_iter(Ray { pos: a, dir }).nth(steps).unwrap(); - println!("{traced:?}"); assert_abs_diff_eq!(traced.pos.x, b.x, epsilon=1.0e-1); assert_abs_diff_eq!(traced.pos.y, b.y, epsilon=1.0e0); assert_abs_diff_eq!(traced.dir.x, dir.x, epsilon=1.0e-2); diff --git a/src/bin/flat/types.rs b/src/bin/flat/types.rs index 101348a..2edc6d8 100644 --- a/src/bin/flat/types.rs +++ b/src/bin/flat/types.rs @@ -20,7 +20,7 @@ impl std::ops::Mul for Mat2 { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Location { /// Положение в основной СК pub pos: Vec2,