# Theta 迷宮

March 26, 2022

## 基於方形迷宮變化

``````use <polyline_join.scad>

rows = 36;
columns = 5;
cell_width = 2;
thickness = 1;

leng = rows * cell_width;
radius = 0.5 * leng / PI;
a_step = 360 / leng;

cells = mz_square(rows, columns, y_wrapping = true);
walls = mz_squarewalls(cells, cell_width, bottom_border = false);

size = [columns, rows] * cell_width;
for(wall_pts = walls) {
transformed = [for(pt = wall_pts) ptf_ring(size, pt, radius)];
polyline_join(transformed)
circle(d = thickness);
}
``````

## 動態切分細胞

dotSCAD 的 `mz_theta` 實現了動態切分細胞，而後建立迷宮的演算，可以指定迷宮的環數，以及第一環要有幾個細胞，傳回的資料會是二維的 list，每一環的細胞數不一定相同，若迷宮資料是 `maze``maze[i]` 就是 i 環的細胞資料，想要知道該環有多少細胞？那就是 `len(maze[i])` 了。

``````use <maze/mz_theta.scad>

rings = 8;
beginning_number = 8;
cell_width = 10;
thickness = 2;

maze = mz_theta(rings, beginning_number);
for(ring = maze) {
thetaStep = 360 / len(ring);        //  該環細胞的張角
for(cell = ring) {
r = mz_theta_get(cell, "r");    // 由內往外第 r 環
c = mz_theta_get(cell, "c");    // 逆時針的第 c 個
type = mz_theta_get(cell, "t"); // 牆面類型
...看你怎麼畫圖囉...
}
}
``````

`type` 表示細胞牆面會是 `"NO_WALL"`（無牆）、`"INWARD_WALL"`（內牆）、`"CCW_WALL"`（逆時針牆） 或 `"INWARD_CCW_WALL"`（內牆與逆時針牆）：

``````module drawWall(r, c, type, thetaStep, thickness) {
function vt_from_angle(theta, r) = [r * cos(theta), r * sin(theta)];

innerR = (r + 1) * cell_width;
outerR = (r + 2) * cell_width;
theta1 = thetaStep * c;
theta2 = thetaStep * (c + 1);

innerVt1 = vt_from_angle(theta1, innerR);
innerVt2 = vt_from_angle(theta2, innerR);
outerVt2 = vt_from_angle(theta2, outerR);

if(type == "INWARD_WALL" || type == "INWARD_CCW_WALL") {
polyline_join([innerVt1, innerVt2])
circle(d = thickness);
}

if(type == "CCW_WALL" || type == "INWARD_CCW_WALL") {
polyline_join([innerVt2, outerVt2])
circle(d = thickness);
}
}
``````

``````use <maze/mz_theta.scad>

rings = 8;
beginning_number = 8;
cell_width = 10;
thickness = 2;

maze = mz_theta(rings, beginning_number);
for(ring = maze) {
thetaStep = 360 / len(ring);
for(cell = ring) {
r = mz_theta_get(cell, "r");
c = mz_theta_get(cell, "c");
type = mz_theta_get(cell, "t");
drawWall(r, c, type, thetaStep, thickness);
}
}

// 最外圍的牆
r = cell_width * (rings + 1);
hollow_out(thickness)
offset(thickness)
circle(r, \$fn = len(maze[rings - 1]));

module drawWall(r, c, type, thetaStep, thickness) {
function vt_from_angle(theta, r) = [r * cos(theta), r * sin(theta)];

innerR = (r + 1) * cell_width;
outerR = (r + 2) * cell_width;
theta1 = thetaStep * c;
theta2 = thetaStep * (c + 1);

innerVt1 = vt_from_angle(theta1, innerR);
innerVt2 = vt_from_angle(theta2, innerR);
outerVt2 = vt_from_angle(theta2, outerR);

if(type == "INWARD_WALL" || type == "INWARD_CCW_WALL") {
polyline_join([innerVt1, innerVt2])
circle(d = thickness);
}

if(type == "CCW_WALL" || type == "INWARD_CCW_WALL") {
polyline_join([innerVt2, outerVt2])
circle(d = thickness);
}
}
``````