# Rendering concentric hexes on Canvas

Ray Rackiewicz

I've written a loop in JavaScript that will render rings of concentric hexagons around a central hexagon on the HTML canvas.

I start with the innermost ring, draw the hex at 3 o'clock, then continue around in a circle until all hexes are rendered. Then I move on to the next ring and repeat.

When you draw hexagons this way (instead of tiling them using solely x and y offsets) any hexagon that is not divisible by 60 is not the same distance to the center hex as those that are divisible by 60 (because these hexes comprise the flat edges, not the vertices, of the larger hex).

The problem I'm having is these hexes (those not divisible by 60 degrees) are rendering in a slightly off position. I'm not sure if it is a floating point math problem, the problem with my algorithm, the problem with my rusty trig, or just plain stupidity. I'm betting 3 out of 4. To cut to the chase, look at the line `if (alpha % 60 !== 0)` in the code below.

As a point of information, I decided to draw the grid this way because I needed an easy way to map the coordinates of each hex into a data structure, with each hex being identified by its ring # and ID# within that ring. If there is a better way to do it I'm all ears, however, I'd still like to know why my rendering is off.

Here is my very amateur code, so bear with me.

``````  <script type="text/javascript">
canvasApp();
}

function canvasApp(){
var xOrigin;
var yOrigin;
var scaleFactor = 30;

var theCanvas = document.getElementById("canvas");
var context;

if (canvas.getContext) {
context = theCanvas.getContext("2d");
resizeCanvas();
}
drawScreen();

function resizeCanvas() {
var imgData = context.getImageData(0,0, theCanvas.width, theCanvas.height);
theCanvas.width = window.innerWidth;
theCanvas.height = window.innerHeight;
context.putImageData(imgData,0,0);
xOrigin = theCanvas.width / 2;
yOrigin = theCanvas.height / 2;
}

function drawScreen() {
var rings = 3;
var alpha = 0;
var modifier = 1;

context.clearRect(0, 0, theCanvas.width, theCanvas.height);
drawHex(0,0);

for (var i = 1; i<=rings; i++) {
for (var j = 1; j<=i*6; j++) {
if (alpha % 60 !== 0) {
var h = modifier * scaleFactor / Math.cos(dtr(360 / (6 * i)));
drawHex(h * (Math.cos(dtr(alpha))), h * Math.sin(dtr(alpha)));
}
else {
drawHex(2 * scaleFactor * i * Math.cos(dtr(alpha)), 2 * scaleFactor * i * Math.sin(dtr(alpha)));
}
alpha += 360 / (i*6);
}
modifier+=2;
}
}

function drawHex(xOff, yOff) {
context.fillStyle = '#aaaaaa';
context.strokeStyle = 'black';
context.lineWidth = 2;
context.lineCap = 'square';
context.beginPath();
context.moveTo(xOrigin+xOff-scaleFactor,yOrigin+yOff-Math.tan(dtr(30))*scaleFactor);
context.lineTo(xOrigin+xOff,yOrigin+yOff-scaleFactor/Math.cos(dtr(30)));
context.lineTo(xOrigin+xOff+scaleFactor,yOrigin+yOff-Math.tan(dtr(30))*scaleFactor);
context.lineTo(xOrigin+xOff+scaleFactor,yOrigin+yOff+Math.tan(dtr(30))*scaleFactor);
context.lineTo(xOrigin+xOff,yOrigin+yOff+scaleFactor/Math.cos(dtr(30)));
context.lineTo(xOrigin+xOff-scaleFactor,yOrigin+yOff+Math.tan(dtr(30))*scaleFactor);
context.closePath();
context.stroke();
}

function dtr(ang) {
return ang * Math.PI / 180;
}

function rtd(ang) {
return ang * 180 / Math.PI;
}
}
</script>
``````
Niddro

Man it took me longer than I'd like to admit to find the pattern for the hexagonal circles. I'm too tired right now to explain since I think I'll need to make some assisting illustrations in order to explain it.

In short, each "circle" of hexagonal shapes is itself hexagonal. The number of hexagonal shapes along one edge is the same as the number of the steps from the center.

``````var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
c.width = 500;
c.height = 500;

function drawHex(x,y) {
ctx.beginPath();
ctx.moveTo(x,y-r);
for (var i = 0; i<=6; i++) {
}
ctx.closePath();
ctx.stroke();
}

drawHexCircle(250,250,4);

function drawHexCircle(x,y,circles) {
drawHex(250,250); //center

for (var i = 1; i<=circles; i++) {
for (var j = 0; j<6; j++) {
drawHex(currentX,currentY);
for (var k = 1; k<i; k++) {
var newX = currentX + Math.cos((j*60+120)*TO_RADIANS)*rc*2*k;
var newY = currentY + Math.sin((j*60+120)*TO_RADIANS)*rc*2*k;
drawHex(newX,newY);
}
}
}

}``````
``````canvas {
border: 1px solid black;
}``````
``<canvas id="canvas"></canvas>``

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다debugcn@gmail.com 삭제

에서 수정

0리뷰
로그인참여 후 검토

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev

분류에서Dev