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 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 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 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.