gpt4 book ai didi

javascript - 旋转六边形上的索引

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:55:38 25 4
gpt4 key购买 nike

我有由小单位六边形组成的六边形。每个六边形都有一个 hex number单位六边形。前几个编号如下:

Size 1:
0
Size 2:
0 1
2 3 4
5 6
Size 3:
0 1 2
3 4 5 6
7 8 9 A B
C D E F
101112

(最后一位为十六进制)

您可以将其旋转 60 度的倍数,以将每个索引映射到旋转后的索引上。这是它们顺时针旋转了 60 度。

Size 1:
0
Size 2:
2 0
5 3 1
6 4
Size 3:
7 3 0
C 8 4 1
10 D 9 5 2
11 E A 6
12 F B

我的问题是如何?我有这两个函数用于十六进制函数和反向十六进制函数:

function hex(n) {
return 3 * +n * (+n + 1) + 1;
}

function reverse_hex(n) {
n = (+n - 1) / 3;
var i = Math.floor(Math.sqrt(n));
// null if not a hex number
return i * (i + 1) === n ? i : null;
}

我可以轻松地进行 0 度和 180 度的旋转。只需旋转 60 度几次,我就可以推导出 60 度的其他倍数。

function rotate(index, direction, size) {
// The unit of direction is 60 degrees. So "1" == rotate by 60 degrees.
direction = ((+direction % 6) + 6) % 6;
switch (direction) {
case 0:
return index;
case 1:
// Something?
return transformed_index;
case 2:
return rotate(rotate(index, 1, size), 1, size);
case 3:
return hex(size) - index - 1;
case 4:
return rotate(rotate(index, 3, size), 1, size);
case 5:
return rotate(rotate(index, 3, size), 2, size);
default: // (NaN or +/-Infinity) % 6 is NaN
return null;
}
}

但我想不出一个算法来做到这一点。

最佳答案

一种方法是将十六进制排列成环,每个环作为一个数组,从 1 环到 6 环,依此类推。要旋转,您从每个环形阵列的顶部移动到底部。因此,如果您有一个大小为 4 的六边形,则外环从外环的顶部向底部移动 3,然后从下一个环向内移动 2,依此类推。

这确实使得在 2D 中获取索引变得棘手。您可以通过创建第二个行数组来解决此问题。每行都是环形结构中的一个索引数组。因此,如果您想要第 2 行的单元格,从左数第 4 行,您可以查找数组 pos[2][4] 以获得环索引。在示例中,我对环索引进行了编码,因此您只需要一个数字即可查找环,然后在环中定位。

该示例显示了一个大小为 5 的十六进制,创建时从左到右编号,然后是从左到右的下一行。六边形旋转了 60 度。

const ctx = canvas.getContext("2d");
const font = "arial";
const fontSize = 14;

function createHex(size) {
// create object to hold a hexagon
const hexagon = {
count: 0,
hex: [],
};
// do first two rows manualy
if (size >= 1) {
hexagon.hex.push([0]);
hexagon.count += 1;
}
if (size >= 2) {
hexagon.hex.push([0, 1, 2, 3, 4, 5]);
hexagon.count += 6;
}
// keep adding rings until correct size
for (var i = 3; i <= size; i++) {
const ring = [];
for (var j = 0; j < i * 2 + 2 + (i - 2) * 4; j++) {
ring.push(j);
}
hexagon.hex.push(ring);
hexagon.count += ring.length;
}
// get the max rign size to use as modulo for row column lookup
hexagon.maxRingLen = size * 2 + 2 + (size - 2) * 4
// create an array for row column lookup
hexagon.pos = [];
// pos to prevent the array from becoming a sparse array
// create each row array and fill with dummy data
for (var i = 0; i < size + size - 1; i++) {
const row = [];
for (var j = 0; j < ((size + size - 1) - (Math.abs((size - 1) - i) - 1)) - 1; j++) {
row.push(0); // add dummy data
}
hexagon.pos.push(row);
}
// this array contains row, column steps for the six ring sizes
const steps = [1, 0, 1, 1, -1, 1, -1, 0, 0, -1, 0, -1];
// each ring starts at the top left and goes round clockwise
for (var i = 0; i < size; i++) {
const ringIndex = size - 1 - i
const ring = hexagon.hex[ringIndex];
var x = size - 1 - ringIndex;
var y = size - 1 - ringIndex;
for (var j = 0; j < ring.length; j++) {
// add the ring position index
hexagon.pos[y][x] = ringIndex * hexagon.maxRingLen + j
// find the next row column pos
const side = Math.floor(j / ringIndex) * 2;
x += steps[side];
y += steps[side + 1];
}
}
// now that we have the row column lookup you can
// create the correct sequence of numbers in the hexagon
// starting at top left moving from left to right all the way to the
// bottom right last number
var count = 0;
for (var i = 0; i < hexagon.pos.length; i++) {
const row = hexagon.pos[i];
for (var j = 0; j < row.length; j++) {
const ringPos = row[j] % hexagon.maxRingLen;
const ringIndex = Math.floor(row[j] / hexagon.maxRingLen);
hexagon.hex[ringIndex][ringPos] = count++;
}

}
return hexagon;
}
// rotates a hexagon 60deg
function rotateHex(hexagon) {
const size = hexagon.hex.length;
for (var i = 1; i < size; i++) { // from inner ring do each ring
const ring = hexagon.hex[i];
for (var j = 0; j < i; j++) {
// move the top to bottom of ring array
ring.unshift(ring.pop());
}
}
}

// just renders for testing.
function renderHex(hexagon, pos) {
const steps = [1, 0, 0.5, 1, -0.5, 1, -1, 0, -0.5, -1, 0.5, -1]
ctx.font = (fontSize-4) + "px " + font;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
const size = hexagon.length;

for (var i = 0; i < size; i++) {
const ringIndex = size - 1 - i
const ring = hexagon[ringIndex];
var x = pos.x - (ringIndex * fontSize * 0.5);
var y = pos.y - (ringIndex * fontSize);
for (var j = 0; j < ring.length; j++) {
ctx.fillText(ring[j].toString(36), x, y);
const side = Math.floor(j / ringIndex) * 2;
x += steps[side] * fontSize;
y += steps[side + 1] * fontSize;

}

}
}

var h = createHex(5);
renderHex(h.hex, {
x: canvas.width * (1 / 4),
y: canvas.height * (2 / 4)
});
rotateHex(h);
renderHex(h.hex, {
x: canvas.width * (3 / 4),
y: canvas.height * (2 / 4)
});
<canvas id="canvas"></canvas>

关于javascript - 旋转六边形上的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44607380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com