What I am looking for is a method or class that allows me to display a list of hexagons in a grid. Ideally I would then be able to use some form of set-method to change the color/hatching/border of the individual hexagons.
The hexagons are stored using the axial coordinate system outlined in the guide by @amitp. But I can easily output their centers as xy-coordinates.
I feel like there might be a solution hidden somewhere in hexbin or RegularPolyCollection. But the former is a histogram method and the latter seems overly complex thanks to the DPI scaling.
So does anyone know of a library that provides a hexagonal grid? It doesn't have to be in matplotlib. I am also quite happy to use ASCII art or switch to R.
Here comes an implementation that allow you to set hexagonal cell the color you want and also allow to create custom border colors.
This is all hand made, just took 1hour using your reference site. You may have to adapt it to your needs, but seems working.
from tkinter import *
class HexaCanvas(Canvas):
""" A canvas that provides a create-hexagone method """
def __init__(self, master, *args, **kwargs):
Canvas.__init__(self, master, *args, **kwargs)
self.hexaSize = 20
def setHexaSize(self, number):
self.hexaSize = number
def create_hexagone(self, x, y, color = "black", fill="blue", color1=None, color2=None, color3=None, color4=None, color5=None, color6=None):
"""
Compute coordinates of 6 points relative to a center position.
Point are numbered following this schema :
Points in euclidiean grid:
6
5 1
.
4 2
3
Each color is applied to the side that link the vertex with same number to its following.
Ex : color 1 is applied on side (vertex1, vertex2)
Take care that tkinter ordinate axes is inverted to the standard euclidian ones.
Point on the screen will be horizontally mirrored.
Displayed points:
3
color3/ \color2
4 2
color4| |color1
5 1
color6\ /color6
6
"""
size = self.hexaSize
Δx = (size**2 - (size/2)**2)**0.5
point1 = (x+Δx, y+size/2)
point2 = (x+Δx, y-size/2)
point3 = (x , y-size )
point4 = (x-Δx, y-size/2)
point5 = (x-Δx, y+size/2)
point6 = (x , y+size )
#this setting allow to specify a different color for each side.
if color1 == None:
color1 = color
if color2 == None:
color2 = color
if color3 == None:
color3 = color
if color4 == None:
color4 = color
if color5 == None:
color5 = color
if color6 == None:
color6 = color
self.create_line(point1, point2, fill=color1, width=2)
self.create_line(point2, point3, fill=color2, width=2)
self.create_line(point3, point4, fill=color3, width=2)
self.create_line(point4, point5, fill=color4, width=2)
self.create_line(point5, point6, fill=color5, width=2)
self.create_line(point6, point1, fill=color6, width=2)
if fill != None:
self.create_polygon(point1, point2, point3, point4, point5, point6, fill=fill)
class HexagonalGrid(HexaCanvas):
""" A grid whose each cell is hexagonal """
def __init__(self, master, scale, grid_width, grid_height, *args, **kwargs):
Δx = (scale**2 - (scale/2.0)**2)**0.5
width = 2 * Δx * grid_width + Δx
height = 1.5 * scale * grid_height + 0.5 * scale
HexaCanvas.__init__(self, master, background='white', width=width, height=height, *args, **kwargs)
self.setHexaSize(scale)
def setCell(self, xCell, yCell, *args, **kwargs ):
""" Create a content in the cell of coordinates x and y. Could specify options throught keywords : color, fill, color1, color2, color3, color4; color5, color6"""
#compute pixel coordinate of the center of the cell:
size = self.hexaSize
Δx = (size**2 - (size/2)**2)**0.5
pix_x = Δx + 2*Δx*xCell
if yCell%2 ==1 :
pix_x += Δx
pix_y = size + yCell*1.5*size
self.create_hexagone(pix_x, pix_y, *args, **kwargs)
if __name__ == "__main__":
tk = Tk()
grid = HexagonalGrid(tk, scale = 50, grid_width=4, grid_height=4)
grid.grid(row=0, column=0, padx=5, pady=5)
def correct_quit(tk):
tk.destroy()
tk.quit()
quit = Button(tk, text = "Quit", command = lambda :correct_quit(tk))
quit.grid(row=1, column=0)
grid.setCell(0,0, fill='blue')
grid.setCell(1,0, fill='red')
grid.setCell(0,1, fill='green')
grid.setCell(1,1, fill='yellow')
grid.setCell(2,0, fill='cyan')
grid.setCell(0,2, fill='teal')
grid.setCell(2,1, fill='silver')
grid.setCell(1,2, fill='white')
grid.setCell(2,2, fill='gray')
tk.mainloop()
I tried to comment my code properly. If something seems unclear to you, please do not hesitate to ask for explanation.
Good luck Arthur Vaisse.
NB : script running on python 3. Drawing is a little jagged. Improve on Tk canvas can add anti alias as suggested in https://mail.python.org/pipermail/tkinter-discuss/2009-April/001904.html
You can use my hexalattice python module exactly for that purpose - creating and plotting hexagonal grids:
from hexalattice.hexalattice import *
hex_centers, _ = create_hex_grid(nx=5,
ny=5,
do_plot=True)
plt.show() # import matplotlib.pyplot as plt
Producing this plot:
See this answer for more examples: this answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With