这是完整的代码...
   include("gears.jscad");
// Here we define the user editable parameters: 
function getParameterDefinitions() {
  return [
    { name: 'circularPitch', caption: 'Circular pitch:', type: 'float', initial: 5 },
    { name: 'pressureAngle', caption: 'Pressure angle:', type: 'float', initial: 20 },
    { name: 'clearance', caption: 'Clearance:', type: 'float', initial: 0 },
    { name: 'thickness', caption: 'Thickness of transmission gears:', type: 'float', initial: 5 },
    { name: 'spurTeeth', caption: 'Number of spur teeth:', type: 'int', initial: 32 },
    { name: 'pinionTeeth', caption: 'Number of pinion teeth:', type: 'int', initial: 14 },
    { name: 'bore', caption: 'Radius of shaft:', type: 'float', initial: 5 }
  ];
}
 // Main function
 function main(params)
{
  // declare parts
  spurGear = new makeSpur(params);
  pinionGear = new makePinion(params);
  // assemble parts
  spurGear = spurGear.translate([-pinionGear.pitchRadius, 0, -20]); // BREAKS CODE
  pinionGear = pinionGear.translate([-spurGear.pitchRadius, 0, 20]); // BREAKS CODE
  return [spurGear,pinionGear];
}
// Spur Gear
function makeSpur(params)
{
  var gear = new involuteGear(
    params.spurTeeth,
    params.circularPitch,
    params.pressureAngle,
    params.clearance,
    params.thickness,
    params.bore
  );
  if(params.bore > 0)
  {
    var bore = CSG.cylinder({start: [0,0,-params.thickness], end: [0,0,params.thickness], radius: params.bore, resolution: 16});
    gear = gear.subtract(bore).rotateX(90);
  }
  return gear;
}
// Pinion Gear
function makePinion(params)
{
  var gear = new involuteGear(
    params.pinionTeeth,
    params.circularPitch,
    params.pressureAngle,
    params.clearance,
    params.thickness,
    params.bore
  );
  if(params.bore > 0)
  {
    var bore = CSG.cylinder({start: [0,0,-params.thickness], end: [0,0,params.thickness], radius: params.bore, resolution: 16});
    gear = gear.subtract(bore).rotateX(90);
  }
  return gear;
}
// title: Gear
// author: Joost Nieuwenhuijse
// license: MIT License
/*
  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:
  this.pitchRadius = numTeeth * circularPitch / (2 * Math.PI);
  // this.getpitchRadius = function() {
    //return pitchRadius;
  //};
  var baseRadius = this.pitchRadius * Math.cos(Math.PI * pressureAngle / 180);
  var outerRadius = this.pitchRadius + addendum;
  var rootRadius = this.pitchRadius - dedendum;
  var maxtanlength = Math.sqrt(outerRadius*outerRadius - baseRadius*baseRadius);
  var maxangle = maxtanlength / baseRadius;
  var tl_at_pitchcircle = Math.sqrt(this.pitchRadius*this.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 j = 0; j < numTeeth; j++)
  {
    var ang = j*360/numTeeth;
    var rotatedtooth = tooth3d.rotateZ(ang);
    allteeth = allteeth.unionForNonIntersecting(rotatedtooth);
  }
  // build the root circle:  
  points = [];
  var toothAngle = 2 * Math.PI / numTeeth;
  var toothCenterAngle = 0.5 * angularToothWidthAtBase; 
  for(var k = 0; k < numTeeth; k++)
  {
    var angl = toothCenterAngle + k * toothAngle;
    var p1 = CSG.Vector2D.fromAngle(angl).times(rootRadius);
    points.push(p1);
  }
  // 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;
}