187 lines
5.5 KiB
HTML
187 lines
5.5 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html><head>
|
|
<script src="lightgl.js"></script>
|
|
<script src="csg.js"></script>
|
|
<script src="openjscad.js"></script>
|
|
<style>
|
|
|
|
body {
|
|
font: 14px/20px 'Helvetica Neue Light', HelveticaNeue-Light, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
max-width: 820px;
|
|
margin: 0 auto;
|
|
padding: 10px;
|
|
}
|
|
|
|
pre, code, textarea {
|
|
font: 12px/20px Monaco, monospace;
|
|
border: 1px solid #CCC;
|
|
border-radius: 3px;
|
|
background: #F9F9F9;
|
|
padding: 0 3px;
|
|
color: #555;
|
|
}
|
|
pre, textarea {
|
|
padding: 10px;
|
|
width: 100%;
|
|
}
|
|
textarea {
|
|
height: 200px;
|
|
}
|
|
textarea:focus {
|
|
outline: none;
|
|
}
|
|
|
|
canvas { cursor: move; }
|
|
|
|
</style>
|
|
<link rel="stylesheet" href="openjscad.css" type="text/css">
|
|
|
|
<script>
|
|
|
|
var gProcessor=null;
|
|
|
|
// Show all exceptions to the user:
|
|
OpenJsCad.AlertUserOfUncaughtExceptions();
|
|
|
|
function onload()
|
|
{
|
|
gProcessor = new OpenJsCad.Processor(document.getElementById("viewer"));
|
|
updateSolid();
|
|
}
|
|
|
|
function updateSolid()
|
|
{
|
|
gProcessor.setJsCad(document.getElementById('code').value);
|
|
}
|
|
</script>
|
|
<title>OpenJsCad demo: involute gears</title>
|
|
</head>
|
|
<body onload="onload()">
|
|
<h1>OpenJsCad demo: involute gears</h1>
|
|
<div id="viewer"></div>
|
|
<h2>Source code</h2>
|
|
Below is the OpenJsCad script for this demo. To build your own models, create a .jscad script
|
|
and use the <a href="processfile.html"><b>OpenJsCad parser</b></a>. For more information see the
|
|
<a href="index.html">OpenJsCad documentation</a>.
|
|
<br><br>
|
|
<textarea id="code">
|
|
// Here we define the user editable parameters:
|
|
function getParameterDefinitions() {
|
|
return [
|
|
{ name: 'numTeeth', caption: 'Number of teeth:', type: 'int', default: 10 },
|
|
{ name: 'circularPitch', caption: 'Circular pitch:', type: 'float', default: 5 },
|
|
{ name: 'pressureAngle', caption: 'Pressure angle:', type: 'float', default: 20 },
|
|
{ name: 'clearance', caption: 'Clearance:', type: 'float', default: 0 },
|
|
{ name: 'thickness', caption: 'Thickness:', type: 'float', default: 5 },
|
|
{ name: 'centerholeradius', caption: 'Radius of center hole (0 for no hole):', type: 'float', default: 2 },
|
|
];
|
|
}
|
|
|
|
// Main entry point; here we construct our solid:
|
|
function main(params)
|
|
{
|
|
var gear = involuteGear(
|
|
params.numTeeth,
|
|
params.circularPitch,
|
|
params.pressureAngle,
|
|
params.clearance,
|
|
params.thickness
|
|
);
|
|
if(params.centerholeradius > 0)
|
|
{
|
|
var centerhole = CSG.cylinder({start: [0,0,-params.thickness], end: [0,0,params.thickness], radius: params.centerholeradius, resolution: 16});
|
|
gear = gear.subtract(centerhole);
|
|
}
|
|
return gear;
|
|
}
|
|
|
|
/*
|
|
For gear terminology see:
|
|
http://www.astronomiainumbria.org/advanced_internet_files/meccanica/easyweb.easynet.co.uk/_chrish/geardata.htm
|
|
Algorithm based on:
|
|
http://www.cartertools.com/involute.html
|
|
|
|
circularPitch: The distance between adjacent teeth measured at the pitch circle
|
|
*/
|
|
function involuteGear(numTeeth, circularPitch, pressureAngle, clearance, thickness)
|
|
{
|
|
// default values:
|
|
if(arguments.length < 3) pressureAngle = 20;
|
|
if(arguments.length < 4) clearance = 0;
|
|
if(arguments.length < 4) thickness = 1;
|
|
|
|
var addendum = circularPitch / Math.PI;
|
|
var dedendum = addendum + clearance;
|
|
|
|
// radiuses of the 4 circles:
|
|
var pitchRadius = numTeeth * circularPitch / (2 * Math.PI);
|
|
var baseRadius = pitchRadius * Math.cos(Math.PI * pressureAngle / 180);
|
|
var outerRadius = pitchRadius + addendum;
|
|
var rootRadius = pitchRadius - dedendum;
|
|
|
|
var maxtanlength = Math.sqrt(outerRadius*outerRadius - baseRadius*baseRadius);
|
|
var maxangle = maxtanlength / baseRadius;
|
|
|
|
var tl_at_pitchcircle = Math.sqrt(pitchRadius*pitchRadius - baseRadius*baseRadius);
|
|
var angle_at_pitchcircle = tl_at_pitchcircle / baseRadius;
|
|
var diffangle = angle_at_pitchcircle - Math.atan(angle_at_pitchcircle);
|
|
var angularToothWidthAtBase = Math.PI / numTeeth + 2*diffangle;
|
|
|
|
// build a single 2d tooth in the 'points' array:
|
|
var resolution = 5;
|
|
var points = [new CSG.Vector2D(0,0)];
|
|
for(var i = 0; i <= resolution; i++)
|
|
{
|
|
// first side of the tooth:
|
|
var angle = maxangle * i / resolution;
|
|
var tanlength = angle * baseRadius;
|
|
var radvector = CSG.Vector2D.fromAngle(angle);
|
|
var tanvector = radvector.normal();
|
|
var p = radvector.times(baseRadius).plus(tanvector.times(tanlength));
|
|
points[i+1] = p;
|
|
|
|
// opposite side of the tooth:
|
|
radvector = CSG.Vector2D.fromAngle(angularToothWidthAtBase - angle);
|
|
tanvector = radvector.normal().negated();
|
|
p = radvector.times(baseRadius).plus(tanvector.times(tanlength));
|
|
points[2 * resolution + 2 - i] = p;
|
|
}
|
|
|
|
// create the polygon and extrude into 3D:
|
|
var tooth3d = new CSG.Polygon2D(points).extrude({offset: [0, 0, thickness]});
|
|
|
|
var allteeth = new CSG();
|
|
for(var i = 0; i < numTeeth; i++)
|
|
{
|
|
var angle = i*360/numTeeth;
|
|
var rotatedtooth = tooth3d.rotateZ(angle);
|
|
allteeth = allteeth.unionForNonIntersecting(rotatedtooth);
|
|
}
|
|
|
|
// build the root circle:
|
|
points = [];
|
|
var toothAngle = 2 * Math.PI / numTeeth;
|
|
var toothCenterAngle = 0.5 * angularToothWidthAtBase;
|
|
for(var i = 0; i < numTeeth; i++)
|
|
{
|
|
var angle = toothCenterAngle + i * toothAngle;
|
|
var p = CSG.Vector2D.fromAngle(angle).times(rootRadius);
|
|
points.push(p);
|
|
}
|
|
|
|
// create the polygon and extrude into 3D:
|
|
var rootcircle = new CSG.Polygon2D(points).extrude({offset: [0, 0, thickness]});
|
|
|
|
var result = rootcircle.union(allteeth);
|
|
|
|
// center at origin:
|
|
result = result.translate([0, 0, -thickness/2]);
|
|
|
|
return result;
|
|
}
|
|
</textarea><br>
|
|
<input type="submit" value="Update" onclick="updateSolid(); return false;">
|
|
<br><br>
|
|
</body>
|
|
</html> |