2016-02-25 23 views
8

Sto provando a trovare un modo per mettere quanti più esagoni in un cerchio possibile. Finora il risultato migliore che ho ottenuto è la generazione di esagoni dal centro verso l'esterno in una forma circolare.cerchio di riempimento con gli esagoni

Ma credo che il mio calcolo per ottenere i massimi circoli esagonali è sbagliato, in particolare la parte in cui io uso il Math.ceil() e Math.Floor funzioni per arrotondare giù/su alcuni valori.

Quando si utilizza Math.ceil(), gli esagoni a volte si sovrappongono al cerchio.
Quando si utilizza Math.floor() d'altra parte, a volte lascia troppo spazio tra l'ultimo cerchio di esagoni e il bordo del cerchio.

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;">

risposta

4

Se tutti i punti dell'esagono sono all'interno del cerchio, l'esagono è all'interno del cerchio. Non penso che ci sia un modo più semplice del calcolo della distanza.

Non sono sicuro di come selezionare il punto di riempimento ottimale, (ma ecco un frammento js che dimostra che il mezzo non è sempre). È possibile che quando si dice "esagono cerchio" si intenda esagono fatto di esagoni, nel qual caso il frammento non prova nulla :)

Ho fatto i lati esagonali 2/11ths il raggio del cerchio e li distanziati del 5% la lunghezza laterale

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