This commit is contained in:
numzero 2025-09-06 01:43:52 +03:00
commit d497f3e96d
4 changed files with 2619 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

2404
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "gears"
version = "0.1.0"
edition = "2024"
[dependencies]
flo_draw = "0.3.1"
glam = "0.30.5"

206
src/main.rs Normal file
View File

@ -0,0 +1,206 @@
use std::f32::consts::PI;
use flo_draw::{
canvas::{Color::Rgba, GraphicsContext, GraphicsPrimitives},
create_drawing_window, with_2d_graphics,
};
use glam::{Mat2, Vec2, vec2};
const fn rad(deg: f32) -> f32 {
deg * (PI / 180.0)
}
fn involute(t: f32) -> Vec2 {
let v = Vec2::from_angle(t);
v - t * v.perp()
}
fn involute_radius_to_t(r: f32) -> f32 {
(r * r - 1.).sqrt()
}
fn gear_shape(n: usize) -> Vec<Vec2> {
const A: f32 = rad(28.);
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;
let mut ret = Vec::with_capacity(2 * n * Q);
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);
}
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);
}
}
ret
}
fn main() {
let g24 = gear_shape(24);
let g36 = gear_shape(36);
with_2d_graphics(|| {
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.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);
}
}
gc.close_path();
gc.stroke_color(Rgba(0.1, 0.8, 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;
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);
}
}
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();
});
});
}