はじめに
今回は「美しい幾何学」第6章のピタゴラスの定理Ⅱを参考にProcessingで作ろうかと思います
リンク
ユークリッド原論によるピタゴラスの定理の証明
400を超えるピタゴラスの定理の証明の中でも、ユークリッドの証明はすでに確立されているほんのわずかな最小限の定理のみを用いるという、そのまったくの厳格さの点で際立っているとこの本にはあります。
ユークリッドの証明は前回の等積な三角形を使用します。ここでは証明は省きますが、内容は
「直角三角形の斜辺でない1つの辺上につくられた正方形は、その1辺が斜辺上に射影された辺と斜辺を2辺にもつ長方形と同じ面積をもつ」ということです。
つまり、上図を見ると上の青と橙色の正方形は下の青と橙色の長方形と同じ面積ということです。
それではProcessingで作成します。
プログラム(アニメーション)
このプログラムでは白色の三角形の頂点が円周上に動くアニメーションです。
頂点が円周上に動くので白色の三角形は直角三角形になります。
斜辺ではない上の正方形を作るのはベクトルを用いて書きました。
PVector[] vec_t = new PVector[3]; //三角形の位置ベクトル
PVector[] vec_s1 = new PVector[2]; //右上の正方形の位置ベクトル
PVector[] vec_s2 = new PVector[4]; //左上の正方形の位置ベクトル
Deform def;
float r = 90;//真ん中三角形の底辺の1/2
float i = 0;
void setup() {
size(500, 500);
def = new Deform();
}
void draw() {
background(0);
fill(colors[2]);
rect(20, 20, 460, 460);
translate(width/2, height/2);
def.triang();
def.rect_R1();
def.rect_L1();
def.rect_R2();
def.rect_L2();
def.move();
}
class Deform {
Deform() {
//三角形の位置ベクトル
vec_t[0] = new PVector(r, 0);
vec_t[1] = new PVector(r*cos(i), -r*sin(i));
vec_t[2] = new PVector(-r, 0);
}
void triang() {
fill(colors[4]);
beginShape();
for (int i = 0; i < 3; i++) {
vertex(vec_t[i].x, vec_t[i].y);
}
endShape(CLOSE);
}
void move() {
vec_t[1] = new PVector(r*cos(i), -r*sin(i));
i+= PI/900;
if (i > PI) noLoop();
}
//右上正方形
void rect_R1() {
PVector[] dir1 = new PVector[2];
dir1[0] = PVector.sub(vec_t[1], vec_t[0]);
dir1[1] = PVector.sub(vec_t[0], vec_t[1]);
vec_s1[0] = new PVector(-dir1[0].y+vec_t[0].x, dir1[0].x+vec_t[0].y);
vec_s1[1] = new PVector(dir1[1].y+vec_t[1].x, -dir1[1].x+vec_t[1].y);
fill(colors[0]);
beginShape();
vertex(vec_t[0].x, vec_t[0].y);
vertex(vec_s1[0].x, vec_s1[0].y);
vertex(vec_s1[1].x, vec_s1[1].y);
vertex(vec_t[1].x, vec_t[1].y);
endShape(CLOSE);
line(vec_t[1].x, vec_t[1].y, r*cos(i), 0);//三角形の頂点からの垂線
}
//左上正方形
void rect_L1() {
PVector[] dir2 = new PVector[2];
dir2[0] = PVector.sub(vec_t[1], vec_t[2]);
dir2[1] = PVector.sub(vec_t[2], vec_t[1]);
vec_s2[0] = new PVector(dir2[0].y+vec_t[2].x, -dir2[0].x+vec_t[2].y);
vec_s2[1] = new PVector(-dir2[1].y+vec_t[1].x, dir2[1].x+vec_t[1].y);
fill(colors[3]);
beginShape();
vertex(vec_t[2].x, vec_t[2].y);
vertex(vec_s2[0].x, vec_s2[0].y);
vertex(vec_s2[1].x, vec_s2[1].y);
vertex(vec_t[1].x, vec_t[1].y);
endShape(CLOSE);
}
//右下長方形
void rect_R2() {
fill(colors[0]);
beginShape();
vertex(vec_t[0].x, vec_t[0].y);
vertex(r*cos(i), 0);
vertex(r*cos(i), r*2);
vertex(vec_t[0].x, r*2);
endShape(CLOSE);
}
//左下長方形
void rect_L2() {
fill(colors[3]);
beginShape();
vertex(r*cos(i), 0);
vertex(r*cos(i), r*2);
vertex(vec_t[2].x, r*2);
vertex(vec_t[2].x, vec_t[2].y);
endShape(CLOSE);
}
}
int[] colors = {#E47820,#D62419,#1D684C,#9FBAD6,#F4F7E3}; //オレンジ、赤、緑、青、白
int getCol0() {
return colors[0];
}
int getCol1() {
return colors[1];
}
int getCol2() {
return colors[2];
}
int getCol3() {
return colors[3];
}
int getCol4() {
return colors[4];
}
プログラム(並べた画像)
このプログラムでは一番上の画像のように直角三角形の頂点の動きを右から左に並べたものになります。
PVector[] vec_t = new PVector[3]; //三角形の位置ベクトル
PVector[] vec_s1 = new PVector[2]; //右上の正方形の位置ベクトル
PVector[] vec_s2 = new PVector[4]; //左上の正方形の位置ベクトル
ArrayList<Deform> def = new ArrayList<Deform>();
int tileCount = 3;
float r = 30;//真ん中三角形の底辺の1/2
void setup() {
size(500, 500);
background(0);
//図を左から右へ角度量ごとに並べる
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 3; i++) {
float posX = 480/tileCount * i;
float posY = 480/tileCount * j;
if (j == 0) {
def.add(new Deform(posX+90, posY+90, PI/9*i));
} else if (j == 1) {
def.add(new Deform(posX+90, posY+90, PI/9*i+PI/9*3*j));
} else if (j == 2) {
def.add(new Deform(posX+90, posY+90, PI/6*i+PI/9*3*j));
}
}
}
noLoop();
}
void draw() {
grid();
for (Deform def : def) {
def.triang();
def.rect_R1();
def.rect_L1();
def.rect_R2();
def.rect_L2();
}
powder();
}
void grid() {
for (int j = 0; j <= 490; j+=160) {
for (int i = 0; i <= 490; i+=160) {
stroke(180);
fill(colors[2]);//緑
rect(10+i*2, 10+j*2, 160, 160);
rect(170, 170, 160, 160);
fill(colors[1]);//赤
rect(170, 10+j*2, 160, 160);
rect(10+i*2, 170, 160, 160);
}
}
}
void powder() {
for (int i = 0; i < 800000; i++) {
stroke(random(255), 60);
strokeWeight(0.6);
point(random(width), random(height));
}
}
class Deform {
float px, py, m;
Deform(float px, float py, float m) {
this.px = px;
this.py = py;
this.m = m;
}
void triang() {
//三角形の位置ベクトル
vec_t[0] = new PVector(r, 0);
vec_t[1] = new PVector(r*cos(m), -r*sin(m));
vec_t[2] = new PVector(-r, 0);
pushMatrix();
translate(px, py);
stroke(50);
fill(colors[4]);
beginShape();
for (int i = 0; i < 3; i++) {
vertex(vec_t[i].x, vec_t[i].y);
}
endShape(CLOSE);
popMatrix();
}
//右上正方形
void rect_R1() {
pushMatrix();
translate(px, py);
PVector[] dir1 = new PVector[2];
dir1[0] = PVector.sub(vec_t[1], vec_t[0]);
dir1[1] = PVector.sub(vec_t[0], vec_t[1]);
vec_s1[0] = new PVector(-dir1[0].y+vec_t[0].x, dir1[0].x+vec_t[0].y);
vec_s1[1] = new PVector(dir1[1].y+vec_t[1].x, -dir1[1].x+vec_t[1].y);
fill(colors[0]);
beginShape();
vertex(vec_t[0].x, vec_t[0].y);
vertex(vec_s1[0].x, vec_s1[0].y);
vertex(vec_s1[1].x, vec_s1[1].y);
vertex(vec_t[1].x, vec_t[1].y);
endShape(CLOSE);
line(vec_t[1].x, vec_t[1].y, r*cos(m), 0);//三角形の頂点からの垂線
popMatrix();
}
//左上正方形
void rect_L1() {
pushMatrix();
translate(px, py);
PVector[] dir2 = new PVector[2];
dir2[0] = PVector.sub(vec_t[1], vec_t[2]);
dir2[1] = PVector.sub(vec_t[2], vec_t[1]);
vec_s2[0] = new PVector(dir2[0].y+vec_t[2].x, -dir2[0].x+vec_t[2].y);
vec_s2[1] = new PVector(-dir2[1].y+vec_t[1].x, dir2[1].x+vec_t[1].y);
fill(colors[3]);
beginShape();
vertex(vec_t[2].x, vec_t[2].y);
vertex(vec_s2[0].x, vec_s2[0].y);
vertex(vec_s2[1].x, vec_s2[1].y);
vertex(vec_t[1].x, vec_t[1].y);
endShape(CLOSE);
popMatrix();
}
//右下長方形
void rect_R2() {
pushMatrix();
translate(px, py);
fill(colors[0]);
beginShape();
vertex(vec_t[0].x, vec_t[0].y);
vertex(r*cos(m), 0);
vertex(r*cos(m), r*2);
vertex(vec_t[0].x, r*2);
endShape(CLOSE);
popMatrix();
}
//左下長方形
void rect_L2() {
pushMatrix();
translate(px, py);
fill(colors[3]);
beginShape();
vertex(r*cos(m), 0);
vertex(r*cos(m), r*2);
vertex(vec_t[2].x, r*2);
vertex(vec_t[2].x, vec_t[2].y);
endShape(CLOSE);
popMatrix();
}
}
int[] colors = {#E47820,#D62419,#1D684C,#9FBAD6,#F4F7E3}; //オレンジ、赤、緑、青、白
int getCol0() {
return colors[0];
}
int getCol1() {
return colors[1];
}
int getCol2() {
return colors[2];
}
int getCol3() {
return colors[3];
}
int getCol4() {
return colors[4];
}
参考文献
・美しい幾何学
リンク
・数学から創るジェネラティブアート
リンク
関連記事
Processingおすすめ本
Processingのおすすめ本を紹介します
コメント