From 9d4c61d7eced576e5781b0a70ccada632458d341 Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 6 Sep 2025 03:10:35 +0300 Subject: [PATCH] works? --- src/main.rs | 237 ++++++++++++++++++---------------------------------- 1 file changed, 82 insertions(+), 155 deletions(-) diff --git a/src/main.rs b/src/main.rs index af9fa33..b50b009 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use flo_draw::{ canvas::{Color::Rgba, GraphicsContext, GraphicsPrimitives}, create_drawing_window, with_2d_graphics, }; -use glam::{Mat2, Vec2, vec2}; +use glam::{FloatExt, Mat2, Vec2, vec2}; const fn rad(deg: f32) -> f32 { deg * (PI / 180.0) @@ -19,187 +19,114 @@ fn involute_radius_to_t(r: f32) -> f32 { (r * r - 1.).sqrt() } -fn gear_shape(n: usize) -> Vec { - const A: f32 = rad(28.); +fn gear_shape_ex(n: usize, inner: f32, outer: f32) -> Vec { const Q: usize = 6; - let b = A.cos(); - let offset = involute(involute_radius_to_t(1. / b)).to_angle(); - let stop_angle = involute_radius_to_t((1.0 + 2.0 / n as f32) / b); - let halfangle = PI / n as f32; - let ma = Mat2::from_angle(offset - halfangle); - let mb = Mat2::from_diagonal(vec2(1., -1.)) * ma; + const A: f32 = rad(28.); + let base = A.cos(); - let mut ret = Vec::with_capacity(2 * n * Q); + let base_to_pitch_angle = involute(involute_radius_to_t(1. / base)).to_angle(); + + let tooth_angle = 2.0 * PI / n as f32; + println!("{n}: {base}, {inner}, {outer}"); + let t1 = involute_radius_to_t((inner / base).max(1.)); + let t2 = involute_radius_to_t(outer / base); + println!("{t1}-{t2}"); + println!("{base_to_pitch_angle}, {}", tooth_angle / 4.); + + let mut side = [Vec2::ZERO; Q + 2]; + side[0] = vec2(inner, 0.0); + for k in 0..=Q { + let t01 = k as f32 / Q as f32; + let t = f32::lerp(t1, t2, t01); + side[k + 1] = base * involute(t); + } + + let m = Mat2::from_angle(-(tooth_angle / 4.0 + base_to_pitch_angle)); + for p in &mut side { + *p = m * *p; + } + if base_to_pitch_angle > tooth_angle / 4.0 { + side[0] = Mat2::from_angle(-(tooth_angle / 2.0)) * vec2(inner, 0.0); + } + + let mut ret = Vec::with_capacity(2 * n * (Q + 2)); for i in 0..n { - let m = Mat2::from_angle(i as f32 * 2. * halfangle); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let p = b * m * ma * involute(stop_angle * t); - ret.push(p); + let m = Mat2::from_angle(i as f32 * tooth_angle); + for p in side { + ret.push(m * p); } - for k in 0..=Q { - let t = 1. - k as f32 / Q as f32; - let p = b * m * mb * involute(stop_angle * t); - ret.push(p); + for p in side.iter().rev() { + ret.push(m * vec2(p.x, -p.y)); } } ret } +fn gear_shape_std(n: usize, low: f32, high: f32) -> Vec { + let unit = 1.0 / n as f32; + return gear_shape_ex(n, 1.0 - low * unit, 1.0 + high * unit); +} + +fn gear_shape(n: usize) -> Vec { + return gear_shape_std(n, 2.2, 2.0); +} + +fn gear_shape_outer(n: usize) -> Vec { + return gear_shape_std(n, 2.0, 2.2); +} + fn main() { - let g24 = gear_shape(24); - let g36 = gear_shape(36); + const R_SCALE: f32 = 0.5; + const N_TEETH_SUN: usize = 36; + const N_TEETH_SAT: usize = 24; + const N_TEETH_SKY: usize = N_TEETH_SUN + 2 * N_TEETH_SAT; + const N_SAT: usize = 3; + const R_SUN: f32 = R_SCALE * N_TEETH_SUN as f32; + const R_SAT: f32 = R_SCALE * N_TEETH_SAT as f32; + const OFF_SAT: f32 = R_SUN + R_SAT; + const R_SKY: f32 = R_SCALE * N_TEETH_SKY as f32; with_2d_graphics(|| { + let sun = gear_shape(N_TEETH_SUN); + let sat = gear_shape(N_TEETH_SAT); + let crown = gear_shape_outer(N_TEETH_SKY); + let canvas = create_drawing_window("Canvas window"); canvas.draw(|gc| { gc.clear_canvas(Rgba(0.1, 0.1, 0.1, 1.0)); - gc.canvas_height(50.0); - gc.line_width(0.5); - - const N1: usize = 20; - const N2: usize = 50; - const R1: f32 = 20.; - const R2: f32 = 50.; - const A: f32 = rad(28.); - - let b = A.cos(); - let b1 = b * R1; - let b2 = b * R2; - let offset = involute_radius_to_t(1. / b); - let offset = involute(offset).to_angle(); + gc.canvas_height(100.0); + gc.line_width(0.25); gc.new_path(); - gc.stroke_color(Rgba(0.3, 0.3, 0.3, 1.0)); - gc.circle(-R1, 0., R1); - gc.circle(R2, 0., R2); - gc.circle(-R2, 0., R2); - gc.stroke(); - - gc.new_path(); - gc.stroke_color(Rgba(0.1, 0.1, 0.8, 1.0)); - gc.circle(-R1, 0., b1); - gc.circle(R2, 0., b2); - gc.circle(-R2, 0., b2); - gc.stroke(); - - // let pitch_radius = R1; - // let base_radius = b1; - // let number_of_teeth = N1; - // let addendum = 2.0 * pitch_radius / number_of_teeth as f32; - // let clearance = 0.0; - // let dedendum = addendum + clearance; - - const Q: usize = 12; - - let stop_angle = involute_radius_to_t((1.0 + 2.0 / N1 as f32) / b); - let halfangle = PI / N1 as f32; - let ma = Mat2::from_angle(offset - halfangle); - let mb = Mat2::from_diagonal(vec2(1., -1.)) * ma; - gc.new_path(); - for i in 0..N1 { - let m = Mat2::from_angle(i as f32 / N1 as f32 * 2. * PI); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let p = b1 * m * ma * involute(stop_angle * t) - vec2(R1, 0.); - gc.line_to(p.x, p.y); - } - for k in 0..=Q { - let t = 1. - k as f32 / Q as f32; - let p = b1 * m * mb * involute(stop_angle * t) - vec2(R1, 0.); - gc.line_to(p.x, p.y); - } + for pt in sun { + let pt = R_SUN * pt; + gc.line_to(pt.x, pt.y); } gc.close_path(); - gc.stroke_color(Rgba(0.1, 0.8, 0.1, 1.0)); + gc.stroke_color(Rgba(0.8, 0.7, 0.1, 1.0)); gc.stroke(); - let stop_angle = involute_radius_to_t((1.0 + 2.0 / N2 as f32) / b); - let halfangle = PI / N2 as f32; - let ma = Mat2::from_angle(offset - halfangle); - let mb = Mat2::from_diagonal(vec2(1., -1.)) * ma; + for k in 0..N_SAT { + let m = Mat2::from_angle(k as f32 / N_SAT as f32 * 2. * PI); + gc.new_path(); + for pt in &sat { + let pt = m * vec2(OFF_SAT, 0.) + R_SAT * pt; + gc.line_to(pt.x, pt.y); + } + gc.close_path(); + gc.stroke_color(Rgba(0.1, 0.8, 0.1, 1.0)); + gc.stroke(); + } + gc.new_path(); - for i in 0..N2 { - let m = Mat2::from_angle((i as f32 - 0.5) / N2 as f32 * 2. * PI); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let p = b2 * m * ma * involute(stop_angle * t) + vec2(R2, 0.); - gc.line_to(p.x, p.y); - } - for k in 0..=Q { - let t = 1. - k as f32 / Q as f32; - let p = b2 * m * mb * involute(stop_angle * t) + vec2(R2, 0.); - gc.line_to(p.x, p.y); - } + for pt in crown { + let pt = R_SKY * pt; + gc.line_to(pt.x, pt.y); } gc.close_path(); - gc.stroke_color(Rgba(0.1, 0.8, 0.1, 1.0)); - gc.stroke(); - - gc.new_path(); gc.stroke_color(Rgba(0.1, 0.4, 0.8, 1.0)); - gc.move_to(-5., 0.); - gc.line_to(5., 0.); - gc.stroke(); - - return; - - let m = Mat2::IDENTITY; // Mat2::from_angle(-offset); - - gc.new_path(); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let p = vec2(R2, 0.) - b2 * m * involute(t); - gc.line_to(p.x, p.y); - } - gc.stroke_color(Rgba(0.1, 0.8, 0.1, 1.0)); - gc.stroke(); - - gc.new_path(); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let m1 = Mat2::from_angle(A - t); - let m2 = Mat2::from_angle((A - t) * R1 / R2); - let p = b1 * m1 * m * involute(t) - vec2(R1, 0.); - let p = m2 * (p - vec2(R2, 0.)) + vec2(R2, 0.); - gc.line_to(p.x, p.y); - } - gc.stroke_color(Rgba(0.8, 0.8, 0.1, 1.0)); - gc.stroke(); - - gc.new_path(); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let m1 = Mat2::from_angle(A - t); - let m2 = Mat2::from_angle((t - A) * R1 / R2); - let p = b1 * m1 * m * involute(t) - vec2(R1, 0.); - let p = m2 * (p + vec2(R2, 0.)) - vec2(R2, 0.); - gc.line_to(p.x, p.y); - } - gc.stroke_color(Rgba(0.8, 0.1, 0.1, 1.0)); - gc.stroke(); - - gc.new_path(); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let m1 = Mat2::from_angle(A - t); - let m2 = Mat2::from_angle(t - A); - let p = b2 * m1 * m * involute(t) - vec2(R2, 0.); - let p = m2 * (p + vec2(R2, 0.)) - vec2(R2, 0.); - gc.line_to(p.x, p.y); - } - gc.stroke_color(Rgba(0.8, 0.4, 0.1, 1.0)); - gc.stroke(); - - gc.new_path(); - for k in 0..=Q { - let t = k as f32 / Q as f32; - let p = b2 * m * involute(t) - vec2(R2, 0.); - gc.line_to(p.x, p.y); - } - gc.stroke_color(Rgba(0.1, 0.8, 0.8, 0.5)); gc.stroke(); }); });