# 來到 3D 海龜繪圖

``````function x(pt) = pt[0];
function y(pt) = pt[1];
function z(pt) = pt[2];

function pt3D(x, y, z) = [x, y, z];

function turtle3D(pt, coordVt) = [pt, coordVt];
function getPt(turtle) = turtle[0];
function getCoordVt(turtle) = turtle[1];

function plus(pt, n) = pt3D(x(pt) + n, y(pt) + n, z(pt) + n);
function minus(pt, n) = pt3D(x(pt) - n, y(pt) - n, z(pt) + n);
function mlt(pt, n) = pt3D(x(pt) * n, y(pt) * n, z(pt) * n);
function div(pt, n) = pt3D(x(pt) / n, y(pt) / n, z(pt) / n);
function neg(pt, n) = mlt(pt, -1);

function ptPlus(pt1, pt2) = pt3D(x(pt1) + x(pt2), y(pt1) + y(pt2), z(pt1) + z(pt2));

// 在海龜的 x' 軸方向移動
function moveX(turtle, leng) = turtle3D(
ptPlus(getPt(turtle), mlt(getCoordVt(turtle)[0], leng)),
getCoordVt(turtle)
);

// 在海龜的 y' 軸方向移動
function moveY(turtle, leng) = turtle3D(
ptPlus(getPt(turtle), mlt(getCoordVt(turtle)[1], leng)),
getCoordVt(turtle)
);

// 在海龜的 z' 軸方向移動
function moveZ(turtle, leng) = turtle3D(
ptPlus(getPt(turtle), mlt(getCoordVt(turtle)[2], leng)),
getCoordVt(turtle)
);

// 繞海龜的 x' 軸轉動，計算 x' 方向單位向量
function turnX(turtle, a) = turtle3D(
getPt(turtle),
[
getCoordVt(turtle)[0],
ptPlus(mlt(getCoordVt(turtle)[1], cos(a)), mlt(getCoordVt(turtle)[2], sin(a))),
ptPlus(mlt(neg(getCoordVt(turtle)[1]), sin(a)), mlt(getCoordVt(turtle)[2], cos(a)))
]
);

// 繞海龜的 y' 軸轉動，計算 y' 方向單位向量
function turnY(turtle, a) = turtle3D(
getPt(turtle),
[
ptPlus(mlt(getCoordVt(turtle)[0], cos(a)), mlt(neg(getCoordVt(turtle)[2]), sin(a))),
getCoordVt(turtle)[1],
ptPlus(mlt(getCoordVt(turtle)[0], sin(a)), mlt(getCoordVt(turtle)[2],cos(a)))
]
);

// 繞海龜的 z' 軸轉動，計算 z' 方向單位向量
function turnZ(turtle, a) = turtle3D(
getPt(turtle),
[
ptPlus(mlt(getCoordVt(turtle)[0], cos(a)), mlt(getCoordVt(turtle)[1],sin(a))),
ptPlus(mlt(neg(getCoordVt(turtle)[0]), sin(a)), mlt(getCoordVt(turtle)[1], cos(a))),
getCoordVt(turtle)[2],
]
);

// 3D 線段
module line3D(p1, p2, thickness, fn = 24) {
\$fn = fn;

hull() {
translate(p1) sphere(thickness / 2);
translate(p2) sphere(thickness / 2);
}
}

// 根據多個點繪製 3D 線段
module polyline3D(points, thickness, fn) {
module polyline3D_inner(points, index) {
if(index < len(points)) {
line3D(points[index - 1], points[index], thickness, fn);
polyline3D_inner(points, index + 1);
}
}

polyline3D_inner(points, 1);
}

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)] // 海龜座標單位向量
);

leng = 10;

t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], 1 , 4);

t3 = moveX(turnZ(t2, 120), leng);
polyline3D([getPt(t2), getPt(t3)], 1 , 4);

t4 = moveX(turnZ(t3, 120), leng);
polyline3D([getPt(t3), getPt(t4)], 1 , 4);
``````

``````程式碼同前...略…

leng = 10;

t2 = moveX(turnX(t, 30), leng); // 只要改這邊，先繞 x' 軸轉 30 度就可以了
polyline3D([getPt(t), getPt(t2)], 1 , 4);

t3 = moveX(turnZ(t2, 120), leng);
polyline3D([getPt(t2), getPt(t3)], 1 , 4);

t4 = moveX(turnZ(t3, 120), leng);
polyline3D([getPt(t3), getPt(t4)], 1 , 4);
``````