This article is an adaptation of C# code to Xojo code and the C# article was originally written by Rod Stephens at  Draw a hexagonalgrid in C#. Rows and columns are numbered in a hexagonal grid when the rows start at zero at the top, and increase as you go near the bottom. Columns start at zero at the left and the value increases as you move to the right. Below is a screen grab of the hexagonal grid.

Figure 1. Hexagonal Grid Layout

Hexagonal Grid

This example needs to be able to do four things:

  • Map a row and column to the points that are created for the hexagon
  • Map a mouse-selected-point (x,y) to a row and column
  • Colour the selected hexagon
  • Show the row and column in the appropriate hexagon

Figure 2. Selected Hexagon

hexagon screen grab

Selecting hexagons will create a blue colour in the hexagon and the hexagon coordinate number will be redrawn in a black colour. Each time a hexagon is selected, it is added to an array of selected coordinates and is stored in the SelectPoints array.

A new project is created and a 400x400 canvas is added to the window. Two labels are placed below the canvas to show the hexagon that was selected. There are two global integer properties added: HexHeight, and SelectPoints. HexHeight is the height of the hexagon in pixels, and SelectPoints is the array of the selected points of the hexagon when the user clicks with the mouse.

Drawing occurs in the Paint event of the canvas.

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint

  //Height of the hexagon

  HexHeight = 68

 

  Dim x, y as Integer

  //Draw Blue selected hexagons

  Dim MySelectPoints() as Double

  For x = 0 to SelectPoints.Ubound Step 2

    MySelectPoints = HexToPoints(HexHeight, SelectPoints(x), SelectPoints(x+1))

    g.ForeColor = RGB(173, 216, 230) //Light Blue

    g.FillPolygon(MySelectPoints)

    g.ForeColor = RGB(0, 0, 0) //Black

    DrawCoordinates(g, HexHeight, SelectPoints(x), SelectPoints(x+1))

  Next x

 

  //Draw black unselected hexagons

  Dim points() As Double

  For x = 0 to 4

    For y = 0 to 4

       points = HexToPoints(HexHeight,x,y)

       g.ForeColor = RGB(0, 0, 0) //Black

       g.DrawPolygon(points)

       DrawCoordinates(g, HexHeight, x, y)

    Next y

  Next x

End Sub

The height of the hexagon will be 68 pixels, and the selected hexagons are first drawn in a light blue colour.

A method called HexToPoints takes a row and column coordinate and converts it to six-points of a hexagon. These six points are used to draw the hexagon.

Public Function HexToPoints(height As double, row As Double, col As double) as double()

  // Start with the leftmost corner of the upper left hexagon.

  Dim width as double = HexWidth(height)

  Dim y as double = height/2

  Dim x as double = 0

 

  // Move down the required number of rows.

  y = y + row * height

 

  // If the column is odd, move down half a hex more.

  If (col mod 2) = 1 then

    y = y + height /2

  End if

 

  // Move over for the column number.

  x = x + col * (width * 0.75)

 

  Dim pointF() as double

  pointF.Append 0 //1-based array

  pointF.Append x

  pointF.Append y

 

  pointF.Append (x + width * 0.25)

  pointF.Append (y - height / 2)

 

  pointF.Append (x + width * 0.75)

  pointF.Append (y - height / 2)

 

  pointF.Append (x + width)

  pointF.Append y

 

  pointF.Append (x + width * 0.75)

  pointF.Append (y + height / 2)

 

  pointF.Append (x + width * 0.25)

  pointF.Append (y + height / 2)

 

  Return PointF

End Function

Code first calls the HexWidth method to determine the width of the hexagon.

Public Function HexWidth(height as double) as double

  //Return the width of the hexagon

  return (4 * (height/2/Sqrt(3)))

End Function

Trigonometry is used to determine the 30-60-90 degree triangle. The hexagon is four times as wide as the triangle and the total width for the triangle is (4 * (height/2/Sqrt(3))). Knowing the hexagons width, the HexToPoints method calculates the left vertex of the hexagon. The Y-coordinate is half the height plus the height times the row number. If the column is an odd number then the hexagon is moved down the y-axis by half of the height. The X-coordinate is 0 plus 0.75 of the hexagons width.

The For-Next loop in the Paint method has a step-2 meaning that it jumps every second value so that the selected hexagons are calculated in pairs of an x and y coordinate. Colour is changed to a light blue and a filled polygon is drawn. Black is the changed colour that is used when drawing the coordinates of the hexagon.

Public Sub DrawCoordinates(g as graphics, Height as Double, row as Integer, col as Integer)

  //Create the text to be written

  Dim MyCoord as String = "(" + row.ToText + "," + col.ToText + ")"

 

  //Calculate coordinates and centre text

  Dim Width as double = HexWidth(Height)

  Dim Centre as Double = MyCoord.Len*2

  Dim X1 as Double = col * (Width * 0.75) + width/2-Centre

  Dim Y1 as Double = row + Width/2-2 //(-2 is half the text height)

 

  // Move down the required number of rows.

  Y1 = Y1 + row * Height

 

  // If the column is odd, move down half a hex more.

  if (col mod 2) = 1 then

    Y1 = Y1 + Height /2

  end if

 

  //Draw the text

  g.DrawString(MyCoord, X1, Y1)

End Sub

Text to be written in each hexagon is created from the row and column to be drawn, and the width of the text, centre of the text, and calculated x and y drawing coordinates are determined. A DrawString command is used to draw the x and y coordinates inside the centre of the hexagon.

The bottom section of Paint code is drawing of the black-unselected hexagons, and two For-Next loops are created to draw 5 hexagons in the x-axis and y-axis direction.

Selection of the hexagon begins in the Canvas MouseDown event.

Dim row, col as Integer

PointToHex(X, Y, HexHeight, row, col)

LblHexagon.Text = "(" + row.ToText + "," + col.ToText + ")"

me.Invalidate

PointToHex is the method which maps a point on the Canvas to a hexagons row and column.

Public Sub PointToHex(X as Double, Y as Double, Height as Double, ByRef Row as Integer, ByRef Col as Integer)

  // Find the test rectangle containing the point

  Dim Width as double = HexWidth(Height)

  Col = (X / (Width * 0.75))

 

  If (Col mod 2 = 0) Then

    Row = (Y / Height)

  Else

    Row = ((Y - Height / 2) / height)

  End If

  // Find the test area

  Dim testx as Double = Col * Width * 0.75

  Dim testy as Double = row * Height

  If (Col mod 2 = 1) Then

       testy = testy + (Height / 2)

  End If

  // See if the point is above or

  // below the test hexagon on the left

  Dim is_above as Boolean = false

  Dim is_below as Boolean = false

  Dim dx as Double = x - testx

  if (dx < Width / 4) Then

    Dim dy as Double = y - (testy + height / 2)

    If (dx < 0.001) Then

       // The point is on the left edge of the test rectangle

       If (dy < 0) Then

         is_above = true

       End If

       If (dy > 0) Then

         is_below = true

       End If

    Elseif (dy < 0) Then

       // See if the point is above the test hexagon

       If (-dy / dx > Sqrt(3)) Then

         is_above = true

       End If

    else

       // See if the point is below the test hexagon

       If ((dy / dx) > Sqrt(3)) Then

         is_below = true

       End If

    End If

  End If

 

  // Adjust the row and column if necessary

  If (is_above) Then

    If (col Mod 2 = 0) Then

       row=row-1

    End If

    col=col-1

   

  ElseIf (is_below) Then

    If (col mod 2 = 1) Then

       row=row+1

    End If

    col=col-1

  End If

  //Add to selected hexagons

  SelectPoints.Append(row)

  SelectPoints.Append(col)

End Sub

This method doesn’t need to worry about upside down triangles and does need to work with odd- and even-numbered columns.

Figure 3. Hexagon Box

Selected Hexagon

The selected row and column are calculated and if the point lies to the left-part of the rectangle then it may be above or below the selected hexagon. This program performs some of the calculations to determine if the point is located above or below the hexagon and updates the row and column if needed. An invalidate call causes the canvas to be redrawn with the selected hexagon, redraws the hexagon location, and also redraws the black outline of unselected hexagons.

The complete Xojo program can be downloaded Github Hexagon Grid Xojo

This example was created on Windows 10 with Xojo 2019 r1.1 on 23 June 2019