我們繼續上一個單元 p5.js 實戰演練(二) –– 疊合公轉軸(二) 的實驗。
若仔細思索就會發現,當我們繪製完其中一個小公轉軸,只依靠 rotate(-outer_orbit_speed);
是沒辦法完全把座標軸校正回來的。
因為繪製小公轉軸的所有動作:
// 步驟 1-1:定位小公轉軸 1 的軸心
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 1-2:繪製沿著小公轉軸 1 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
實際上包含了四次的座標轉換,分別是:
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed);
rotate(inner_orbit_speed);
那我們就必須分別對這四次的座標轉換反向校正回來。
我們可以用 p5.js 基礎教學(三) -- 繪製座標格線 的成果,繪製座標格線來實驗校正結果。
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
var gridSpacing = 50; // 設定每 50 px 就畫一條格線
function createGrid() {
for (var x = -width; x < width; x += gridSpacing) {
for (var y = -height; y < height; y += gridSpacing) {
stroke(200); // 設定線的顏色為灰色
strokeWeight(1); // 設定線的寬度為1
line(x, -height, x, height); // 畫出垂直線
line(-width, y, width, y); // 畫出水平線
}
}
}
function draw() {
background(100, 100);
translate(width/2, height/2);
var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
var inner_orbit_speed = frameCount/60/3 * 2 * PI;
// 步驟 1-1:定位小公轉軸 1 的軸心
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 1-2:繪製沿著小公轉軸 1 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 繪製格線
createGrid();
}
這是無校正版本,座標系統會同時繞著小公轉軸和大公轉軸旋轉。
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
var gridSpacing = 50; // 設定每 50 px 就畫一條格線
function createGrid() {
for (var x = -width; x < width; x += gridSpacing) {
for (var y = -height; y < height; y += gridSpacing) {
stroke(200); // 設定線的顏色為灰色
strokeWeight(1); // 設定線的寬度為1
line(x, -height, x, height); // 畫出垂直線
line(-width, y, width, y); // 畫出水平線
}
}
}
function draw() {
background(100, 100);
translate(width/2, height/2);
var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
var inner_orbit_speed = frameCount/60/3 * 2 * PI;
// 步驟 1-1:定位小公轉軸 1 的軸心
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 1-2:繪製沿著小公轉軸 1 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 只校正小公轉軸 rotate 函數
rotate(-inner_orbit_speed);
// 繪製格線
createGrid();
}
這版本的座標網格已經校正了小公轉軸的變化,但依然繞著大公轉軸旋轉。
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
var gridSpacing = 50; // 設定每 50 px 就畫一條格線
function createGrid() {
for (var x = -width; x < width; x += gridSpacing) {
for (var y = -height; y < height; y += gridSpacing) {
stroke(200); // 設定線的顏色為灰色
strokeWeight(1); // 設定線的寬度為1
line(x, -height, x, height); // 畫出垂直線
line(-width, y, width, y); // 畫出水平線
}
}
}
function draw() {
background(100, 100);
translate(width/2, height/2);
var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
var inner_orbit_speed = frameCount/60/3 * 2 * PI;
// 步驟 1-1:定位小公轉軸 1 的軸心
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 1-2:繪製沿著小公轉軸 1 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 校正小公轉軸 rotate 函數和大公轉軸 translate 函數
rotate(-inner_orbit_speed);
translate(-200, 0);
// 繪製格線
createGrid();
}
如果只對大公轉軸的 translate 做校正是沒用的,因為原本的 translate(200, 0);
就是由 rotate(outer_orbit_speed);
疊加上去的,必須兩個都進行校正。
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
var gridSpacing = 50; // 設定每 50 px 就畫一條格線
function createGrid() {
for (var x = -width; x < width; x += gridSpacing) {
for (var y = -height; y < height; y += gridSpacing) {
stroke(200); // 設定線的顏色為灰色
strokeWeight(1); // 設定線的寬度為1
line(x, -height, x, height); // 畫出垂直線
line(-width, y, width, y); // 畫出水平線
}
}
}
function draw() {
background(100, 100);
translate(width/2, height/2);
var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
var inner_orbit_speed = frameCount/60/3 * 2 * PI;
// 步驟 1-1:定位小公轉軸 1 的軸心
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 1-2:繪製沿著小公轉軸 1 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 對四個座標轉換做校正
rotate(-inner_orbit_speed);
rotate(outer_orbit_speed);
translate(-200, 0);
rotate(-outer_orbit_speed);
// 繪製格線
createGrid();
}
棒棒!我們對所有動作都進行反向校正之後,就可以讓座標系統維持最原始的樣子了。
我們用剛剛實驗的結果來校正原本的作品。
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
function draw() {
background(100, 100);
translate(width/2, height/2);
var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
var inner_orbit_speed = frameCount/60/3 * 2 * PI;
// 步驟 1-1:定位小公轉軸 1 的軸心
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 1-2:繪製沿著小公轉軸 1 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 對四個座標轉換做校正
rotate(-inner_orbit_speed);
rotate(outer_orbit_speed);
translate(-200, 0);
rotate(-outer_orbit_speed);
// 步驟 2-1:定位小公轉軸 2 的軸心
rotate(outer_orbit_speed);
translate(0, 200);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 2-2:繪製沿著小公轉軸 2 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 對四個座標轉換做校正
rotate(-inner_orbit_speed);
rotate(outer_orbit_speed);
translate(0, -200);
rotate(-outer_orbit_speed);
// 步驟 3-1:定位小公轉軸 3 的軸心
rotate(outer_orbit_speed);
translate(-200, 0);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 3-2:繪製沿著小公轉軸 3 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 對四個座標轉換做校正
rotate(-inner_orbit_speed);
rotate(outer_orbit_speed);
translate(200, 0);
rotate(-outer_orbit_speed);
// 步驟 4-1:定位小公轉軸 4 的軸心
rotate(outer_orbit_speed);
translate(0, -200);
rotate(-outer_orbit_speed); // 校正 rotate 函數對座標系統的轉動
// 步驟 4-2:繪製沿著小公轉軸 4 繞行的 4 個 circle
rotate(inner_orbit_speed);
circle(100, 0, 20);
circle(-100, 0, 20);
circle(0, 100, 20);
circle(0, -100, 20);
// 對四個座標轉換做校正
rotate(-inner_orbit_speed);
rotate(outer_orbit_speed);
translate(0, 200);
rotate(-outer_orbit_speed);
}
這是軌跡版本:
到這邊我們終於得到預期結果了,同時大公轉軸和小公轉軸都有四個對象在做圓周運動。