Simple Gears

edited August 2014 in Share Your Work

Hi: This is a simple gears visual simulation test code I built for fun and wanted to share it with yoiu. Please let me know if you have any suggestions or find any problems.

Thanks,

Here is the video:

and here is the code:

//Simple Gears(visual simulation test code).
//Built with Processing 2.03 by Adrian Fernandez. Miami, FL. USA. (07-31-2014).

final int minNumberOfTeeth=3;
final int maxNumberOfTeeth=40;

void setup()
{
  size(1350, 690);  
  frameRate(60);
  textAlign(CENTER);
  textSize(18);
}

void draw()
{
  background(0);  
  int radio=100;
  float teethHeight=0.18*radio; 
  float centerPositionX=2*width/3-radio-teethHeight/2;
  float centerPositionY=height/2;
  int rotationDirection=1;
  float rotationSpeed=1;
  drawGear(radio, centerPositionX, centerPositionY, teethHeight, rotationDirection, rotationSpeed);
  radio=50;  
  rotationDirection=-1;
  rotationSpeed=2;
  centerPositionX=2*width/3+radio+teethHeight/2;
  centerPositionY=height/2-teethHeight/(2*rotationSpeed); 
  drawGear(radio, centerPositionX, centerPositionY, teethHeight, rotationDirection, rotationSpeed); 
  radio=200;
  rotationDirection=-1;
  rotationSpeed=0.5;
  centerPositionX=2*width/3-2*radio-4*teethHeight/3;
  centerPositionY=height/2+3*teethHeight/(2*rotationSpeed); 
  drawGear(radio, centerPositionX, centerPositionY, teethHeight, rotationDirection, rotationSpeed); 
  fill(255);
  text("Move mouse sideways to see rotation.", width/2, 100);
}

void drawGear(int radio, float centerPositionX, float centerPositionY, float teethHeight, float rotationDirection, float rotationSpeed )
{ 
  float rotationAngle=map(mouseX, 0, width, 0, TWO_PI ); 
  int numberOfTeeth=radio/5; 
  numberOfTeeth=constrain(numberOfTeeth, minNumberOfTeeth, maxNumberOfTeeth);
  float teethAngle=TWO_PI/numberOfTeeth;
  float teethWidth=sin(teethAngle/2)*radio; 
  float lineY=cos(teethAngle/2)*radio+teethHeight;
  pushMatrix();
  translate(centerPositionX, centerPositionY);
  rotate( rotationDirection*rotationSpeed*rotationAngle);
  fill(150);
  stroke(255);
  for (int i=0; i<numberOfTeeth; i++)
  {  
    rotate(teethAngle); 
    stroke(200);
    strokeWeight(1);
    triangle(-3*teethWidth/4, -lineY+teethHeight, teethWidth/2, -lineY+teethHeight, -teethWidth/2, -lineY);
    triangle(teethWidth/4, -lineY, -teethWidth/2, -lineY, teethWidth/2, -lineY+teethHeight);
    stroke(150);
    strokeWeight(2);
    line(-teethWidth/2, -lineY, teethWidth/2, -lineY+teethHeight);
  }
  stroke(100);
  ellipse(0, 0, 2*(-lineY+teethHeight), 2*(-lineY+teethHeight)) ;
  stroke(80);
  strokeWeight(radio/2); 
  ellipse(0, 0, radio, radio);
  fill(0);
  noStroke();
  ellipse(0, 0, radio/5, radio/5);//Shaft
  AdditionsBlock(radio);
  popMatrix();
}

void AdditionsBlock(float radio)
{
  rectMode(CENTER);
  rect(0, -radio/10, radio/20, -radio/15);
  ellipse(0, 0.85*radio, radio/15, radio/15);//counterWeight
  rotate(PI/20);
  ellipse(0, 0.85*radio, radio/15, radio/15);//counterWeight
  rotate(PI/20);
  ellipse(0, 0.85*radio, radio/15, radio/15);//counterWeight
}

Comments

  • Very nice! ;)

  • edited August 2014

    Made some turbines with few modifications to the same code.

    //Drawing Turbines(visual simulation test code).
    //Built with Processing 2.03 by Adrian Fernandez. Miami, FL. USA. (08-01-2014).
    
    final int minNumberOfBlades=10;
    final int maxNumberOfBlades=40;
    
    void setup()
    {
      size(1350, 690);
      textAlign(CENTER);
      textSize(18);
    }
    
    void draw()
    {
      background(0);
      float radio=60;
      float rotationAngle=map(mouseX, 0, width, 0, PI );  
      int numberOfBlades=40;
      float centerPositionX=width/2-2*radio-400;
      float centerPositionY=height/2;
      drawTurbine(radio, centerPositionX, centerPositionY, numberOfBlades, rotationAngle);
      centerPositionX=width/2-2*radio-150;
      drawTurbine(radio, centerPositionX, centerPositionY, numberOfBlades, rotationAngle); 
      centerPositionX=width/2+2*radio+400;
      centerPositionY=height/2;
      drawTurbine(radio, centerPositionX, centerPositionY, numberOfBlades, rotationAngle);
      centerPositionX=width/2+2*radio+150;
      drawTurbine(radio, centerPositionX, centerPositionY, numberOfBlades, rotationAngle); 
      fill(255);
      text("Move mouse sideways to see rotation", width/2, 100);
    }
    
    void drawTurbine(float radio, float centerPositionX, float centerPositionY, int numberOfBlades, float rotationAngle)
    {
      numberOfBlades=constrain(numberOfBlades, minNumberOfBlades, maxNumberOfBlades);
      float bladeAngle=TWO_PI/numberOfBlades;
      float bladeWidth=sin(bladeAngle/2)*radio;
      float lineY=cos(bladeAngle/2)*radio+radio/4;
      stroke(255);
      pushMatrix();
      translate(centerPositionX, centerPositionY);  
      rotate(rotationAngle);
      for (int i=0; i<numberOfBlades; i++)
      {  
        rotate(bladeAngle);
        fill(150);
        stroke(200);
        strokeWeight(1);
        triangle(-bladeWidth, -lineY-radio/16, bladeWidth, -lineY+radio, 0, -lineY-radio/8);
      }
      strokeWeight(1);
      for (int j=1;j<5;j++)
      {
        stroke(5*j);
        ellipse(0, 0, -radio/(1+j), -radio/(1+j));
      }
      noFill(); 
      stroke(80);
      strokeWeight(radio/4);
      ellipse(0, 0, -3.05*radio, -3.05*radio);
      stroke(150);
      strokeWeight(radio/12);
      ellipse(0, 0, -3.05*radio, -3.05*radio);
      popMatrix();
    }
    
  • edited March 2015

    Hi! I've made a total code refactoring and post it online: :ar!
    http://studio.processingtogether.com/sp/pad/export/ro.9WrTp2GiTlnLW/latest

    It's using a class + static background. Only the dents and holes are actually dynamically rendered! :bz
    Check it out the modded code below: :D

    /**
     * Simple Gears (v2.04)
     * by Adrian Fernandez aKa Processor65
     * Miami, FL. USA (Jul-31-2014)
     * mod GoToLoop (Aug-01-2014)
     *
     * forum.processing.org/two/discussion/6576/simple-gears
     * studio.processingtogether.com/sp/pad/export/ro.9WrTp2GiTlnLW/latest
     */
    
    static final color[] INKS = {
      #008000, #0000FF, #FF0000
    }; 
    
    final Gear[] gears = new Gear[INKS.length];
    
    static final boolean online = 1/2 == 1/2.;
    
    PImage bg;
    
    void setup() {
      size(1000, 600, JAVA2D);
      noLoop();
      frameRate(20);
    
      noStroke();
      strokeWeight(1);
    
      rectMode(CENTER);
      ellipseMode(CENTER);
    
      createGears();
      println(gears);
    
      bg = createBG();
    }
    
    void mouseMoved() {
      redraw();
    }
    
    void draw() {
      if (online)  set(0, 0, bg);
      else         background(bg);
    
      for (Gear gear: gears)  gear.renderDynamic();
    }
    
    void createGears() {
      int offSetX = width*3>>2;
      int offSetY = height>>1;
    
      int rad = 100;
      int spd = 1;
    
      int cx = offSetX - rad - Gear.TOOTH_HEIGHT/2;
      int cy = offSetY;
    
      gears[0] = new Gear(cx, cy, rad, spd, 1);
    
      rad = 50;
      spd = 2;
    
      cx = offSetX + rad + Gear.TOOTH_HEIGHT/2;
      cy = offSetY - Gear.TOOTH_HEIGHT/2/spd;
    
      gears[1] = new Gear(cx, cy, rad, spd, -1);
    
      rad = 200;
      float vel = .5;
    
      cx = offSetX - rad*2 - Gear.TOOTH_HEIGHT*4/3;
      cy = offSetY + round(Gear.TOOTH_HEIGHT*3/2/vel);
    
      gears[2] = new Gear(cx, cy, rad, vel, -1);
    }
    
    PImage createBG() {
      PGraphics pg = createGraphics(width, height, JAVA2D);
    
      pg.beginDraw();
      pg.smooth(4);
      pg.ellipseMode(CENTER);
    
      pg.textAlign(CENTER, CENTER);
      pg.textSize(030);
    
      pg.background(0); 
      pg.fill(-1);
      pg.text("Move mouse sideways to see rotation", width>>1, height>>3);
    
      int c = 0;
      for (Gear gear: gears)  gear.renderStatic(pg, INKS[c++]);
    
      pg.endDraw();
      return pg.get();
    }
    
    final class Gear {
      static final int MIN_TEETH = 3, MAX_TEETH = 0200 - 1;
      static final int TOOTH_HEIGHT = 18;
    
      final short centerX, centerY, rad;
      final byte  teeth, toothWidth;
    
      final float vel, toothAngle;
      final short lineY, toothHY;
    
      Gear(int cx, int cy, int dim, float spd, int dir) {
        centerX = (short) cx;
        centerY = (short) cy;
    
        rad = (short) dim;
        vel = spd*dir;
    
        teeth = (byte) constrain(dim/5, MIN_TEETH, MAX_TEETH);
        toothAngle = TWO_PI/teeth;
    
        toothWidth = (byte) round(sin(toothAngle/2.0)*dim);
        lineY = (short) (TOOTH_HEIGHT + round(cos(toothAngle/2.0)*dim));
        toothHY = (short) (TOOTH_HEIGHT - lineY);
      }
    
      void renderStatic(PGraphics pg, color c) {
        pg.stroke(100);
        pg.strokeWeight(2);
        pg.fill(0250);
        pg.ellipse(centerX, centerY, -toothHY<<1, -toothHY<<1);
    
        pg.fill(c);
        pg.ellipse(centerX, centerY, rad*1.5, rad*1.5);
    
        pg.noStroke();
        pg.fill(0);
        pg.ellipse(centerX, centerY, rad/5, rad/5);
      }
    
      void renderDynamic() {
        translate(centerX, centerY);
        rotate(mouseX*TWO_PI/width*vel);
    
        noSmooth();
        fill(0250);
        drawDents();
    
        smooth(2);
        fill(0);
        drawHoles();
    
        resetMatrix();
      }
    
      protected void drawDents() {
        int toothRad = toothWidth>>1, toothQuarter = toothRad>>1;
        float toothAdjust = toothWidth*-.7;
    
        for (int i = 0; i++ != teeth; rotate(toothAngle)) {
          triangle(toothAdjust, toothHY
            , toothRad, toothHY
            , -toothRad, -lineY);
    
          triangle(toothQuarter, -lineY
            , -toothRad, -lineY
            , toothRad, toothHY);
    
          if (online)  drawGapFill(toothRad);
        }
      }
    
      protected void drawGapFill(int rad) {
        stroke(0250);
        line(-rad, -lineY, rad, toothHY);
        noStroke();
      }
    
      protected void drawHoles() {
        int d = rad>>4;
        rect(0, -rad/10, rad/20, d);
    
        float y = .85*rad;
        for (int i = 0; i++ != 3; rotate(PI/20.0))  ellipse(0, y, d, d);
      }
    
      String toString() {
        return "Dents: #" + teeth + " \tDiam: " + (rad<<1)
          + " \tSpeed: " + vel;
      }
    }
    
  • Well, that's a more sophisticated way of doing it, thanks for sharing. I noticed a couple of things:

    -In the online version the tooth's edges look really smooth; but the division line between the 2 triangles is visible. In my version, I added the line (code line 63) to erase it.

    -When run in the computer the division line is not visible; but the edges look jagged.

    I see you really liked this one.. ;)

    Thanks

  • edited August 2014

    HEHE! Made it for performance and organization reasons.
    Using noSmooth() in "Java Mode" seems to blend the 2 triangle() drawings together well.
    But it seems like it doesn't transpose that well for "JavaScript Mode"! :-&

  • Can you add the line to make the triangles blend?

  • edited August 2014

    It's done now! New 2.03 version w/ an additional drawGapFill() method! =:)
    It's conditioned to call that online only though! ;)

  • edited September 2014

    Update: Added a Reciprocating Engine with system inertia for acceleration and braking.

    Still with problems related to the math and physics.

    -To simulate inertia the angular speed varies exponentially tending asymptotically to the final speed value in both cases (acceleration and braking). In reality I don't know if that's the equation in a real physical system like that; but the visual effect is acceptable. When braking the rotation even reverses (by the end of the video) something I wasn't expecting.

    These are the equations I'm using to control the angular speed.

    -For acceleration [1-exp(-t/TC)] ----------TC is the Time Constant

    -For braking [exp(-t/TC)]

    Still under construction...

    Here is how it looks:

Sign In or Register to comment.