2016-02-25 16 views
8

Ich versuche einen Weg zu finden, so viele Sechsecke wie möglich in einen Kreis zu setzen. Bis jetzt ist das beste Ergebnis, das ich erzielt habe, die Erzeugung von Sechsecken von der Mitte nach außen in einer kreisförmigen Form.Kreis mit Sechsecken füllen

Aber ich denke, meine Berechnung die maximalen Sechseck Kreise zu bekommen falsch ist, vor allem den Teil, wo ich die Math.ceil() und Math.Floor Funktionen verwenden, um einige Werte zu runden unten/oben.

Bei der Verwendung von Math.ceil() überlappen manchmal Sechsecke den Kreis.
Wenn Sie andererseits Math.floor() verwenden, lässt es manchmal zu viel Abstand zwischen dem letzten Kreis der Sechsecke und dem Rand des Kreises.

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

Antwort

4

Wenn alle Punkte auf dem Sechseck innerhalb des Kreises sind, ist das Sechseck innerhalb des Kreises. Ich glaube nicht, dass es einen einfacheren Weg gibt als die Entfernungsberechnung.

Ich bin nicht sicher, wie man den optimalen Füllpunkt auswählt, (aber hier ist ein js Ausschnitt, der beweist, dass die Mitte nicht immer es ist). Es ist möglich, dass wenn Sie "Sechseck Kreis" meinen, Sechseck aus Sechsecken, in diesem Fall das Schnipsel beweist nichts :)

Ich habe die Sechseckseiten 2/11ths den Radius des Kreises und Abstand von 5% die Seitenlänge.

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