歯車について勉強する の履歴(No.1)

更新


公開メモ

LANG: p5js_live
function myCreateSlider(label, i, option) {
  let x = 20, y = i * 30 + 20;
  createSpan(label).position(x, y);
  let span = createSpan(option[2]);
  span.position(x+370, y);
  let slider = createSlider(...option);
  slider.position(x+60, y);
  slider.size(300);
  slider.input(()=> span.html(slider.value()));
  return slider;
}

let d = 0;
let wsize = 800;
function setup() {
  createCanvas(wsize, wsize);
  sliderM = myCreateSlider('Scale',   0, [10, 200, 40, 1]);
  sliderA = myCreateSlider('Teeth A', 1, [6, 100, 6, 1]);
  sliderB = myCreateSlider('Teeth B', 2, [6, 100, 6, 1]);
  sliderAA= myCreateSlider('Alpha'  , 3, [10, 30, 20, 1]);
  sliderS = myCreateSlider('Speed',   4, [-10, 50, 10, 1]);
}

function draw() {
  background(220);
  noFill();
  stroke('#00c');
  strokeWeight(1);
  
  const m = sliderM.value(), z1=sliderA.value();
  let z2=sliderB.value(); 
  let dd = z2 % 2 ? Math.PI/z2 : 0;
  let gap = 0;
  gear(wsize/2 - m*z1/2, wsize/2, d/z1, m-gap/z1, z1, sliderAA.value()/ 360 * 2 * Math.PI);
  gear(wsize/2 + m*z2/2, wsize/2, -d/z2+dd, m-gap/z2, z2, sliderAA.value()/ 360 * 2 * Math.PI);
  d += 0.001 * sliderS.value();
}

function gear(ox, oy, d, m, z, a = 20 / 360 * 2 * Math.PI) {
  let rp = m * z / 2;
  let rk = m * (z+2) / 2;
  let rf = m * (z-2.5) / 2;
  let rb = m * z * Math.cos(a) / 2;
  
  // circle(ox,oy,rp*2);
  // circle(ox,oy,rk*2);
  // circle(ox,oy,rf*2);
  // circle(ox,oy,rb*2);

  const a0 = Math.tan(Math.acos(rb/rp))-Math.acos(rb/rp);
  const r2a = (r) => Math.tan(Math.acos(rb/r))-Math.acos(rb/r)-a0;

  let p1=[]
  let n = 30, r0=Math.max(rb, rf);
  for(let j=0; j <= n; j++) {
    let rj = r0 + (rk-r0) * j/n;
    p1.unshift([rj, r2a(rj)]);
  }
  if(rf<rb) {
    for(let j=0; j <= n; j++) {
      let rj = r0 + (rf-r0) * j/n;
      p1.push([rj, r2a(rb)]);
    }
  }
  
  let p = []
  if(rb>rf) {
    let last_r = rp;
    let ff = 0, ao=-Math.PI/z/2;
    for(let dp=0;  ; dp-=0.01) {
      let y = Math.PI*m/4-m*Math.tan(a)+rp*dp
      let x = (rp-m)
      let r = Math.sqrt(x*x+y*y)
      let aa = Math.atan2(y,x)-dp;
      if(last_r<r) break;
      p.push([r, aa+ao]);
      last_r = r;
    }
    let f = 0;
    for(let dp=0; f++ < 200 ; dp+=0.01) {
      let y = Math.PI*m/4-m*Math.tan(a)+rp*dp
      let x = (rp-m)
      let r = Math.sqrt(x*x+y*y)
      let aa = Math.atan2(y,x)-dp;
      p.unshift([r, aa+ao]);
    }
  
    let j=0;
    f=0;
    for(let i=0; i<p1.length-1; i++) {
      if(p[j][0]<p1[i][0]) continue;
      while(j<p.length-1 && p[j+1][0]>p1[i][0]) j++;
      if(j>=p.length-1)break;
      let pa = ((p[j][0]-p1[i][0])*p[j+1][1]+(p1[i][0]-p[j+1][0])*p[j][1])/(p[j][0]-p[j+1][0]);
      if(p1[i][1] < pa) f = 1;
      if(f && p1[i][1] >= pa) {
//        p1.splice(i,p1.length-i,...p.slice(j-1,-1));
        p = p.slice(j-1,-1);
        break;
      }
      p1[i][1]=Math.max(p1[i][1], pa)
    }
  }
  
  p1.unshift([p1[0][0],Math.PI/z*(1/2)])
  if(true) {
    // fillet
    for(let i=0; i<p1.length; i++) {
      if(p1[i][0]<rf+m/2) {
        p1[i][1] += (-Math.PI/z*1/2-p1[i][1])*((rf+m/2-p1[i][0])/(m/2))**3;
      }
    }
  } else {
    p1.push([p1[p1.length-1][0],-Math.PI/z*1/2])
  }
  
  for(let j=0; j<z; j++) {
    let dd = 2*Math.PI/z*j;
    let dd2 = 2*Math.PI/z*(1/2+j);
    for(let i=0; i<p1.length-1; i++) {
      line(ox+p1[i][0]*Math.cos(d+p1[i][1]+dd), oy+p1[i][0]*Math.sin(d+p1[i][1]+dd), 
           ox+p1[i+1][0]*Math.cos(d+p1[i+1][1]+dd), oy+p1[i+1][0]*Math.sin(d+p1[i+1][1]+dd));
      line(ox+p1[i][0]*Math.cos(d-p1[i][1]+dd2), oy+p1[i][0]*Math.sin(d-p1[i][1]+dd2), 
           ox+p1[i+1][0]*Math.cos(d-p1[i+1][1]+dd2), oy+p1[i+1][0]*Math.sin(d-p1[i+1][1]+dd2));
    }
  }
}

Counter: 601 (from 2010/06/03), today: 3, yesterday: 1