checkpoint gear generation work

This commit is contained in:
Stewart Allen 2024-07-18 20:13:50 -06:00
commit 156fe593ac
6 changed files with 99 additions and 27 deletions

View file

@ -109,6 +109,25 @@ function sqr(v) {
return v * v return v * v
} }
// radians rotatition around origin
function rotate(x,y,radians) {
return [
x * Math.cos(radians) - y * Math.sin(radians),
y * Math.cos(radians) + x * Math.sin(radians)
];
}
const deg2rad = (Math.PI / 180);
const rad2deg = (180 / Math.PI);
function toRadians(degrees) {
return degrees * deg2rad;
}
function toDegrees(radians) {
return radians * rad2deg;
}
/** /**
* return distance between two points * return distance between two points
*/ */
@ -576,6 +595,7 @@ base.util = {
pwait, pwait,
ptimer, ptimer,
flatten, flatten,
rotate,
dist2D, dist2D,
distSq, distSq,
distSqv2, distSqv2,
@ -587,6 +607,8 @@ base.util = {
offsetPrecision, offsetPrecision,
circleCenter, circleCenter,
numOrDefault, numOrDefault,
toRadians,
toDegrees,
thetaDiff, thetaDiff,
intersect, intersect,
inRange, inRange,

View file

@ -551,6 +551,13 @@ class Point {
this.z += delta.z; this.z += delta.z;
return this; return this;
} }
// radians rotatition in XY around origin
rotate(angle) {
const { x, y } = this;
this.x = x * Math.cos(angle) - y * Math.sin(angle);
this.y = y * Math.cos(angle) + x * Math.sin(angle);
}
} }
function dot(u, v) { function dot(u, v) {

View file

@ -1094,6 +1094,7 @@ class Polygon {
} else if (this.isClockwise() !== poly.isClockwise()) { } else if (this.isClockwise() !== poly.isClockwise()) {
this.reverse(); this.reverse();
} }
return this;
} }
/** /**
@ -1105,6 +1106,7 @@ class Polygon {
} else if (this.isClockwise() === poly.isClockwise()) { } else if (this.isClockwise() === poly.isClockwise()) {
this.reverse(); this.reverse();
} }
return this;
} }
/** /**

View file

@ -321,12 +321,14 @@ let add = {
}, },
gear(opt = {}) { gear(opt = {}) {
function gengear(teeth, module, angle) { function gengear(teeth, module, angle, twist, shaft) {
api.modal.hide(); api.modal.hide();
worker.model_gen_gear({ worker.model_gen_gear({
teeth: parseInt(teeth), teeth: parseInt(teeth),
module: parseFloat(module), module: parseFloat(module),
angle: parseFloat(angle) angle: parseFloat(angle),
twist: parseFloat(twist),
shaft: parseFloat(shaft),
}).then(gear => { }).then(gear => {
const nmdl = new mesh.model({ file: "gear", mesh: gear.toFloat32() }); const nmdl = new mesh.model({ file: "gear", mesh: gear.toFloat32() });
const ngrp = group.new([ nmdl ]); const ngrp = group.new([ nmdl ]);
@ -342,11 +344,17 @@ let add = {
h.input({ value: opt.module || 3, size: 5, id: "gmodule" }), h.input({ value: opt.module || 3, size: 5, id: "gmodule" }),
h.label('pressure angle'), h.label('pressure angle'),
h.input({ value: opt.angle || 20, size: 5, id: "gangle" }), h.input({ value: opt.angle || 20, size: 5, id: "gangle" }),
h.label('twist angle'),
h.input({ value: opt.twist || 0, size: 5, id: "gtwist" }),
h.label('shaft diameter'),
h.input({ value: opt.shaft || 10, size: 5, id: "gshaft" }),
h.button({ _: "create", onclick() { h.button({ _: "create", onclick() {
gengear( gengear(
api.modal.bound.gteeth.value, api.modal.bound.gteeth.value,
api.modal.bound.gmodule.value, api.modal.bound.gmodule.value,
api.modal.bound.gangle.value, api.modal.bound.gangle.value,
api.modal.bound.gtwist.value,
api.modal.bound.gshaft.value,
) )
} }) } })
]) ] ]) ]

View file

@ -738,6 +738,8 @@ mesh.tool = class MeshTool {
return out; return out;
} }
// returns points array for a polygon
// extrusion and twist is handled in work.js
generateGear(numTeeth, module, pressureAngle) { generateGear(numTeeth, module, pressureAngle) {
// Adapted from: Public Domain Parametric Involute Spur Gear by Leemon Baird, 2011, Leemon@Leemon.com http://www.thingiverse.com/thing:5505 // Adapted from: Public Domain Parametric Involute Spur Gear by Leemon Baird, 2011, Leemon@Leemon.com http://www.thingiverse.com/thing:5505
// see also http://grabcad.com/questions/tutorial-how-to-model-involute-gears-in-solidworks-and-show-design-intent // see also http://grabcad.com/questions/tutorial-how-to-model-involute-gears-in-solidworks-and-show-design-intent
@ -759,6 +761,15 @@ mesh.tool = class MeshTool {
// radius a fraction f up the curved side of the tooth // radius a fraction f up the curved side of the tooth
function q7(f, r, b, r2, t, s) { return q6(b, s, t, (1 - f) * Math.max(b, r) + f * r2); } function q7(f, r, b, r2, t, s) { return q6(b, s, t, (1 - f) * Math.max(b, r) + f * r2); }
function qf(steps, r, b, r2, t, s) {
let res = [];
let step = 1/steps;
for (let f=0; f <= 1; f += step) {
res.push(q7(f, r, b, r2, t, s));
}
return res;
}
// rotate an array of 2d points // rotate an array of 2d points
function rotate(points_array, angle) { function rotate(points_array, angle) {
let answer = []; let answer = [];
@ -780,32 +791,31 @@ mesh.tool = class MeshTool {
let r = p - (c - p) - clearance; // radius of root circle let r = p - (c - p) - clearance; // radius of root circle
let t = mm_per_tooth / 2 - backlash / 2; // tooth thickness at pitch circle let t = mm_per_tooth / 2 - backlash / 2; // tooth thickness at pitch circle
let k = -iang(b, p) - t / 2 / p; // angle where involute meets base circle on side of tooth let k = -iang(b, p) - t / 2 / p; // angle where involute meets base circle on side of tooth
let points = [ // [x,y] points for a single gear tooth
polar(r, -pi / number_of_teeth),
polar(r, r < b ? k : -pi / number_of_teeth),
...qf(10, r, b, c, k, 1),
...qf(10, r, b, c, k, -1).reverse(),
polar(r, r < b ? -k : pi / number_of_teeth),
// polar(r, 3.142 / number_of_teeth)
];
// here is the magic - a set of [x,y] points to create a single gear tooth let gear = [];
let points = [polar(r, -3.142 / number_of_teeth), polar(r, r < b ? k : -pi / number_of_teeth), // create all gear teeth by rotating the first tooth
q7(0 / 5, r, b, c, k, 1), q7(1 / 5, r, b, c, k, 1), q7(2 / 5, r, b, c, k, 1), q7(3 / 5, r, b, c, k, 1), q7(4 / 5, r, b, c, k, 1), q7(5 / 5, r, b, c, k, 1),
q7(5 / 5, r, b, c, k, -1), q7(4 / 5, r, b, c, k, -1), q7(3 / 5, r, b, c, k, -1), q7(2 / 5, r, b, c, k, -1), q7(1 / 5, r, b, c, k, -1), q7(0 / 5, r, b, c, k, -1),
polar(r, r < b ? -k : pi / number_of_teeth), polar(r, 3.142 / number_of_teeth)];
let answer = [];
// create every gear tooth by rotating the first tooth
for (var i = 0; i < number_of_teeth; i++) { for (var i = 0; i < number_of_teeth; i++) {
answer = answer.concat(rotate(points, -i * 2 * pi / number_of_teeth)); gear.appendAll(rotate(points, -i * 2 * pi / number_of_teeth));
} }
return answer; // returns an array of [x,y] points return gear; // returns an array of [x,y] points
} }
// gear parameter setup // gear parameter setup
// number_of_teeth = numTeeth; // number of teeth (typically the only parameter to change) let mm_per_tooth = 2 * module * pi; // mm size of one gear tooth
// note: rest of parameters must be unchanged if you want gears to fit. let clearance = 0; // freedom between two gear centers
let mm_per_tooth = 9 * module * pi; // pixel size of one gear tooth (even though it says millimeters, it's pixels) must be same for two gears to fit each other let backlash = 0; // freedom between two gear contact points
// let pressure_angle = pressureAngle; // in degrees, determines gear shape, range is 10 to 40 degrees, most common is 20 degrees let pressure_angle = degrees_to_radians(pressureAngle);
let clearance = 4; // freedom between two gear centers
let backlash = 4; // freedom between two gear contact points console.log({ mm_per_tooth });
let axle_radius = 20; // center hole radius in pixels
let pressure_angle = degrees_to_radians(pressureAngle); // convet degrees to radians
return build_gear(numTeeth); return build_gear(numTeeth);
} }

View file

@ -401,11 +401,34 @@ let model = {
}, },
gen_gear(data, send) { gen_gear(data, send) {
const { teeth, module, angle, z } = data; const { teeth, module, angle, twist, shaft, z } = data;
let points = new mesh.tool().generateGear(teeth, module, angle); let points = new mesh.tool()
let verts = points.map(v => [...v, 0]).flat(); .generateGear(teeth, module, angle)
let poly = newPolygon().addVerts(verts).extrude(z || 10); .map(v => [...v, 0]).flat();
send.done(poly); let poly = newPolygon().addVerts(points);
if (shaft) {
poly.addInner(
newPolygon().centerCircle({
x:0, y:0, z:0
}, shaft, Math.min(20+shaft,100))
);
}
let verts = poly.extrude(z || 15);
if (twist) {
let rad = base.util.toRadians(twist);
for (let i=0; i<verts.length; i += 3) {
if (Math.abs(verts[i+2]) < 0.001) {
let [x, y] = base.util.rotate(
verts[i],
verts[i+1],
rad
);
verts[i] = x;
verts[i+1] = y;
}
}
}
send.done(verts);
} }
}; };