Analysis and Representation of a Circle in Hexagonal Grid using Python

The primary advantage of a hexagonal grid over a traditional square grid is that the distance between the centre of each hex cell (or hex) and the centre of all six adjacent hexes is constant. By comparison, in a square grid, the distance from the enter of each square cell to the centre of the four diagonal adjacent cells it shares a corner with is greater than the distance to the centre of the four adjacent cells it shares an edge with. The constant distance of a hex grid is desirable for games in which the measurement of movement is a factor. The other advantage is the fact that neighbouring cells always share edges; there are no two cells with contact at only one point.

 TYPES OF GRIDS

Quite simply Grids are built from a repetition of simple shapes. The cells of the grids can be used to represent different shapes with varying degree of accuracy. Few of the major grids are described below:-

Square Grid

square_grid

The most common grid is a square grid. It’s simple, easy to work with, and maps nicely onto a computer screen. Locations can use the familiar cartesian coordinates (x, y) and the axes are orthogonal. The square coordinate system is the same even if your map squares are angled on screen in an isometric or axonometric projection.

Neighbourhood:

i) 4-n -> Common Side

ii) 8-n -> Common Vertex or Side

Triangular Grid

triangular_grid

Triangles are common in 3d graphics but are rarely used for game maps. A big disadvantage of triangle maps, aside from unfamiliarity, is the large perimeter and small area (the opposite of a hexagon). In 3d graphics, triangles are the only shape that is planar; squares and hexagons can be “bent”, sometimes in impossible ways.

Neighbourhood:

i) 3-n -> Common Side

ii) 6-n -> Common Vertex or Side

Hexagonal Grid

hexagonal_grid

Hexagons have been used in some board and computer games because they offer less distortion of distances than square grids. This is in part because each hexagon has more non-diagonal neighbors than a square. (Diagonals distort grid distances.) Hexagons have a pleasing appearance and occur in nature (for example, honeycombs). In this project, we’ll use hexagons that have pointy tops and flat sides, but the math works the same if we want flat tops and pointy sides.

Neighbourhood:

i) 6-n -> Common Side

Therefore, All Neighbours of a hexagonal grid share a side.

Co-ordinate systems used in Hexagonal lattice:

a.Offset Coordinates

It is a type of Coordinate system for hexagonal grids. Every other column or row is offset in the horizontal or vertical direction given us a total of 4 variants:-

i) Odd – r Horizontal Layout

i) Even – r Horizontal Layout

i) Odd – r Vertical Layout

i) Even – r Vertical Layout

b.Cube Coordinates

Another way to look at hexagonal grids is to see that there are three primary axes, unlike the two we have for square grids. There’s an elegant symmetry with these. The three axes x, y, z have the constraint x+y+z=0. This symmetry allows more intuitive understanding of the algorithms in hexagonal grid.

c.Axial Coordinates

The axial coordinate system is built by taking two of the three coordinates from a cube coordinate system. Since we have a constraint such as x + y + z = 0, the third coordinate is redundant. Thus Axial coordinates is just a simpler form of cube coordinates. We will be using Axial coordinates in this project.

Here we are going to use a slightly modified version of Bressenham algorithm to draw the circle , we are going to use python turtle module to implement the algorithm.

The code looks like this:

import collections

import math

import turtle

SIZE = int(input(“Size of each hexagon in the grid: “))

COOD = int(input(“Grid size: “))

RAD = int(input(“Radius of the required circle: “))

CX, CY = map(int,input(“Center of Circle: “).split())

chain_code=[]

Point = collections.namedtuple(“Point”, [“x”, “y”])

Hex = collections.namedtuple(“Hex”, [“q”, “r”])

def hex_to_pixel(hex):

x = SIZE * math.sqrt(3) * (hex.q + hex.r/2)

y = SIZE * 3/2 * hex.r

return Point(x, y)

sc=turtle.Screen()

tr=turtle.Turtle()

def init_turtle():

tr.hideturtle()

sc.bgcolor(“lightgreen”)

sc.title(“Hex”)

tr.color(“blue”)

tr.pensize(1)

tr.fillcolor(‘red’)

def draw_hex(hex, fill):

tr.penup()

tr.seth(0)

tr.setpos(hex_to_pixel(hex))

tr.forward(SIZE)

tr.left(90)

tr.pendown()

if fill:

tr.begin_fill()

for i in range(6):

tr.forward(SIZE);

tr.left(60)

if fill:

tr.end_fill()

def draw_hexgrid():

sc.tracer(0, 0)

for i in range(-COOD, COOD):

for j in range(-COOD, COOD):

draw_hex(Hex(i, j), False)

tr.fillcolor(‘black’)

for i in range(-COOD, COOD):

draw_hex(Hex(i, 0), True)

for j in range(-COOD, COOD):

draw_hex(Hex(0, j), True)

sc.update()

sc.tracer(4,20)

def draw_sym(x, y):

draw_hex(Hex(CX+x, CY+y), True)

draw_hex(Hex(CX+y, CY+x), True)

draw_hex(Hex(CX+x+y, CY-x), True)

draw_hex(Hex(CX+x+y, CY-y), True)

draw_hex(Hex(CX+y, CY-x-y), True)

draw_hex(Hex(CX+x, CY-x-y), True)

draw_hex(Hex(CX-x, CY-y), True)

draw_hex(Hex(CX-y, CY-x), True)

draw_hex(Hex(CX-x-y, CY+x), True)

draw_hex(Hex(CX-x-y, CY+y), True)

draw_hex(Hex(CX-y, CY+x+y), True)

draw_hex(Hex(CX-x, CY+x+y), True)

def draw_circle(r):

x, y=0, r

d=0.25

while x<y:

draw_sym(x, y)

x+=1

if d<0:

d+=2*x+y+2.5

chain_code.append(0)

else:

y-=1

d+=(x-y)+2.75

chain_code.append(1)

draw_sym(x, y)

def draw_diameter():

tr.fillcolor(‘yellow’)

for j in range(1, RAD):

draw_hex(Hex(CX+0, CY+j), True)

draw_hex(Hex(CX+0, CY-j), True)

init_turtle()

draw_hexgrid()

tr.fillcolor(‘red’)

draw_hex(Hex(CX, CY), True)

draw_circle(RAD)

draw_diameter()

print(“Chain Code: “)

print(chain_code)

sc.mainloop()

Upon executing the code you should get something that looks like this:

result

Leave a comment