我正试图找到一种尽可能多地将六边形放在圆圈中的方法。到目前为止,我获得的最好结果是从中心向外以圆形形状生成六边形。
但我认为我的计算得到最大六边形圆是错误的,尤其是我使用Math.ceil()
和Math.Floor
函数来舍入/向上舍入某些值的部分。
使用Math.ceil()
时,六边形有时与圆圈重叠
另一方面,当使用Math.floor()
时,它有时会在最后一个六边形圆与圆的边界之间留下太多空间。
var c_el = document.getElementById("myCanvas");
var ctx = c_el.getContext("2d");
var canvas_width = c_el.clientWidth;
var canvas_height = c_el.clientHeight;
var PI=Math.PI;
var PI2=PI*2;
var hexCircle = {
r: 110, /// radius
pos: {
x: (canvas_width / 2),
y: (canvas_height / 2)
}
};
var hexagon = {
r: 20,
pos:{
x: 0,
y: 0
},
space: 1
};
drawHexCircle( hexCircle, hexagon );
function drawHexCircle(hc, hex ) {
drawCircle(hc);
var hcr = Math.ceil( Math.sqrt(3) * (hc.r / 2) );
var hr = Math.ceil( ( Math.sqrt(3) * (hex.r / 2) ) ) + hexagon.space; // hexRadius
var circles = Math.ceil( ( hcr / hr ) / 2 );
drawHex( hc.pos.x , hc.pos.y, hex.r ); //center hex ///
for (var i = 1; i<=circles; i++) {
for (var j = 0; j<6; j++) {
var currentX = hc.pos.x+Math.cos(j*PI2/6)*hr*2*i;
var currentY = hc.pos.y+Math.sin(j*PI2/6)*hr*2*i;
drawHex( currentX,currentY, hex.r );
for (var k = 1; k<i; k++) {
var newX = currentX + Math.cos((j*PI2/6+PI2/3))*hr*2*k;
var newY = currentY + Math.sin((j*PI2/6+PI2/3))*hr*2*k;
drawHex( newX,newY, hex.r );
}
}
}
}
function drawHex(x, y, r){
ctx.beginPath();
ctx.moveTo(x,y-r);
for (var i = 0; i<=6; i++) {
ctx.lineTo(x+Math.cos((i*PI2/6-PI2/4))*r,y+Math.sin((i*PI2/6-PI2/4))*r);
}
ctx.closePath();
ctx.stroke();
}
function drawCircle( circle ){
ctx.beginPath();
ctx.arc(circle.pos.x, circle.pos.y, circle.r, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
}
<canvas id="myCanvas" width="350" height="350" style="border:1px solid #d3d3d3;">
答案 0 :(得分:4)
如果六边形上的所有点都在圆内,则六边形在圆内。我不认为这比做距离计算更简单。
我不确定如何选择最佳填充点,(但这里有一个js片段,证明中间并不总是如此)。当你说&#34;六角圈&#34;你的意思是用六边形做成的六边形,在这种情况下,代码片段没有任何证据:)
我将六边形的边是圆的半径的2/11,并将它们的边长间隔为5%。
var hex = {x:0, y:0, r:10};
var circle = {x:100, y:100, r:100};
var spacing = 1.05;
var SQRT_3 = Math.sqrt(3);
var hexagon_offsets = [
{x: 1/2, y: -SQRT_3 / 2},
{x: 1, y: 0},
{x: 1/2, y: SQRT_3 / 2},
{x: -1/2, y: SQRT_3 / 2},
{x: -1, y: 0},
{x: -1/2, y: -SQRT_3 / 2}
];
var bs = document.body.style;
var ds = document.documentElement.style;
bs.height = bs.width = ds.height = ds.width = "100%";
bs.border = bs.margin = bs.padding = 0;
var c = document.createElement("canvas");
c.style.display = "block";
c.addEventListener("mousemove", follow, false);
document.body.appendChild(c);
var ctx = c.getContext("2d");
window.addEventListener("resize", redraw);
redraw();
function follow(e) {
hex.x = e.clientX;
hex.y = e.clientY;
redraw();
}
function drawCircle() {
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.arc(circle.x, circle.y, circle.r, 0, 2 * Math.PI, true);
ctx.closePath();
ctx.stroke();
}
function is_in_circle(p) {
return Math.pow(p.x - circle.x, 2) + Math.pow(p.y - circle.y, 2) < Math.pow(circle.r, 2);
}
function drawLine(a, b) {
var within = is_in_circle(a) && is_in_circle(b);
ctx.strokeStyle = within ? "green": "red";
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
ctx.closePath();
ctx.stroke();
return within;
}
function drawShape(shape) {
var within = true;
for (var i = 0; i < shape.length; i++) {
within = drawLine(shape[i % shape.length], shape[(i + 1) % shape.length]) && within;
}
if (!within) return false;
ctx.fillStyle = "green";
ctx.beginPath();
ctx.moveTo(shape[0].x, shape[0].y);
for (var i = 1; i <= shape.length; i++) {
ctx.lineTo(shape[i % shape.length].x, shape[i % shape.length].y);
}
ctx.closePath();
ctx.fill();
return true;
}
function calculate_hexagon(x, y, r) {
return hexagon_offsets.map(function (offset) {
return {x: x + r * offset.x, y: y + r * offset.y};
})
}
function drawHexGrid() {
var hex_count = 0;
var grid_space = calculate_hexagon(0, 0, hex.r * spacing);
var y = hex.y;
var x = hex.x;
while (y > 0) {
y += grid_space[0].y * 3;
x += grid_space[0].x * 3;
}
while (y < c.height) {
x %= grid_space[1].x * 3;
while (x < c.width) {
var hexagon = calculate_hexagon(x, y, hex.r);
if (drawShape(hexagon)) hex_count++;
x += 3 * grid_space[1].x;
}
y += grid_space[3].y;
x += grid_space[3].x;
x += 2 * grid_space[1].x;
}
return hex_count;
}
function redraw() {
c.width = window.innerWidth;
c.height = window.innerHeight;
circle.x = c.width / 2;
circle.y = c.height / 2;
circle.r = Math.min(circle.x, circle.y) * 0.9;
hex.r = circle.r * (20 / 110);
ctx.clearRect(0, 0, c.width, c.height);
var hex_count = drawHexGrid();
drawCircle();
ctx.fillStyle = "rgb(0, 0, 50)";
ctx.font = "40px serif";
ctx.fillText(hex_count + " hexes within circle", 20, 40);
}
&#13;