我在看下面关于“Games on Strange Boards”的文章。它描述了各种本地二维阵列拓扑,例如:
Cylinder
arrays - 如何创建二维莫比乌斯带,克莱因瓶和射影平面阵列?-LMLPHP
Torus
arrays - 如何创建二维莫比乌斯带,克莱因瓶和射影平面阵列?-LMLPHP
Möbius strip
arrays - 如何创建二维莫比乌斯带,克莱因瓶和射影平面阵列?-LMLPHP
Klein bottle
arrays - 如何创建二维莫比乌斯带,克莱因瓶和射影平面阵列?-LMLPHP
Projective plane
arrays - 如何创建二维莫比乌斯带,克莱因瓶和射影平面阵列?-LMLPHP
在上面的图表中,具有相同箭头的边以箭头匹配的方式粘在一起因此,如果箭头指向同一方向,则它们将正常粘合但是,如果它们指向不同的方向,那么它们在扭曲后被粘合。
例如,从圆柱体的右上边缘移开将使您返回到左上边缘但是,从móbius条的右上边缘移动会将您包裹回左下边缘。
现在,创建圆柱形和环形阵列很容易。使用模操作使行和列环绕。考虑用于计算具有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,有什么特殊情况需要处理吗?

最佳答案

假设一个圆柱体是由一张长方形的纸制成的床单有两面,正面和背面。当我们把纸粘到圆筒里时,我们不能从正面(圆筒外面)到背面(圆筒里面)。然而,如果我们把这张纸粘到一条莫比乌斯带上,我们就可以了如果我们将两边分开并将其展平,那么Móbius条带上的网格看起来会是这样的:

 ┌────┬────┬────┬────┰────┬────┬────┬────┐
 │ 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 │
 └────┴────┴────┴────┸────┴────┴────┴────┘

注意左边的正方形(即小写的)在前面,而右边的正方形(即大写的)在后面。只有大小写差异的正方形是相同的正方形,仅位于móbius条的对边上。需要注意的一点是,这条扁平的莫比斯带很像一个圆柱体,只是左右两边重合。
下面是莫比斯脱衣舞的代码:
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
};

希望能有所帮助。

关于arrays - 如何创建二维莫比乌斯带,克莱因瓶和射影平面阵列?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53087240/

10-10 15:57