Open3

二次元配列による六角格子の表現

みつよしみつよし

概要

平面充填する正六角形のセルでセルオートマトンを実装する際のプログラム的な状態の表現方法

六角にする理由:

正方形によるムーア近傍だと対角線方向と縦横方向に差異があり、方角により"光速"が異なったりとなんとなく本質的でない気がするため

問題点

  1. 二次元配列で表現するとindex計算がずれる
  2. 2セル間の距離の算出がめんどい

最終的に長方形のディスプレイに表示する以上、二次元配列で表現するのは妥当だと思う

みつよしみつよし

1. 二次元配列で表現した際のindex計算

表現

二次元配列に格納する。
このとき、奇数行と偶数行は表示時の位置が半セル分ずれる。

隣接セルの列挙

対象のセルの添字が(x, y)のとき、周囲rセルを列挙する。
まず縦方向(jで表現)は-rからrまで列挙する。
横方向は行によりセル数が異なり、奇数行と偶数行は表示時の位置がずれているため。

    for (let j = -r; j <= r; j += 1) {
      const row = cells[y + j]
      const distanceFromCenter = Math.abs(j)
      const dx = radius - (distanceFromCenter / 2)
      for (let i = -dx; i <= dx; i += 1) {
        const index = j % 2 === 0 ? i : oddRowIndex(i)
        const state = row[x + index] // 隣接セルの状態
      }
    }

    function oddRowIndex(index: number): number {
      if (y % 2 === 0) {
        return index + 0.5
      } else {
        return index - 0.5
      }
    }

添字による状態の取得を cells[y + j]cells[(y + j + cells.length) % cells.length] とすればトーラス状に上下左右を接続できる。
※ 行数が奇数の場合は上下の接続時に半セル分左右がずれる

みつよしみつよし

2. セル間の距離

任意の 2セル間の距離の算出はよくわからない。
どうするの??

隣接セルの列挙中に対象セルからの距離を算出する

上記の隣接セルの列挙処理の相対インデックスをつかって対象セル(x, y)からの距離を算出する。

対象セルから同心円上に存在するセルはおなじ距離をもち、これはrから求められる(下記 distance() )ので

    for (let j = -r; j <= r; j += 1) {
      const row = cells[y + j]
      const distanceFromCenter = Math.abs(j)
      const dx = radius - (distanceFromCenter / 2)
      for (let i = -dx, k = 0; i <= dx; i += 1, k += 1) {
        const index = j % 2 === 0 ? i : oddRowIndex(i)
        const d = distance(k, j) // (x, y)からの距離
      }
    }

    function distance(k: number, j: number): number {
      for (let n = r; n >= 0; n -= 1) {
        if (k === r - n || k === (2 * n - Math.abs(j)) + (r - n) || j === -n || j === n) {
          return n
        }
      }
      return 0
    }