Sign in to follow this  
agm_ultimatex

Mathematically positioning hexagons in a grid format

Recommended Posts

I'm working on getting a grid using hexagons in a honeycomb pattern. Thanks to the work of the previous developer, here's where it stands in terms of layout:

http://imgur.com/BBDZB

The code is:

[code]

generateTiles : function(f) {
var xyz = [0,0,0];
var radius = 7;
var max_out = 14;
var deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]];
var output = ""
for (var i = 0; i < radius; i++) {
var x = xyz[0];
var y = xyz[1]-i;
var z = xyz[2]+i;
for (var j = 0; j < 6; j++) {
for (var k = 0; k < i; k++) {
x = x+deltas[j][0]
y = y+deltas[j][1]
z = z+deltas[j][2]
f(x,y,z);
}
}
}
},
[/code]



The f function that is called passes an x and y value for coordinates:

[code]
var coords = [0,0,0];

this.x = function() {
var x = (Math.sqrt(3) * (radius + 1) * (coords[2]/2 + coords[0]));
return GridInterface.HexGrid.x_offset + x;
};

this.y = function() {
var y = (3/2 * (radius + 1) * coords[2]);
return GridInterface.HexGrid.y_offset + y;
};
[/code]

The x/y offset values is the center of the grid.


What I want to achieve is to have it work when the hexagons are rotated 30 degrees, so the sides are flat at the top and bottom. When i rotate them now, the points are touching as supposed to being directly side by side. Any suggestions on how i can make this happen would be greatly apprecated.

Share this post


Link to post
Share on other sites
[quote name='agm_ultimatex' timestamp='1317867543' post='4869625']
What I want to achieve is to have it work when the hexagons are rotated 30 degrees, so the sides are flat at the top and bottom. When i rotate them now, the points are touching as supposed to being directly side by side. Any suggestions on how i can make this happen would be greatly apprecated.
[/quote]

Ignoring some minor adjustments: swap x and y and just rotate 90° instead.

Share this post


Link to post
Share on other sites
Hexagon are actually not really that hard, once you deconstruct them in your mind into a rectangle and two "tips".

Assuming your orientation has vertical sides and the tip at the top and bottom, some values you will need a lot are:

Calling the height of this "tip" A and the height of the rectangle B (and assuming that hexWidth is the width of the rectangle, ie. one edge to the opposite edge):

Precalculate sin of 60°, you will need it a lot:

[color="#000000"]A = hexWidth / (4 * sin60);[/color] [color="#000000"]B = 2*A;
TipToTip = 4*A
RowHeight = 3*A (or A+B.. note how A is the overlap of two rows)
The slope of the tip is: A / width => .25 / sin60
[/color]
One piece of code I keep rederiving every time I use hex grids is mapping a point to hex coordinates (because I hate copy pasting stuff without understanding it, even if I copy from myself)

[code]
//x and y are float coordinates, col and row are the grid coords (indices) of the hexagon

const float sin60 = 0.8660254f;
const float hexColumnWidth = cellSize_;
const float hexRowHeight = .75f * cellSize_ / sin60; //In combination with the numbers above, this means the ratio width/height of a hexagon is 1/sin60
const float slope = 2.0f / 3.0f; //Needs to be relative to 3/4 of hexagon height ie. slope / hexRowHeight = (.5 * cellSize_ / sin60) / (.75 * cellSize_ / sin60) = 2/3

float hexSpaceY = y / hexRowHeight;
row = floor(hexSpaceY);
hexSpaceY -= row;

//Every second row is offset by half a hex width (in this case to the right, so it has to be subtracted)
float hexSpaceX = (x - (iy%2) * hexColumnWidth/2) / hexColumnWidth;
col = floor(hexSpaceX);
hexSpaceX -= col;

//Now these ominous hexSpace coordinates are not grid coordinates, but imagine a rectangle around the hexagon excluding the bottom tip. The coordinates are relative to this rectangle (the vertex at the top would be [.5, 0] for example)

//Upper left neighbor (ie. left half of the hexagon and above the top left edge (note that y-axis is top->bottom)
if ( hexSpaceX < .5f && hexSpaceY < (.5f - hexSpaceX) * slope )
{
--row;
if (row%2) --col; //only in every odd row does "one left" equal a change of the column
}

//Upper right neighbor
//Note how the slope is implicitely inverted by swapping hexSpaceX and .5
if ( hexSpaceX >= .5f && hexSpaceY < (hexSpaceX - .5f) * slope)
{
if (row%2) ++col; //in every even row "one right" equals a column change (hence we do the same test as above but BEFORE decrementing row)
--row;
}[/code]

There are probably smarter or more efficient ways to do it, but this is what I came up with this time. I have found that understanding the geometry of the hex and the ratios of its parts to be key if you want to feel comfortable with hexes. You might notice I didn't resort to a radius or any trigonometry at all. Ignoring the sin(60) which everything is based on and which is kind of weird, since basing it on A = hexWidth * .5 * tan(30°) would be a more obvious thing to do.

Share this post


Link to post
Share on other sites
An alternative way to label hexagons is to pick the center of one of the hexagons as origin, (1,0) is the hexagon to its right and (0,1) is the hexagon above it and partially to the right. You have to work with coordinates that are not orthogonal, but I haven't found any situations where that was a serious problem. I prefer to work this way, but it's probably a matter of personal taste.

Share this post


Link to post
Share on other sites
[quote name='alvaro' timestamp='1317930431' post='4869877']
An alternative way to label hexagons is to pick the center of one of the hexagons as origin, (1,0) is the hexagon to its right and (0,1) is the hexagon above it and partially to the right. You have to work with coordinates that are not orthogonal, but I haven't found any situations where that was a serious problem. I prefer to work this way, but it's probably a matter of personal taste.
[/quote]

It sure is much more convenient than having to worry about odd and even rows (or columns). But assuming you want your grid as an overlay over a rectangular area, wouldn't you need to fix the coordinates by wrapping them? (Something like x = (x+y) % width )? Though in this particular case it probably doesn't matter, considering the layout of the hexes.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this