六角形グリッドの範囲内のセルを見つける


8

最初に-私はここで超高密度になっていることを知っています。

これで、このアルゴリズムのC#実装を記述しようとしています。

var results = []
for each -N  dx  N:
  for each max(-N, -dx-N)  dy  min(N, -dx+N):
    var dz = -dx-dy
    results.append(cube_add(center, Cube(dx, dy, dz)))

私はこの途方もないリソースからこれを取得しました。

私の問題は、これまでに試したすべての実装で、すばらしい結果が得られたことです。たとえば、以下に示すコードは現在、この結果になります。

1

この:

2

私のコードは現在次のようになっています:

for (int x = this.CellPositionX - distance; x <= this.CellPositionX + distance; x++)
    {
        for (int y = this.CellPositionY - Math.Max(-distance, -x - distance); y <= this.CellPositionY + Math.Min(distance, -x + distance); y++)
        {
            HexPosition rangePosition = new HexPosition(x, y);
            range.Add(rangePosition);
        }
    }

誰かがここで何かがおかしいのを発見できますか?すべての提案を歓迎します。私はしばらくの間、これに頭をぶつけてきました。

ありがとう!

更新されたメモ:グリッドで軸座標を使用しています。アップデート#2:以下で指摘するように、for..eachループが間違っていて、ワークアウトにデルタを使用していませんでした。助けてくれてありがとう!

私は現在、回答からの実装で以下に示すような問題を抱えています: ここに画像の説明を入力してください

私は調査を続けます-もし私がそれを見つけたら、私はここにすべての結果を投稿します。皆さんありがとう!


1
そのリソースをありがとう、それは本当によく見えます!ほとんどすべてのグラフィックスが操作可能であることに気付いたとき、私は少し驚いてしまいました。:)
Christer

3
彼の例ではキューブ座標を使用していますが、オフセット座標または軸座標を使用しているようです。x、y、zを3次座標から、使用している座標系に変換する必要があります。
Alex Sherman、

1
@ Vector57アキシャルを使用しています。変換セクションから、Zプロパティを使用して何もする必要がないこと、およびq / rとx / yは交換可能であると記載されています...またはそれを誤解していますか?
aaron-bond 2016

それはそのように見えますが、例では彼はr = zを使用していますが、なぜあなたがどちらを選択するかが重要である理由がわかりません。
Alex Sherman

回答:


4

したがって、さらに調査すると、問題は実際には座標系変換とは関係ありません。これは、軸座標XとYではなくQとRに名前を付けることで、より明確になる可能性があります。実際に発生している問題は、ループ状態が悪いことです。元のコードサンプルはデルタqとrを生成します。これをforループで絶対座標に変換しようとして、ミスをしました。アルゴリズムは、代わりに次のようになります。

for (int dx = -distance; dx <= distance; dx++)
{
    for (int dy = Math.Max(-distance, -dx - distance); dy <= Math.Min(distance, -dx + distance); dy++)
    {
        HexPosition rangePosition = new HexPosition(
            this.CellPositionX + dx, this.CellPositionY + dy);
        range.Add(rangePosition);
    }
}

ああderp ...記事には、それらがデルタ値であることも記載されています:(これを今すぐ試してみて、どうなるかを確認してください。ありがとう:)
aaron-bond

これをありがとう。それは間違いなくそれを行う正しい方法にかなり近いです。私はまだ座標をめちゃくちゃにしていますが、少なくとも私は正しい数を持っています!何らかの理由で、-xでは1つのセルが高すぎ、+ xでは1つのセルが低すぎます。あなたがそれについて何か知っているなら私は写真を上に掲載しましたが、とにかく私は自分自身を調査し続けます:)あなたの助けに感謝します!
aaron-bond 2016

軸座標を正しく解釈していますか?xとzではなくxとyを使用することを選択したことを忘れないでください。コードの残りの部分が例からのこの変更を考慮しない場合、奇妙な動作になる可能性があります。
Alex Sherman

はい、xとzになるように切り替えました。dxはxになり、z = -dx-dy ...
aaron-bond

1
あなたが投稿した新しい写真では、7ヘクスが強調表示されています。これは、distance = 1で予想されるものです。値を印刷してみてください。CellPositionを0,0および距離1に設定すると、取得するヘクスは(-1、0)になります。(-1、1); (0、-1); (0、0); (0、1); (1、-1); (1、0)
amitp

7

以下のようVector57は指摘し、問題は、使用しているで間違った座標系。説明されているアルゴリズムは、x、y、zコンポーネントを持つキューブ座標で使用することを目的としています

キューブ座標

これはアルゴリズムの疑似コードからは明らかではないかもしれませんが、これこれを単純化しているためです。

var results = []
for each -N  dx  N:
    for each -N  dy  N:
        for each -N  dz  N:
            if dx + dy + dz = 0:
                results.append(cube_add(center, Cube(dx, dy, dz)))

... x、y、zに対する単純なネストループ。範囲アルゴリズムに期待されるもの。

使用している座標系はわかりませんが、これは「オフセット座標系」の1つだと思います。これは、グリッドセルを2D配列内に配置することで簡単に実装できるため、人気があります。

オフセットq垂直レイアウト

これは、これらのキューブアルゴリズムを使用できないという意味ではありません。それは単にあなたが立方体座標からあなた自身のもの変換する必要があることを意味します。たとえば、「odd-q」縦型レイアウトとの間で変換するには、以下を使用します。

# convert cube to odd-q offset
col = x
row = z + (x - (x&1)) / 2

# convert odd-q offset to cube
x = col
z = row - (col - (col&1)) / 2
y = -x-z

こんな感じでした。CubeからAxialへの変換について言及していて、z部分を削除するだけで残りのqとrがxとyになるページの一部がありました。私はそこで単純化しすぎたに違いないと思います。これをありがとう。私が欠けていたものの優れた説明。後でやってみます!:)
aaron-bond 2016

私は見たばかりで、アキシャルを使用しています。確かにアルゴリズムはZについて言及していないので、それもまたストレートq = xr = yシステムです?
アーロンボンド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.