ProcessingProcessingサイクロイド曲線

Processingで内サイクロイド曲線を作る

はじめに

前回は、外サイクロイド曲線をProcessingで作ったので、今回は内サイクロイド曲線を作りたいと思います。

内サイクロイド曲線とは?

動円が定円の内側にあるとき、動円の円周上の点が描く軌跡を内サイクロイド曲線またはハイポサイクロイドといいます。

Processingで動かすために動円上の点 P(x,y)の求め方を見ていきましょう。

点P\((x,y)\)の位置を求める

\begin{cases}
x=(R-r)\cos\theta+r\cos\displaystyle\frac{(R-r)\theta}{r} \\
y=(R-r)\sin\theta-r\sin\displaystyle\frac{(R-r)\theta}{r}
\end{cases}

定円半径Rと動円半径rの比率による関係

上図より、定円半径:動円半径 = 2 : 1のときは直線になり、
4 : 1のときはアステロイドになります。

それではProcessingで動かしてみて確かめましょう。

Processingで内サイクロイド曲線

以下がProcessingで内サイクロイド曲線を動かすコードになります。
前回同様に理解しやすくするためにボタンも実装してみました。

PGraphics pg1, pg2, pg3, pg4;
float x, y;
float rad = 0;
float R = 200; //定円半径
float r; //動円半径

boolean Cyc1 = false;
boolean Cyc2 = false;
boolean Cyc3 = false;
boolean Cyc4 = false;
boolean show1 = false;
boolean show2 = false;
boolean show3 = false;
boolean show4 = false;

void setup() {
  size(700, 500);
  pg1 = createGraphics(width, height);
  pg2 = createGraphics(width, height);
  pg3 = createGraphics(width, height);
  pg4 = createGraphics(width, height);
}

void draw() {
  background(230);
  //定円
  noFill();
  ellipse(width/2, 220, R*2, R*2);
  Button();
  rad += 0.6;
  //ボタン操作
  if (Cyc1) Cycloid1(); //2:1(直線)
  if (Cyc2) Cycloid2(); //3:1
  if (Cyc3) Cycloid3(); //4:1(アステロイド)
  if (Cyc4) Cycloid4(); //5:1
  //keyを押したら画像表示
  if (show1) image(pg1, 0, 0);
  if (show2) image(pg2, 0, 0);
  if (show3) image(pg3, 0, 0);
  if (show4) image(pg4, 0, 0);
}

void Button() {
  fill(255);
  rect(100, 440, 80, 30);
  rect(240, 440, 80, 30);
  rect(370, 440, 80, 30);
  rect(500, 440, 80, 30);
  fill(0);
  textSize(16);
  textAlign(CENTER, CENTER);
  text("2:1", 140, 455);
  text("3:1", 280, 455);
  text("4:1", 410, 455);
  text("5:1", 540, 455);
}

void mouseClicked() {
  if (mouseX>=100 && mouseX<=180 && mouseY>=440 && mouseY<=470) {
    Cyc1 = !Cyc1;
    rad = 0;
  }
  if (mouseX>=240 && mouseX<=320 && mouseY>=440 && mouseY<=470) {
    Cyc2 = !Cyc2;
    rad = 0;
  }
  if (mouseX>=370 && mouseX<=450 && mouseY>=440 && mouseY<=470) {
    Cyc3 = !Cyc3;
    rad = 0;
  }
  if (mouseX>=500 && mouseX<=580 && mouseY>=440 && mouseY<=470) {
    Cyc4 = !Cyc4;
    rad = 0;
  }
}

void keyPressed() {
  if (key == '1') {
    show1 = !show1;
    if (!show1) show1 = false;
  } else if (key == '2') {
    show2 = !show2;
    if (!show2) show2 = false;
  } else if (key == '3') {
    show3 = !show3;
    if (!show3) show3 = false;
  } else if (key == '4') {
    show4 = !show4;
    if (!show4) show4 = false;
  }
}

void Cycloid1() {
  r = R/2;
  //内サイクロイド曲線
  x = width/2 + (R-r)*cos(radians(rad)) + r*cos((R-r)*radians(rad)/r);
  y = -220 + (R-r)*sin(radians(rad)) - r*sin((R-r)*radians(rad)/r);
  //円の中心とサイクロイド曲線上の点を結ぶ線分
  line(width/2+(R-r)*cos(radians(rad)), 220-(R-r)*sin(radians(rad)), x, -y);
  //動円
  noFill(); 
  ellipse(width/2+(R-r)*cos(radians(rad)),220-(R-r)*sin(radians(rad)), r*2, r*2);
  pg1.beginDraw();
  pg1.noStroke();
  pg1.fill(209, 0, 0);
  pg1.ellipse(x, -y, 5, 5);
  pg1.endDraw();
  image(pg1, 0, 0);
  if (rad >= 360) {
    delay(3000); //1周したら3秒停止
    Cyc1 = !Cyc1;
  }
}

void Cycloid2() {
  r = R/3;
  x = width/2 + (R-r)*cos(radians(rad)) + r*cos((R-r)*radians(rad)/r);
  y = -220 + (R-r)*sin(radians(rad)) - r*sin((R-r)*radians(rad)/r);
  //円の中心とサイクロイド曲線上の点を結ぶ線分
  line(width/2+(R-r)*cos(radians(rad)), 220-(R-r)*sin(radians(rad)), x, -y);
  //動円
  noFill(); 
  ellipse(width/2+(R-r)*cos(radians(rad)),220-(R-r)*sin(radians(rad)), r*2, r*2);
  pg2.beginDraw();
  pg2.noStroke();
  pg2.fill(0, 40, 205);
  pg2.ellipse(x, -y, 5, 5);
  pg2.endDraw();
  image(pg2, 0, 0);
  if (rad >= 360) {
    delay(3000);
    Cyc2 = !Cyc2;
  }
}

void Cycloid3() {
  r = R/4;
  x = width/2 + (R-r)*cos(radians(rad)) + r*cos((R-r)*radians(rad)/r);
  y = -220 + (R-r)*sin(radians(rad)) - r*sin((R-r)*radians(rad)/r);
  //円の中心とサイクロイド曲線上の点を結ぶ線分
  line(width/2+(R-r)*cos(radians(rad)), 220-(R-r)*sin(radians(rad)), x, -y);
  //動円
  noFill(); 
  ellipse(width/2+(R-r)*cos(radians(rad)),220-(R-r)*sin(radians(rad)), r*2, r*2);
  pg3.beginDraw();
  pg3.noStroke();
  pg3.fill(74, 170, 64);
  pg3.ellipse(x, -y, 5, 5);
  pg3.endDraw();
  image(pg3, 0, 0);
  if (rad >= 360) {
    delay(3000);
    Cyc3 = !Cyc3;
  }
}

void Cycloid4() {
  r = R/5;
  x = width/2 + (R-r)*cos(radians(rad)) + r*cos((R-r)*radians(rad)/r);
  y = -220 + (R-r)*sin(radians(rad)) - r*sin((R-r)*radians(rad)/r);
  //円の中心とサイクロイド曲線上の点を結ぶ線分
  line(width/2+(R-r)*cos(radians(rad)), 220-(R-r)*sin(radians(rad)), x, -y);
  //動円
  noFill(); 
  ellipse(width/2+(R-r)*cos(radians(rad)),220-(R-r)*sin(radians(rad)), r*2, r*2);
  pg4.beginDraw();
  pg4.noStroke();
  pg4.fill(213, 81, 139);
  pg4.ellipse(x, -y, 5, 5);
  pg4.endDraw();
  image(pg4, 0, 0);
  if (rad >= 360) {
    delay(3000);
    Cyc4 = !Cyc4;
  }
}

アニメーション

実際の動作は以下のようになります。

参考文献

・Wikipedia-サイクロイド
https://ja.wikipedia.org/wiki/サイクロイド

・実用メカニズム事典

コメント

タイトルとURLをコピーしました