Отримайте кільце плитки в шестикутній сітці


17

Завдяки цій публікації: шестикутна плитка і знаходячи своїх сусідніх сусідів , я можу збирати сусідні плитки до заданої плитки. Але я в значній мірі застряг у алгоритмі, який дає мені лише "кільце" плитки, вказане зміщенням. Алгоритм, наведений у цій публікації про переповнення стека, точно не стосується порядку, в якому він збирає плитки.

Я знаю, що з кожним зміщенням додається 6 плиток.

  • Зсув 1 дає 6 плиток (перша сусідня плитка).
  • Зсув 2 дає вам 12.
  • Зсув 3 дає вам 18 і т.д.

З кожним зміщенням спостерігається постійне зростання 6. Тому я припускаю, що має існувати правило, яке адаптується до цих компенсацій. Я не можу точно зрозуміти це. Хтось?

Відповіді:


23

Шестикутне кільце з радіусом N складається з 6 прямих, кожна довжиною N - див. Мій надзвичайно грубий приклад нижче :) Для N = 2:

введіть тут опис зображення

Стрілки охоплюють 2 шестикутники кожна.

Я припускаю, що у вас є деякі функції, які надають вам сусідню плитку в конкретному напрямку, наприклад, північ (), південний схід () тощо. Отже, ваш алгоритм у псевдокоді повинен бути приблизно таким:

var point = startingPoint.north(N)
for i = 0..N-1:
    result.add(point)
    point = point.southeast(1);
for i = 0..N-1:
    result.add(point)
    point = point.south(1);
for i = 0..N-1:
    result.add(point)
    point = point.southwest(1);
for i = 0..N-1:
    result.add(point)
    point = point.northwest(1);
for i = 0..N-1:
    result.add(point)
    point = point.north(1);
for i = 0..N-1:
    result.add(point)
    point = point.northeast(1);

Зауважте, що це має працювати також для крайових випадків N = 1, повернення 6 плиток і N = 0 повернення порожнього набору.

Я знаю, що код не ідеальний :) Тут є надмірність. У своїх проектах, що використовують карти, що регулярно викладені плиткою (шестикутну або іншу), у мене зазвичай є переклад "Напрям", який дозволяє мені робити це більш гладко:

var point = startingPoint.inDir(N, Direction.North)
var dir = Direction.SouthEast.
for d = 0..Direction.count():
    for i = 0..N-1:
        result.add(point)
        point = point.inDir(1, dir);
    dir = nextDirection(dir);

Це має підштовхнути мене в правильному напрямку. Спасибі!
Сидар

2
Зауважте, що зразок коду додасть повторювані точки для перших п'яти сегментів. Однак це приємна відповідь.
MichaelHouse

@ Byte56 Так, я зрозумів. Але принаймні я бачу зв’язок між зрушеннями в напрямку!
Сидар

1
@ Byte56 Дійсно? Гм. Я намагався уникати цього ... 0..N-1 дає 0..1 для N = 2, тож це i = 0 і i = 1, що становить 2 значення. 2 значення кожного разу на 6 напрямків - це 12 плиток, як це має бути ...?
Ліосан

Ні. Ти маєш рацію. Оскільки кожен цикл додає крапку з останнього циклу, я був відключений однією для циклів, моя помилка. Це розумний алгоритм.
MichaelHouse

2

Я знайшов цю статтю дуже хорошою орієнтацією на алгоритми шестикутної сітки, і її розділ "Відстані" надає метод визначення кількості кроків між двома плитками. Якщо ви перетворите свої осьові координати (xy) в кубічні координати (xyz), відстань завжди дорівнює найбільшому зсуву координат між двома плитками, або max (| dx |, | dy |, | dz |).

О(н2)

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.