1

I am a novice programmer working with OpenJScad written in Javascript to build 3D models.

I am trying to figure out how to structure my code so that I can access an object's instance properties that are dynamically created with user input parameters. I have a parent Gear class with the following variable...

// Gear parent class
Gear = function(numTeeth, circularPitch, pressureAngle, clearance, thickness)
{    
var pitchRadius = numTeeth * circularPitch / (2 * Math.PI);

I am making several Gear sub-classes that accept user parameters, ie...

// Spur Gear
function makeSpur(params)
{
    var gear = new Gear(
    params.spurTeeth,
    params.circularPitch,
    params.pressureAngle,
    params.clearance,
    params.inputBore
);

if(params.inputBore > 0)
{
    var inputBore = CSG.cylinder({start: [0,0,-params.thickness2], end:
        [0,0,params.thickness2], radius: params.inputBore, resolution: 16});
    gear = gear.subtract(inputBore).rotateX(90);
}
return gear;

...and then dynamically generating location coordinates based on the pitchRadius property of another Gear object...

// function main
var spurGear = makeSpur(params);
spurGear = spurGear.translate([-pinionGear.pitchRadius,0,0]);

Everything renders, except when I try to access the pitchRadius property from another Gear instance. Ive read about prototypes and accessing private / public properties, but I just can't figure out how to structure the code so that I can access instance properties in function main.

Marek Grzenkowicz
  • 17,024
  • 9
  • 81
  • 111
  • 2
    `var` creates a local variable, have you tried `this.pitchRadius = ...`? – elclanrs Jul 23 '13 at 00:47
  • @elclanrs I have tried that but it still could not access the instance property – Sean Ragsdale Jul 23 '13 at 00:55
  • Something else must be wrong with your code than, when you define a property in the contructor function body with `this.pitchRadius=` then it becomes available as an instance property. The code you posted should work if you use `this.pitchRadius` – HMR Jul 23 '13 at 01:39
  • @HMR Could it be improper scope? Right now I have the constructors outside of main. – Sean Ragsdale Jul 23 '13 at 02:52
  • Are you getting errors? In firefox with firebug you can break on an error and check out what line causes the error. Use the console to log the value of spurGear. – HMR Jul 23 '13 at 05:49
  • @HMR When I compile the original code I get no errors. When i change var.pitchRadius to a priveleged property, the code breaks when I reference the property in an instance object in main. – Sean Ragsdale Jul 23 '13 at 18:28

2 Answers2

0

Here is the full code...

   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;
}
0

I noticed that you are actually returning CSG object in the constructor, so try to use properties container described in OpenJSCAD User guide. According to the guide properties variable is intended to store metadata for the object.

This is an example from guide:

var cube = CSG.cube({radius: 1.0});
cube.properties.aCorner = new CSG.Vector3D([1, 1, 1]);

Additional comments:

  1. You are returning different object then this in your constructor
  2. If you will do something like this: gear = gear.rotateX(90); then you have new object
  3. If you will use properties then metadata is cloned when you do transformation.
mrh
  • 917
  • 1
  • 9
  • 28