2016-02-25 10 views
8

できるだけ円に六角形を入れる方法を探しています。今まで私が得た最良の結果は、中心から外側に向かって六角形を円形に生成することです。円を六角形で塗りつぶし

は、しかし、私は私の計算は私が/アップいくつかの値を切り捨てする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 = { 
 
\t r: 110, /// radius 
 
\t pos: { 
 
\t \t x: (canvas_width/2), 
 
\t \t y: (canvas_height/2) 
 
\t } 
 
}; 
 

 
var hexagon = { 
 
\t r: 20, 
 
\t pos:{ 
 
\t \t x: 0, 
 
\t \t y: 0 
 
\t }, 
 
\t space: 1 
 
}; 
 

 
drawHexCircle(hexCircle, hexagon); 
 
function drawHexCircle(hc, hex) { 
 
\t drawCircle(hc); 
 
\t var hcr = Math.ceil(Math.sqrt(3) * (hc.r/2)); 
 
    var hr = Math.ceil((Math.sqrt(3) * (hex.r/2))) + hexagon.space; // hexRadius 
 
\t var circles = Math.ceil((hcr/hr)/2); 
 
    drawHex(hc.pos.x , hc.pos.y, hex.r); //center hex /// 
 
\t for (var i = 1; i<=circles; i++) { 
 
\t \t for (var j = 0; j<6; j++) { 
 
\t \t \t var currentX = hc.pos.x+Math.cos(j*PI2/6)*hr*2*i; 
 
\t \t \t var currentY = hc.pos.y+Math.sin(j*PI2/6)*hr*2*i; 
 
\t \t \t drawHex(currentX,currentY, hex.r); 
 
\t \t \t for (var k = 1; k<i; k++) { 
 
\t \t \t \t var newX = currentX + Math.cos((j*PI2/6+PI2/3))*hr*2*k; 
 
\t \t \t \t var newY = currentY + Math.sin((j*PI2/6+PI2/3))*hr*2*k; 
 
\t \t \t \t drawHex(newX,newY, hex.r); 
 
\t \t \t } 
 
\t \t } 
 
\t } 
 
} 
 

 
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){ 
 
\t ctx.beginPath(); 
 
\t ctx.arc(circle.pos.x, circle.pos.y, circle.r, 0, 2 * Math.PI); 
 
\t ctx.closePath(); 
 
\t ctx.stroke(); 
 
}
<canvas id="myCanvas" width="350" height="350" style="border:1px solid #d3d3d3;">

答えて

4

六角形上のすべての点が円内にある場合、六角形、円の範囲内です。私は、距離計算を行うより簡単な方法はないと思います。

私は最適な塗りつぶしポイントを選択する方法がわかりませんが(ここでは、中央が必ずしもそうでないことを証明するjsスニペットがあります)。あなたが「六角形の円」と言うとき、六角形で作られた六角形を意味する可能性があります。この場合、スニペットは何も証明しません:)

私は六角形の辺を円の半径の2/11にし、辺の長さ

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); 
 
}