From 39e18d7eefe81c959d5b4856b3b5a12a01e474c8 Mon Sep 17 00:00:00 2001 From: Mihail Mitrovanov Date: Fri, 23 May 2025 14:12:42 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BF=D1=8B=D1=82=D0=BA=D0=B0=20=D0=B2=20=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 137 ----------------- Cargo.toml | 1 - src/main.rs | 413 +++++++++++++++++++++++++++++++++++----------------- 3 files changed, 282 insertions(+), 269 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 618cd84..9a6c95b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,6 @@ version = 4 name = "PointInteraction" version = "0.1.0" dependencies = [ - "rand", "sdl3", ] @@ -16,24 +15,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -46,69 +27,6 @@ version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[package]] -name = "rand" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" -dependencies = [ - "rand_chacha", - "rand_core", - "zerocopy", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom", -] - [[package]] name = "sdl3" version = "0.14.22" @@ -126,58 +44,3 @@ name = "sdl3-sys" version = "0.4.7+SDL3-3.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d16a8a3623a4cb39a3661c81d9d4c5fd77ada27fc056e320b3651bf7bde1b1" - -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml index 8c2d871..b33211e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,3 @@ edition = "2024" [dependencies] sdl3 = "0.14.19" -rand = "0.9.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index db8f6d6..bf8f652 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,23 @@ use sdl3::event::Event; use sdl3::keyboard::Keycode; use sdl3::pixels::Color; -use sdl3::rect::Point; use sdl3::render::{FPoint, WindowCanvas}; use std::f32::consts::PI; -use std::ops; -use std::ops::{AddAssign, Mul, Rem, Sub}; +use std::ops::{Mul, Neg, Rem, Sub}; +use std::sync::mpsc; +use std::thread; +use std::thread::JoinHandle; use std::time::{Duration, Instant}; -const SIZE: u32 = 400; -const SIZE_F: f32 = 400.0; - +const SIZE: u32 = 500; +const SIZE_F: f32 = 500.0; +const ARC: f32 = SIZE_F * 2.0 * PI; pub fn main() { - let mut point_a = Point2D::new(-5.0, 0.0); - let mut point_b = Point2D::new(5.0, 0.0); + let mut point_a = Vector2::new(0.0, 0.0); + let mut point_b = Vector2::new(SIZE_F, 0.0); let line = Line2D::new(&mut point_a, &mut point_b); - + let mut selection = 1; let sdl_context = sdl3::init().unwrap(); @@ -42,9 +43,13 @@ pub fn main() { let mut event_pump = sdl_context.event_pump().unwrap(); let time = Instant::now(); let mut count = 0; + + let mut ready_points: Vec<(FPoint, f32)> = vec![]; + 'running: loop { canvas.set_draw_color(Color::RGB(0, 0, 0)); canvas.clear(); + for event in event_pump.poll_iter() { match event { Event::Quit { .. } @@ -64,36 +69,62 @@ pub fn main() { } => { selection = 2; } + Event::KeyDown { + keycode: Some(Keycode::X), + .. + } => { + let a_clone = point_a.clone(); + let b_clone = point_b.clone(); + let timer = Instant::now(); + ready_points.clear(); + for x in (-(SIZE as i32))..(SIZE as i32) { + for y in (-(SIZE as i32))..(SIZE as i32) { + let pt = Vector2::new(x as f32, y as f32); + if pt.eq(&a_clone) || pt.eq(&b_clone) { + continue; + } + let dist_a = pt.distance(&(a_clone)); + let dist_b = pt.distance(&b_clone); + // let sum = (1.0 / ((dist_a) / SIZE_F).powi(2)).min(100.0_f32) + // + (1.0 / ((dist_b) / SIZE_F).powi(2)).min(100.0_f32); + let ratio = if dist_a > dist_b { 0.2 } else { 0.7 }; + + ready_points.push((pt.to_cartesian().to_sdl(), ratio)); + } + } + println!("end"); + println!("{}", timer.elapsed().as_millis()); + } Event::KeyDown { keycode: Some(Keycode::D), .. } => { println!("Debug") } - Event::MouseMotion { .. } => { - if let Event::MouseMotion { - timestamp: _, - window_id: _, - which: _, - mousestate: _, - x, - y, - xrel, - yrel, - } = event - { - let mut cursor: &mut Point2D; - if selection == 1 { - cursor = line.a; - } else { - cursor = line.b; - } - - cursor += (xrel, yrel); - cursor.optimize(); - cursor = &mut cursor.abs(); - } - } + // Event::MouseMotion { .. } => { + // if let Event::MouseMotion { + // timestamp: _, + // window_id: _, + // which: _, + // mousestate: _, + // x, + // y, + // xrel, + // yrel, + // } = event + // { + // let mut cursor: &mut Point2D; + // if selection == 1 { + // cursor = line.a; + // } else { + // cursor = line.b; + // } + // + // cursor += (xrel, yrel); + // cursor.optimize(); + // cursor = &mut cursor.abs(); + // } + // } _ => {} } } @@ -105,56 +136,106 @@ pub fn main() { count += 1; - line.draw(&mut canvas, 1.0); + canvas.set_draw_color(Color::WHITE); + point_a.draw(&mut canvas); + point_b.draw(&mut canvas); + for ready_point in &ready_points { + canvas.set_draw_color(Color::from(( + (u8::MAX as f32 * ready_point.1) as u8, + u8::MAX, + u8::MAX, + ))); + canvas.draw_point(ready_point.0).unwrap() + } canvas.present(); if count == 10000 { println!("Time for 10000 is {} ms", time.elapsed().as_millis()); } - std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 600)); + thread::sleep(Duration::new(0, 1_000_000_000u32 / 600)); } } #[derive(Debug)] -struct Point2D { +struct Vector2 { x: f32, y: f32, - spin: bool, + orientation: Vector3, } - -impl Point2D { - pub fn new(x: f32, y: f32) -> Point2D { - Point2D { x, y, spin: false } +impl Vector2 { + pub fn new(x: f32, y: f32) -> Vector2 { + Vector2 { + x, + y, + orientation: Vector3::vector_z(), + } } - pub fn new_with_spin(x: f32, y: f32, spin: bool) -> Point2D { - Point2D { x, y, spin } - } - pub fn distance_abs(&self, point: &Point2D) -> f32 { - let a_abs = self.optimized().abs(); - let b_abs = point.optimized().abs(); - (a_abs.x - b_abs.x).hypot(a_abs.y - b_abs.y) + pub fn new_with_spin(x: f32, y: f32, spin: Vector3) -> Vector2 { + Vector2 { + x, + y, + orientation: spin, + } } - pub fn distance_sq(&self, point: &Point2D) -> f32 { - (self.x - point.x).powi(2) + (self.y - point.y).powi(2) + pub fn to_3d_raw(&self) -> Vector3 { + Vector3::new(self.x, self.y, 0.0) } - pub fn alt_distance(&self, point: &Point2D) -> f32 { - 2.0 * SIZE_F - self.distance_abs(point) + pub fn to_3d_placed(&self) -> Vector3 { + let v_angle = ((self.y / SIZE_F) * PI / 2.0); + let z = v_angle.sin() * SIZE_F; + let xy_scale = v_angle.cos(); + let angle = (self.x / SIZE_F) * PI / 2.0; + let x = angle.cos() * SIZE_F * xy_scale; + let y = angle.sin() * SIZE_F * xy_scale; + + Vector3::new(x, y, z) } - pub fn to_cartesian(&self) -> Point2D { + pub fn distance(&self, point: &Vector2) -> f32 { + let self_3d = self.to_3d_placed(); + let other_3d = point.to_3d_placed(); + let dot = Vector3::dot(self_3d.normalized(), other_3d.normalized()); + let angle = dot.acos(); + angle / PI * ARC + } + + pub fn alt_distance(&self, point: &Vector2) -> f32 { + ARC - self.distance(point) + } + + pub fn rotate_to(&mut self, point: Vector2) { + let self_3d = self.to_3d_placed(); + let other_3d = point.to_3d_placed(); + let mut normal = other_3d * self_3d; + normal.normalize(); + self.orientation = -normal; + } + + pub fn move_to(&mut self, distance: f32) { + let angle = distance / ARC * 2.0 * PI; + let rotation = Quaternion::from_axis_angle(self.orientation.clone(), angle); + let self_3d = self.to_3d_placed(); + let rotated = self_3d.rotated(rotation); + let projected = rotated.to_2d_placed(); + + self.x = projected.x; + self.y = projected.y; + } + + pub fn to_cartesian(&self) -> Vector2 { let angle = (self.x / SIZE_F) * PI; let cos = angle.cos(); let sin = angle.sin(); let scale = (SIZE_F + self.y) / 2.0; - Point2D::new(cos * scale, sin * scale) + Vector2::new(cos * scale, sin * scale) } - pub fn to_super_space(&self) -> Point2D { + pub fn to_super_space(&self) -> Vector2 { let len = self.x.hypot(self.y); let y = len * 2.0 - SIZE_F; @@ -168,15 +249,15 @@ impl Point2D { x = -x; } - Point2D::new(x, y) + Vector2::new(x, y) } pub fn to_sdl(&self) -> FPoint { FPoint::new(self.x + SIZE_F, self.y + SIZE_F) } - pub fn from_sdl(x: f32, y: f32) -> Point2D { - Point2D::new(x - SIZE_F, y - SIZE_F) + pub fn from_sdl(x: f32, y: f32) -> Vector2 { + Vector2::new(x - SIZE_F, y - SIZE_F) } pub fn draw(&self, canvas: &mut WindowCanvas) { @@ -197,9 +278,9 @@ impl Point2D { remainder } - pub fn normalized(&self) -> Point2D { + pub fn normalized(&self) -> Vector2 { let len = self.x.hypot(self.y); - Point2D::new_with_spin(self.x / len, self.y / len, self.spin) + Vector2::new_with_spin(self.x / len, self.y / len, self.orientation.clone()) } pub fn optimize(&mut self) { @@ -211,14 +292,12 @@ impl Point2D { let side = self.y.signum(); self.y += -side * 2.0 * (self.y.abs() - SIZE_F); self.x = self.x + SIZE_F; - self.spin = !self.spin; } } - pub fn optimized(&self) -> Point2D { + pub fn optimized(&self) -> Vector2 { let mut x: f32 = self.x; let mut y: f32 = self.y; - let mut spin: bool = self.spin; if self.x.abs() > SIZE_F { x = Self::lapped(self.x); } @@ -227,10 +306,9 @@ impl Point2D { let side = self.y.signum(); y += -side * 2.0 * (self.y.abs() - SIZE_F); x = self.x + SIZE_F; - spin = !spin; } - Point2D::new_with_spin(x, y, spin) + Vector2::new_with_spin(x, y, self.orientation.clone()) } pub fn draw_point(canvas: &mut WindowCanvas, points: &Vec) { @@ -238,15 +316,11 @@ impl Point2D { canvas.draw_points(&points[..]).unwrap(); } - pub fn eq(&self, point: &Point2D) -> bool { + pub fn eq(&self, point: &Vector2) -> bool { (self.x.abs() - point.x.abs()).abs() < 0.1 && (self.y.abs() - point.y.abs()).abs() < 0.1 } - pub fn eq_spin(&self, point: &Point2D) -> bool { - self.eq(point) && self.spin == point.spin - } - - pub fn abs(&self) -> Point2D { + pub fn abs(&self) -> Vector2 { let x: f32; let y: f32; if self.x < 0.0 { @@ -260,11 +334,11 @@ impl Point2D { y = self.y; } - Point2D::new(x, y) + Vector2::new(x, y) } - pub fn relative(&self) -> Point2D { - Point2D::new(Self::lapped(self.x), Self::lapped(self.y)) + pub fn relative(&self) -> Vector2 { + Vector2::new(Self::lapped(self.x), Self::lapped(self.y)) } pub fn add(&mut self, x: f32, y: f32) { @@ -273,62 +347,151 @@ impl Point2D { } } -impl ops::AddAssign for Point2D { - fn add_assign(&mut self, rhs: Self) { - self.x += rhs.x * bool_to_int(self.spin) as f32; - self.y += rhs.y * bool_to_int(self.spin) as f32; +#[derive(Debug)] +struct Vector3 { + x: f32, + y: f32, + z: f32, +} + +impl Vector3 { + pub fn new(x: f32, y: f32, z: f32) -> Vector3 { + Vector3 { x, y, z } + } + + pub fn normalize(&mut self) { + let len = self.x.hypot(self.y).hypot(self.z); + self.x /= len; + self.y /= len; + self.z /= len; + } + + pub fn normalized(&self) -> Vector3 { + let len = self.x.hypot(self.y).hypot(self.z); + Vector3::new(self.x / len, self.y / len, self.z / len) + } + + pub fn vector_x() -> Vector3 { + Vector3::new(1.0, 0.0, 0.0) + } + + pub fn vector_y() -> Vector3 { + Vector3::new(0.0, 1.0, 0.0) + } + + pub fn vector_z() -> Vector3 { + Vector3::new(0.0, 0.0, 1.0) + } + + pub fn dot(a: Vector3, b: Vector3) -> f32 { + a.x * b.x + a.y * b.y + a.z * b.z + } + + pub fn rotated(&self, rotation: Quaternion) -> Vector3 { + let x2 = rotation.x + rotation.x; + let y2 = rotation.y + rotation.y; + let z2 = rotation.z + rotation.z; + + let wx2 = rotation.w * x2; + let wy2 = rotation.w * y2; + let wz2 = rotation.w * z2; + let xx2 = rotation.x * x2; + let xy2 = rotation.x * y2; + let xz2 = rotation.x * z2; + let yy2 = rotation.y * y2; + let yz2 = rotation.y * z2; + let zz2 = rotation.z * z2; + + Vector3::new( + self.x * (1.0 - yy2 - zz2) + self.y * (xy2 - wz2) + self.z * (xz2 + wy2), + self.x * (xy2 + wz2) + self.y * (1.0 - xx2 - zz2) + self.z * (yz2 - wx2), + self.x * (xz2 - wy2) + self.y * (yz2 + wx2) + self.z * (1.0 - xx2 - yy2), + ) + } + + pub fn to_2d_placed(self) -> Vector2 { + let normalized = self.normalized(); + let y = normalized.z.sin(); + let x = normalized.y.atan2(normalized.x) / PI; + Vector2::new(x * SIZE_F, y * SIZE_F) } } -impl AddAssign<(f32, f32)> for Point2D { - fn add_assign(&mut self, rhs: (f32, f32)) { - self.x += rhs.0 * bool_to_int(self.spin) as f32; - self.y += rhs.1 * bool_to_int(self.spin) as f32; +impl Neg for Vector3 { + type Output = Vector3; + fn neg(self) -> Vector3 { + Vector3::new(-self.x, -self.y, -self.z) } } -impl AddAssign<(f32, f32)> for &mut Point2D { - fn add_assign(&mut self, rhs: (f32, f32)) { - self.x += rhs.0 * bool_to_int(self.spin) as f32; - self.y += rhs.1 * bool_to_int(self.spin) as f32; - } -} - -fn bool_to_int(flag: bool) -> i32 { - if !flag { 1 } else { -1 } -} - -impl Clone for Point2D { +impl Clone for Vector3 { fn clone(&self) -> Self { - Point2D::new_with_spin(self.x, self.y, self.spin) + Vector3::new(self.x, self.y, self.z) + } +} +impl Mul for Vector3 { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + Vector3::new( + self.y * rhs.z + self.z * rhs.y, + self.x * rhs.z + self.z * rhs.x, + self.x * rhs.y + self.y * rhs.x, + ) + } +} + +struct Quaternion { + x: f32, + y: f32, + z: f32, + w: f32, +} + +impl Quaternion { + pub fn new(x: f32, y: f32, z: f32, w: f32) -> Quaternion { + Quaternion { x, y, z, w } + } + + pub fn from_axis_angle(axis: Vector3, angle: f32) -> Quaternion { + let half_angle = angle / 2.0; + let s = half_angle.sin(); + let c = half_angle.cos(); + Quaternion::new(axis.x * s, axis.y * s, axis.z * s, c) + } +} + +impl Clone for Vector2 { + fn clone(&self) -> Self { + Vector2::new_with_spin(self.x, self.y, self.orientation.clone()) } } struct Line2D<'a> { - a: &'a mut Point2D, - b: &'a mut Point2D, + a: &'a mut Vector2, + b: &'a mut Vector2, ending: Color, fill: Color, segments: u32, } -impl Sub for Point2D { +impl Sub for Vector2 { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { - Point2D::new_with_spin(self.x - rhs.x, self.y - rhs.y, self.spin) + Vector2::new_with_spin(self.x - rhs.x, self.y - rhs.y, self.orientation) } } -impl Mul for Point2D { - type Output = Point2D; +impl Mul for Vector2 { + type Output = Vector2; fn mul(self, rhs: f32) -> Self::Output { - Point2D::new_with_spin(self.x * rhs, self.y * rhs, self.spin) + Vector2::new_with_spin(self.x * rhs, self.y * rhs, self.orientation) } } impl<'a> Line2D<'a> { - pub fn new(a: &'a mut Point2D, b: &'a mut Point2D) -> Self { + pub fn new(a: &'a mut Vector2, b: &'a mut Vector2) -> Self { Self { a, b, @@ -338,43 +501,31 @@ impl<'a> Line2D<'a> { } } - pub fn draw<'b>(&'a self, canvas: &mut WindowCanvas, pow: f32) { + pub fn draw_two_side<'b>(&'a self, canvas: &mut WindowCanvas) { let distance: f32; - if pow < 0.0 { - distance = self.a.alt_distance(self.b); - } else { - distance = self.b.distance_abs(self.a); - } + distance = self.b.distance(self.a); + let alt_distance = distance; + println!("distance: {}", distance); + let a_abs = self.a.optimized(); + let b_abs = self.b.optimized(); + let main_vector = (b_abs - a_abs).normalized(); + let vec_positive = main_vector.clone() * (distance / self.segments as f32); + let vec_negative = main_vector * (-alt_distance / self.segments as f32); - let a_abs = self.a.abs(); - let b_abs = self.b.abs(); - let vec = (b_abs - a_abs).normalized() * (distance / self.segments as f32) * pow; let mut cursor = self.a.clone(); + let mut cursor_negative = cursor.clone(); canvas.set_draw_color(self.fill); - for i in 1..self.segments { - cursor.add(vec.x, vec.y); + + for _i in 1..self.segments { + cursor.add(vec_positive.x, vec_positive.y); cursor.optimize(); cursor.draw(canvas); + cursor_negative.add(vec_negative.x, -vec_negative.y); + cursor_negative.optimize(); + cursor_negative.draw(canvas); } canvas.set_draw_color(self.ending); self.a.draw(canvas); self.b.draw(canvas); } - - pub fn draw_alt<'b>(&'a self, canvas: &mut WindowCanvas) { - let mut local_a = self.a.clone().abs(); - let mut local_b = self.b.clone().abs(); - - let x_step = (local_a.x - local_b.x) / self.segments as f32; - let y_step = (local_a.y - local_b.y) / self.segments as f32; - canvas.set_draw_color(self.fill); - for i in 1..self.segments { - let pt = Point2D::new(local_b.x + x_step * i as f32, local_b.y + y_step * i as f32); - pt.draw(canvas); - } - - canvas.set_draw_color(self.ending); - local_b.draw(canvas); - local_a.draw(canvas); - } }