Нахождение ячеек в пределах диапазона на гексагональной сетке

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
Спасибо за этот ресурс, он выглядит очень хорошо! Я был немного потрясен, когда понял, что почти вся графика была интерактивной. :)
Кристер
3
В приведенном им примере используются координаты куба, в то время как кажется, что вы используете смещение или осевые координаты. Вам нужно преобразовать x, y, z из кубических координат, которые он имеет, в любую используемую вами систему координат.
Алекс Шерман
1
@ Vector57 Я использую Axial. Из раздела преобразования упоминается, что мне не нужно ничего делать со свойством Z, хотя q / r и x / y взаимозаменяемы ... или я не так понял?
Аарон-Бонд
Это выглядит так, хотя в примерах он использует r = z, но я не понимаю, почему это должно иметь значение, какой вы выберете.
Алекс Шерман

Ответы:

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);
    }
}
Алекс Шерман
источник
О, сумасшедший ... в статье даже упоминается, что они являются дельта-значениями :( Собираюсь попробовать это сейчас и посмотреть, как это происходит. Спасибо :)
aaron-bond
Спасибо за это. Это определенно намного ближе к правильному способу сделать это. Я все еще что-то путаю с координатами, но по крайней мере у меня есть правильный номер! По какой-то причине у меня одна ячейка слишком высока на -x, а другая - на + x. Я разместил фото наверху, если вы знаете что-нибудь об этом, но я все равно продолжу исследовать себя :) спасибо за вашу помощь!
Аарон-Бонд
Вы правильно интерпретируете осевые координаты? Помните, что вы решили использовать x и y, а не x и z, поэтому, если остальная часть вашего кода не учитывает это изменение из примеров, это может привести к странному поведению.
Алекс Шерман
Да, я переключился так, чтобы это были x и z. dx становится x, а z = -dx - dy ...
Аарон-Бонд
1
Новая картинка, которую вы разместили, показывает 7 гексов. Это то, что вы ожидаете с расстояния = 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, что вы ожидаете от алгоритма диапазона.

Я не знаю, какую систему координат вы используете, но я предполагаю, что это одна из систем "смещения координат", которые популярны, потому что их легко реализовать, поместив ячейки сетки в двумерный массив:

смещение 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
congusbongus
источник
У меня было чувство, что это было что-то вроде этого. Была часть этой страницы, в которой упоминалось преобразование из куба в осевое и было сказано просто удалить часть z, а оставшиеся q и r стали x и y. Я думаю, что я, должно быть, слишком упрощен там. Спасибо за это. Отличное объяснение того, чего мне не хватало. Я попробую позже! :)
Аарон-Бонд
Я только что посмотрел, и я использую осевой. Конечно, поскольку в алгоритме нет упоминания о Z, он также прямой q = xи r = yсистемный?
Аарон-Бонд