> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.eC03SBGtZfQ/rev.10
 * 
 * authors: 
 *   GoToLoop

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/**
 * 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;
  }
}