六边形路径上的点坐标

Coordinates of dot on an hexagon path

在一个项目中,我想在正六边形路径周围均匀分布点。
因此,我想计算我的点从六角形中心的坐标和边的长度。

例如,如果我想围绕一个圆做同样的事情,我会做(在 JS 中):

let center = {x: 0, y: 0}
let radius = 10;
let amountOfDots = 48;
for (let i = 0; i < amountOfDots; i++) {
    let x = radius * Math.sin(Math.PI * 2 * i / amountOfDots) + center.x;
    let y = radius * Math.cos(Math.PI * 2 * i / amountOfDots) + center.y;
    // draw my dot in (x, y) or whatever
}

换句话说,我想在一个循环中获得所有这些点的坐标。
在这个例子中 amountOfDots = 24

我的直觉不会太难实现,但我在数学上苦苦挣扎...
谢谢:)

我们在单位圆(半径 = 1)上执行此操作时的一些观察结果:

  • 六个六角边之一的大小为1

  • 六边形的六个点坐标为:

    ( 1,    0   )  
    ( 0.5,  √3/2)
    (-0.5,  √3/2)
    (-1,    0   )
    (-0.5, -√3/2)
    ( 0.5, -√3/2)
    
  • 六边形外接球的总大小为6

  • 两个连续点之间的距离(在那个圆周上)是 6 / amountOfDots

  • 一个点到起点(在六边形上)的距离可以知道这个点在哪条六边形边上(距离的整数部分),以及在那条边上有多远edge(距离的小数部分)

  • 使用插值我们可以确定这样一个点的坐标

这是一个交互式 JS 片段,用于计算和绘制这些点:

// Main algorithm:
function hexagonDots(center, radius, amountOfDots) {
    // Function to map unit coordinates to the given center & radius
    const project = (x, y) => ({
        x: center.x + radius * x,
        y: center.y + radius * y
    });
    const y = Math.sqrt(3) / 2; // = sin(60°)
    const hexaX = [1, 0.5, -0.5, -1, -0.5, 0.5, 1];
    const hexaY = [0, y, y, 0, -y, -y, 0];

    return Array.from({length: amountOfDots}, (_, i) => {
        let offset = 6 * i / amountOfDots;
        const edgenum = Math.floor(offset); // On which edge is this dot?
        offset %= 1; // Retain fractional part only: offset on that edge
        return project( 
            // Use interpolation to get coordinates of that point on that edge
            hexaX[edgenum] + offset * (hexaX[edgenum + 1] - hexaX[edgenum]),
            hexaY[edgenum] + offset * (hexaY[edgenum + 1] - hexaY[edgenum])
        );
    });
}

// I/O management:

function drawHexagon(ctx, dots) {
    // Draw
    ctx.resetTransform();
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
    ctx.translate(200, 80);
    for (const {x, y} of dots) {
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x+1, y);
        ctx.stroke();
    }
}

const ctx = document.querySelector("canvas").getContext("2d");

function refresh() {
    const center = {x: 0, y: 0};
    const radius = 70;
    const amountOfDots = +this.value;
    const dots = hexagonDots(center, radius, amountOfDots);
    drawHexagon(ctx, dots);
}

const input = document.querySelector("input");
input.addEventListener("input", refresh);
refresh.call(input);
Dots: <input type="number" value="48" size="4"><br>
<canvas></canvas>