らせん
提供:kuhalaboWiki
(版間での差分)
(→再帰的な描画と対数らせん) |
(→再帰的な描画と対数らせん) |
||
77行: | 77行: | ||
=== 再帰的な描画と対数らせん === | === 再帰的な描画と対数らせん === | ||
− | * ベクトル操作:(x,y)の2つの値を1まとめに扱う。位置や運動を整理して扱うことができる。[https://funacchi.qrunch.io/entries/ZlygjgxrGamwt2fz 参考サイト](閉鎖されました) | + | * ベクトル操作:(x,y)の2つの値を1まとめに扱う。位置や運動を整理して扱うことができる。 |
+ | ** [https://funacchi.qrunch.io/entries/ZlygjgxrGamwt2fz 参考サイト](閉鎖されました) | ||
** PVector https://processing.org/reference/PVector.html | ** PVector https://processing.org/reference/PVector.html | ||
** https://processing.org/tutorials/pvector/ | ** https://processing.org/tutorials/pvector/ |
2020年11月3日 (火) 06:42時点における版
- 自然界のらせん(渦巻き)
- 巻貝の貝殻
- 台風
- 銀河の星の渦
- ひまわりの種の配列
- 座標系
- 3種のらせん
- アルキメデスらせん
- フェルマーらせん
- 対数らせん
- らせんの描画
float theta = 0; float STEP = 2 * PI * 0.01; //曲線の精度(2*PI = 360度)を100等分 void setup(){ size(500, 500); } void draw(){ translate(width / 2, height / 2); //描画ウィンドウの中心に移動 line(rad(theta) * cos(theta), rad(theta) * sin(theta), rad(theta + STEP) * cos(theta + STEP), rad(theta + STEP) * sin(theta + STEP)); theta += STEP; } float rad(float t){ //動径を定める関数 float r = 5 * t; //アルキメデスらせん //float r = 20 * sqrt(t); //フェルマーらせん // float r = pow(1.1, t); //対数らせん return(r); }
- PIは円周率で3.14159265…
- rad() 角度を度数法から弧度法に変換する。参考サイト
- pow(x,a) べき乗の計算 xのa乗
- sqrt() は平方根
- 自己相似な対数らせん
float STEP = 2 * PI * 0.01; //曲線の精度 void setup(){ size(500, 500); colorMode(HSB, 1); } void draw(){ background(1,0,1); drawLogSpiral(); //対数らせんを描画 }
void drawLogSpiral(){ float theta = 0; float scalar = pow(10, (float) mouseX / width) * height / 2; //マウスのx座標によって1~10倍に拡大する translate(width / 2, height / 2); //描画ウィンドウの中心に移動 for(int i = 0; i < 2000; i++){ line(scalar * rad(theta) * cos(theta), scalar * rad(theta) * sin(theta), scalar * rad(theta + STEP) * cos(theta + STEP), scalar * rad(theta + STEP) * sin(theta + STEP)); theta -= STEP; //反時計回りに進むほど動径は減少する } } float rad(float t){ //動径を定める関数 float r = pow(1.1, t); return(r); }
- mouseX マウスのX座標
再帰的な描画と対数らせん
- ベクトル操作:(x,y)の2つの値を1まとめに扱う。位置や運動を整理して扱うことができる。
正方形の中に正方形を再帰的に描く
PVector[] vec; //PVector型の配列を宣言 float gap = 0.01; //内接する正方形のずれ void setup(){ size(500, 500); vec = new PVector[4]; //正方形の4つの頂点をベクトルとして生成 vec[0] = new PVector(0, 0); //ウィンドウ左上の角 vec[1] = new PVector(width, 0); //ウィンドウ右上の角 vec[2] = new PVector(width, height); //ウィンドウ右下の角 vec[3] = new PVector(0, height); //ウィンドウ左下の角 } void draw(){ drawSquare(vec); //4つのベクトルを頂点とする四角形を描画 vec = getVector(vec); //ベクトルをgapの分だけずらす }
void drawSquare(PVector[] v){ for(int i = 0; i < 4; i++){ line(v[i].x, v[i].y, v[(i + 1) % 4].x, v[(i + 1) % 4].y); //頂点v[i]と頂点v[i+1]のx座標とy座標の値を取りだし,線分を描く } }
PVector[] getVector(PVector[] vec){ PVector[] nextVec = new PVector[4]; for(int i = 0; i < 4; i++){ PVector dir = PVector.sub(vec[(i + 1) % 4], vec[i]); //2頂点間の方向ベクトル dir.mult(gap); //ずれの分を方向ベクトルにかける nextVec[i] = PVector.add(vec[i], dir); //元の頂点の位置ベクトルをずらして新たなベクトルを作る } return(nextVec); }
- %は割り算のあまり。9%4=1 (9を4で割るとあまり1)
- 頂点は0,1,2,3なので、3の次は、3+1=4になるが、4で割った余りを考えると4%4=0となる。あまり(剰余系)を使うと、0,1,2,3,0,1,2,3…の循環を表せる。
- v[i].xはベクトルv[i]のx座標
- v[i].yはベクトルv[i]のy座標
- .add(a,b)はベクトルの足し算
- .sub(a,b)はベクトルの引き算
- .mult(a)はベクトルの掛け算
void mouseClicked(){ background(255); gap = random(1) / 2; println("gap =", gap); vec[0] = new PVector(0, 0); vec[1] = new PVector(width, 0); vec[2] = new PVector(width, height); vec[3] = new PVector(0, height); }
- 多角形に拡張する。
- PVector fromAngle : 指定した角度(ラジアン)の傾きを持つ単位ベクトル(大きさ1)を返す。
PVector[] vec; //PVector型の配列を宣言 float gap = 0.1; //内接する正多角形のずれ int gon = 8; //正多角形の頂点の数 void setup(){ size(500, 500); vec = new PVector[gon]; for(int i = 0; i < gon; i++){ //正多角形の頂点の位置ベクトル vec[i] = PVector.fromAngle(2 * i * PI / gon); vec[i].mult(width / 2); } } void draw(){ translate(width / 2, height / 2); //描画ウィンドウの中心に移動 drawPolygon(vec); vec = getVector(vec); }
void drawPolygon(PVector[] v){ for(int i = 0; i < gon; i++){ line(v[i].x, v[i].y, v[(i + 1) % gon].x, v[(i + 1) % gon].y); } }
PVector[] getVector(PVector[] v){ PVector[] nextVec = new PVector[gon]; for(int i = 0; i < gon; i++){ PVector dir = PVector.sub(v[(i + 1) % gon], v[i]); dir.mult(gap); nextVec[i] = PVector.add(v[i], dir); } return nextVec; }
void mouseClicked(){ gap = random(1) / 2; gon = int(random(4, 16)); background(255); vec = new PVector[gon]; for(int i = 0; i < gon; i++){ //正多角形の頂点の位置ベクトル vec[i] = PVector.fromAngle(2 * i * PI / gon); vec[i].mult(width / 2); } }
フェルマーらせん
- 離散的らせん
- 回転角
- 有理数
- 1/2,1/3,1/5,1/10,1/20,1/40
- /61
- / 72
- / 17
- / 305
- / 109
- / 360
- 17/55
- 無理数
- sqrt(5)
- 黄金比
- 円周率
- 有理数
int itr = 0; //描画の繰り返し回数 float scalar = 5; //拡大倍率 float rotation; void setup() { size(500, 500); background(255); //背景を白くする rotation = 17.0 / 55; // rotation = sqrt(5); // rotation = (1 + sqrt(5)) / 2; } void draw() { translate(width / 2, height / 2); //描画ウィンドウの中心に移動 fill(0); //点を黒く塗る drawFermatSpiral(rotation); //引数を回転角とするフェルマーらせんの描画 itr++; } void drawFermatSpiral(float rot){ float theta = 2 * PI * itr * rot; //回転角 PVector v = PVector.fromAngle(theta); v.mult(scalar * sqrt(itr)); ellipse(v.x, v.y, scalar, scalar); //点を描画 }
複数の離散的らせん
int itr = 0; //描画の繰り返し回数 float scalar = 5; //拡大倍率 void setup() { size(500, 500); background(255); } void draw() { translate(width / 2, height / 2); //描画ウィンドウの中心に移動 noStroke(); fill(255, 0, 0, 127); //点を赤く塗る drawFermatSpiral(4.0 / 17); fill(0, 0, 255, 127); //点を青く塗る drawFermatSpiral(17.0 / 72); fill(0, 255, 0, 127); //点を緑に塗る drawFermatSpiral(72.0 / 305); itr++; } void drawFermatSpiral(float rot){ float theta = 2 * PI * itr * rot; //回転角 PVector v = PVector.fromAngle(theta); v.mult(scalar * sqrt(itr)); ellipse(v.x, v.y, scalar, scalar); //点を描画 }