如何创建二维莫比乌斯带、克莱因瓶和投影平面阵列?
How to create two dimensional Möbius strip, Klein bottle and projective plane arrays?
我正在阅读以下关于“Games on Strange Boards”的文章。它描述了各种本地二维数组拓扑结构,例如:
在上图中,具有相同箭头的边以箭头匹配的方式粘合在一起。因此,如果箭头指向相同的方向,则它们正常粘合。但是,如果它们指向不同的方向,那么它们在扭曲后就会粘在一起。
例如,离开圆柱体的右上边缘将使您回到左上边缘。但是,离开莫比乌斯带的右上边缘将使您回到左下边缘。
现在,创建圆柱和环形阵列很容易。您使用模运算使行和列环绕。考虑用于计算具有 m
行和 n
列的环形阵列坐标的代码:
const mod = (x, y) => (x % y + y) % y; // floored division modulo operation
const coords = (m, n) => (i, j) => [mod(i, m), mod(j, n)]; // toroidal array
你会如何计算莫比乌斯带、克莱因瓶或射影平面的坐标?考虑到这些是 non-orientable surfaces,是否有任何特殊情况需要处理?
考虑一个由矩形 sheet 纸制成的圆柱体。 sheet 有两个面,正面和背面。当我们将 sheet 粘合到圆柱体中时,我们无法从正面(圆柱体外部)到达背面(圆柱体内部)。但是,如果我们将 sheet 张纸粘到莫比乌斯带上,那么我们就可以做到。如果我们将两侧分开并展平,莫比乌斯带上的网格会是这样的:
┌────┬────┬────┬────┰────┬────┬────┬────┐
│ a4 │ b4 │ c4 │ d4 ┃ A1 │ B1 │ C1 │ D1 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a3 │ b3 │ c3 │ d3 ┃ A2 │ B2 │ C2 │ D2 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a2 │ b2 │ c2 │ d2 ┃ A3 │ B3 │ C3 │ D3 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a1 │ b1 │ c1 │ d1 ┃ A4 │ B4 │ C4 │ D4 │
└────┴────┴────┴────┸────┴────┴────┴────┘
请注意,左边的方块(即小写的)在前面,而右边的方块(即大写的)在后面。只有大小写不同的正方形是同一个正方形,只是位于莫比乌斯带的相对两侧。需要注意的一件事是,这个扁平的莫比乌斯带很像一个圆柱体,只是左右两侧重合。
莫比乌斯带的代码如下所示:
const mod = (x, y) => (x % y + y) % y;
const coords = (m, n) => (i, j) => {
j = mod(j, 2 * n); // wrapping around like a cylinder
if (j < n) return [i, j]; // front side
return [m - i - 1, j - n]; // back side, translated to front side
};
克莱因瓶与莫比乌斯带完全相同,只是它的行为更像圆环体而不是圆柱体。克莱因瓶的代码如下所示:
const mod = (x, y) => (x % y + y) % y;
const coords = (m, n) => (i, j) => {
i = mod(i, m); // wrapping around
j = mod(j, 2 * n); // like a torus
if (j < n) return [i, j]; // front side
return [m - i - 1, j - n]; // back side, translated to front side
};
射影平面也像环面。但是,它的每一面都可以有两个方向,常规方向和旋转 180°。这是扁平投影平面的样子:
┌────┬────┬────┬────┰────┬────┬────┬────┐
│ a4 │ b4 │ c4 │ d4 ┃ A1 │ B1 │ C1 │ D1 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a3 │ b3 │ c3 │ d3 ┃ A2 │ B2 │ C2 │ D2 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a2 │ b2 │ c2 │ d2 ┃ A3 │ B3 │ C3 │ D3 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a1 │ b1 │ c1 │ d1 ┃ A4 │ B4 │ C4 │ D4 │
┝━━━━┿━━━━┿━━━━┿━━━━╋━━━━┿━━━━┿━━━━┿━━━━┥
│ D4 │ C4 │ B4 │ A4 ┃ d1 │ c1 │ b1 │ a1 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ D3 │ C3 │ B3 │ A3 ┃ d2 │ c2 │ b2 │ a2 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ D2 │ C2 │ B2 │ A2 ┃ d3 │ c3 │ b3 │ a3 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ D1 │ C1 │ B1 │ A1 ┃ d4 │ c4 │ b4 │ a4 │
└────┴────┴────┴────┸────┴────┴────┴────┘
所以,投影平面的代码如下所示:
const mod = (x, y) => (x % y + y) % y;
const coords = (m, n) => (i, j) => {
i = mod(i, 2 * m); // wrapping around
j = mod(j, 2 * n); // like a torus
if (i >= m) { // collapse to Klein bottle topology
i -= m;
j = mod(n - j - 1, 2 * n);
}
if (j < n) return [i, j]; // front side
return [m - i - 1, j - n]; // back side, translated to front side
};
希望对您有所帮助。
我正在阅读以下关于“Games on Strange Boards”的文章。它描述了各种本地二维数组拓扑结构,例如:
在上图中,具有相同箭头的边以箭头匹配的方式粘合在一起。因此,如果箭头指向相同的方向,则它们正常粘合。但是,如果它们指向不同的方向,那么它们在扭曲后就会粘在一起。
例如,离开圆柱体的右上边缘将使您回到左上边缘。但是,离开莫比乌斯带的右上边缘将使您回到左下边缘。
现在,创建圆柱和环形阵列很容易。您使用模运算使行和列环绕。考虑用于计算具有 m
行和 n
列的环形阵列坐标的代码:
const mod = (x, y) => (x % y + y) % y; // floored division modulo operation
const coords = (m, n) => (i, j) => [mod(i, m), mod(j, n)]; // toroidal array
你会如何计算莫比乌斯带、克莱因瓶或射影平面的坐标?考虑到这些是 non-orientable surfaces,是否有任何特殊情况需要处理?
考虑一个由矩形 sheet 纸制成的圆柱体。 sheet 有两个面,正面和背面。当我们将 sheet 粘合到圆柱体中时,我们无法从正面(圆柱体外部)到达背面(圆柱体内部)。但是,如果我们将 sheet 张纸粘到莫比乌斯带上,那么我们就可以做到。如果我们将两侧分开并展平,莫比乌斯带上的网格会是这样的:
┌────┬────┬────┬────┰────┬────┬────┬────┐
│ a4 │ b4 │ c4 │ d4 ┃ A1 │ B1 │ C1 │ D1 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a3 │ b3 │ c3 │ d3 ┃ A2 │ B2 │ C2 │ D2 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a2 │ b2 │ c2 │ d2 ┃ A3 │ B3 │ C3 │ D3 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a1 │ b1 │ c1 │ d1 ┃ A4 │ B4 │ C4 │ D4 │
└────┴────┴────┴────┸────┴────┴────┴────┘
请注意,左边的方块(即小写的)在前面,而右边的方块(即大写的)在后面。只有大小写不同的正方形是同一个正方形,只是位于莫比乌斯带的相对两侧。需要注意的一件事是,这个扁平的莫比乌斯带很像一个圆柱体,只是左右两侧重合。
莫比乌斯带的代码如下所示:
const mod = (x, y) => (x % y + y) % y;
const coords = (m, n) => (i, j) => {
j = mod(j, 2 * n); // wrapping around like a cylinder
if (j < n) return [i, j]; // front side
return [m - i - 1, j - n]; // back side, translated to front side
};
克莱因瓶与莫比乌斯带完全相同,只是它的行为更像圆环体而不是圆柱体。克莱因瓶的代码如下所示:
const mod = (x, y) => (x % y + y) % y;
const coords = (m, n) => (i, j) => {
i = mod(i, m); // wrapping around
j = mod(j, 2 * n); // like a torus
if (j < n) return [i, j]; // front side
return [m - i - 1, j - n]; // back side, translated to front side
};
射影平面也像环面。但是,它的每一面都可以有两个方向,常规方向和旋转 180°。这是扁平投影平面的样子:
┌────┬────┬────┬────┰────┬────┬────┬────┐
│ a4 │ b4 │ c4 │ d4 ┃ A1 │ B1 │ C1 │ D1 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a3 │ b3 │ c3 │ d3 ┃ A2 │ B2 │ C2 │ D2 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a2 │ b2 │ c2 │ d2 ┃ A3 │ B3 │ C3 │ D3 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ a1 │ b1 │ c1 │ d1 ┃ A4 │ B4 │ C4 │ D4 │
┝━━━━┿━━━━┿━━━━┿━━━━╋━━━━┿━━━━┿━━━━┿━━━━┥
│ D4 │ C4 │ B4 │ A4 ┃ d1 │ c1 │ b1 │ a1 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ D3 │ C3 │ B3 │ A3 ┃ d2 │ c2 │ b2 │ a2 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ D2 │ C2 │ B2 │ A2 ┃ d3 │ c3 │ b3 │ a3 │
├────┼────┼────┼────╂────┼────┼────┼────┤
│ D1 │ C1 │ B1 │ A1 ┃ d4 │ c4 │ b4 │ a4 │
└────┴────┴────┴────┸────┴────┴────┴────┘
所以,投影平面的代码如下所示:
const mod = (x, y) => (x % y + y) % y;
const coords = (m, n) => (i, j) => {
i = mod(i, 2 * m); // wrapping around
j = mod(j, 2 * n); // like a torus
if (i >= m) { // collapse to Klein bottle topology
i -= m;
j = mod(n - j - 1, 2 * n);
}
if (j < n) return [i, j]; // front side
return [m - i - 1, j - n]; // back side, translated to front side
};
希望对您有所帮助。