Повернуть шестигранник

Я могу легко пересечь следующее слева направо, но у меня много проблем (2 дня и без прогресса), получая формулу, чтобы пересечь ее сверху и снизу справа.

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

В принципе, я ищу формулу, которая может получить следующие значения:

let topRight = [
    [ h[2][4], h[3][3], h[4][2] ],
    [ h[1][3], h[2][3], h[3][2], h[4][1] ],
    [ h[0][2], h[1][2], h[2][2], h[3][1], h[4][0] ],
    [ h[0][1], h[1][1], h[2][1], h[3][0] ],
    [ h[0][0], h[1][0], h[2][0] ]
]

let bottomRight = [
    [ h[2][4], h[1][3], h[0][2] ],
    [ h[3][3], h[2][3], h[1][2], h[0][1] ],
    [ h[4][2], h[3][2], h[2][2], h[1][1], h[0][0] ],
    [ h[4][1], h[3][1], h[2][1], h[1][0] ],
    [ h[4][0], h[3][0], h[2][0] ]
]

Единственной частью, которую я мог получить, было значение topRight x:

function hexagonArraySize(row) {
  if (row < this.size) {
    return (this.size + row)
  } else {
    return (this.size * 2 - (row % this.size) - 2)
  }
}

for (var i = 0, l = this.size * 2 - 1, j = l % size; i < l; ++i, ++j) {
  this.h[j] = new Array(this.hexagonArraySize(i)).fill().map((_, b) => {
    let x = (i > Math.floor(this.size / 2)) ? b : b + (this.size - i - 1)
    let y = 0 // didn't found the formula for this one...
  }, []).join("")
}

Я сделал скрипку, доступную здесь: https://jsfiddle.net/0qwf8m1p/12/

По-прежнему существует topRight y, bottomRight x и y.

Ответ 1

Итак, вы разработали координату topRight x.

Обе координаты topRight и bottomRight y имеют одно и то же уравнение:

  • Вы начинаете с (size - 1) * 2
  • Первое значение всегда равно (size - 1) * 2 - i) (где i - индекс последовательности)
  • Затем вы повторяете первое значение i раз, но самое большее size times

Это завершает следующую формулу:

let y = (size - 1) * 2 - i - Math.max(0, b - Math.min(i, size - 1))
        |                  |                                      |
        |    first value   |      repeat at most size times       |

Затем вам нужно вычислить значение x для bottomRight. Здесь у вас два случая:

  • Если i меньше size / 2, тогда значение равно длине последовательности - b (индекс предмета)
  • В противном случае значение равно (size - 1) * 2 - b

Это завершает следующую формулу:

let x = (i > Math.floor(size / 2)) ? (size - 1) * 2 - b : hexagonArraySize(i) - b - 1
        |                          |                    |
        |       check index        |     second half    |          first half

Рабочая скрипка здесь

Ответ 2

Здесь возможно выполнение двух методов. Они работают путем инициализации координат x,y начала для каждой строки в преобразованном шестиугольнике, затем условно повторяют значение x на основании того, прошло ли значение y символа size шестиугольника, где индексы "изгиб":

function hexagon (size) {
  const height = size * 2 - 1;
  
  return Array.from({ length: height }, (_, y) => {
    const width = size + Math.min(y, height - y - 1);
    
    return Array.from({ length: width }, (_, x) => [y, x]);
  })
}

const h = hexagon(3);

function topRight (h) {
  const height = h.length;
  const size = (height + 1) / 2;
  const t = [];
  
  for (let i = height; i > 0; i--) {
    const width = size + Math.min(i - 1, height - i);
    const row = Array.from({ length: width });
    
    let y = Math.max(i - size, 0);
    let x = i - 1;
    
    for (let j = 0; j < width; j++) {
      row[j] = h[y++][y >= size ? x-- : x];
    }
    
    t.push(row);
  }
  
  return t;
}

function bottomRight (h) {
  const height = h.length;
  const size = (height + 1) / 2;
  const t = [];
  
  for (let i = 0; i < height; i++) {
    const width = size + Math.min(i, height - i - 1);
    const row = Array.from({ length: width });
    
    let y = height - Math.max(size - i, 1);
    let x = height - i - 1;
    
    for (let j = 0; j < width; j++) {
      row[j] = h[y][y-- < size ? x-- : x];
    }

    t.push(row);
  }
  
  return t;
}

console.log('topRight');
topRight(h).forEach(row => console.log(JSON.stringify(row)));
console.log('bottomRight');
bottomRight(h).forEach(row => console.log(JSON.stringify(row)));