【问题标题】:How to create two dimensional Möbius strip, Klein bottle and projective plane arrays?如何创建二维莫比乌斯带、克莱因瓶和投影平面阵列?
【发布时间】:2019-04-04 20:22:12
【问题描述】:

我正在阅读以下有关“Games on Strange Boards”的文章。它描述了各种局部二维数组拓扑,例如:

  1. Cylinder

  2. Torus

  3. Möbius strip

  4. Klein bottle

  5. Projective plane

在上图中,具有相同箭头的边以它们箭头匹配的方式粘合在一起。因此,如果箭头指向相同的方向,则它们是正常粘合的。但是,如果它们指向不同的方向,那么它们会在扭曲后粘上。

例如,从圆柱体的右上边缘移开会使您回到左上边缘。但是,从莫比乌斯带的右上边缘移开会使您回到左下边缘。

现在,创建圆柱形和环形阵列很容易。您使用模运算使行和列环绕。考虑计算具有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,是否有任何特殊情况需要处理?

【问题讨论】:

    标签: arrays algorithm math data-structures topology


    【解决方案1】:

    考虑一个由矩形纸制成的圆柱体。片材有两个侧面,正面和背面。当我们将片材粘成圆柱体时,我们无法从正面(圆柱体外部)到达背面(圆柱体内部)。但是,如果我们将这张纸粘成莫比乌斯带,那么我们可以。如果我们将两侧分开并将其展平,这就是莫比乌斯带上的网格的样子:

     ┌────┬────┬────┬────┰────┬────┬────┬────┐
     │ 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
    };
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2020-05-16
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多