From 1faf395c34e9aa805529779695a9261a373bbced Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 28 Apr 2024 22:48:33 +0300 Subject: [PATCH] Use iterators --- src/bin/flat.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/src/bin/flat.rs b/src/bin/flat.rs index d2656b3..d42ded8 100644 --- a/src/bin/flat.rs +++ b/src/bin/flat.rs @@ -16,22 +16,27 @@ pub fn main() { gc.canvas_height(1000.0); gc.new_path(); + gc.circle(0.0, 0.0, space.coil_r + space.coil_w + space.coil_m); gc.circle(0.0, 0.0, space.coil_r + space.coil_w); gc.circle(0.0, 0.0, space.coil_r - space.coil_w); - gc.line_width(3.0); - gc.stroke_color(Color::Rgba(0.8, 0.8, 0.8, 1.0)); - gc.stroke(); + gc.circle(0.0, 0.0, space.coil_r - space.coil_w - space.coil_m); + gc.winding_rule(WindingRule::EvenOdd); + gc.fill_color(Color::Rgba(0.8, 0.8, 0.8, 1.0)); + gc.fill(); gc.line_width(1.0); gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 1.0)); for y in itertools_num::linspace(-1.0, 1.0, 101) { let base = vec2(-500.0, 0.0); let dir = vec2(1.0, y); - let path = trace(&space, base, dir, 1000.0, 1.0); + let path = trace_iter(&space, base, dir, 1.0); gc.new_path(); gc.move_to(base.x, base.y); - for pt in path { + for pt in path.take(10000) { gc.line_to(pt.x, pt.y); + if any(greaterThan(abs(pt), Vec2::from_s(1000.0))) { + break + } } gc.stroke(); } @@ -89,6 +94,24 @@ trait Metric { } } +struct TraceIter<'a, M: Metric> { + space: &'a M, + p: Vec2, + v: Vec2, + dt: f32, +} + +impl<'a, M: Metric> Iterator for TraceIter<'a, M> { + type Item = Vec2; + + fn next(&mut self) -> Option { + let a: Vec2 = -convolute(krist(self.space, self.p), self.v); + self.v = self.v + a * self.dt; + self.p = self.p + self.v * self.dt; + Some(self.p) + } +} + fn trace(space: &impl Metric, base: Vec2, dir: Vec2, distance: f32, dt: f32) -> Vec { let steps = floor(distance / dt) as usize; let mut result = Vec::with_capacity(steps); @@ -103,6 +126,32 @@ fn trace(space: &impl Metric, base: Vec2, dir: Vec2, distance: f32, dt: f32) -> result } +fn trace_iter(space: &M, base: Vec2, dir: Vec2, dt: f32) -> TraceIter { + TraceIter{ + space: space, + p: base, + v: normalize(dir), + dt: dt, + } +} + +#[test] +fn t_iter() { + let space = Coil { + coil_scale: 2.0, + coil_r: 300.0, + coil_w: 50.0, + coil_m: 10.0, + }; + let base = vec2(-500.0, 0.0); + let dir = vec2(1.0, 0.3); + let dt = 1.0; + let steps = 1000; + let a = trace(&space, base, dir, dt * (steps as f32), dt); + let b: Vec = trace_iter(&space, base, dir, dt).take(steps).collect(); + assert_eq!(a, b); +} + fn krist(space: &impl Metric, pos: Vec2) -> Tens2 { // Γ^i_k_l = .5 * g^i^m * (g_m_k,l + g_m_l,k - g_k_l,m) let g = inverse(&space.metric(pos)); // с верхними индексами