Glacier
Glacier draws a grid of interconnecting hexagonal elements with a recursive algorithm. The grid fades out after a certain amount of tiles. The algorithm contains a bug in the way hexes are spaced, but this actually creates a nice visual effect: the glaciers start drifting apart the further they are from the core. A global warming bug!
Script
size(600, 600)
hexwork = {}
class Hex:
def __init__(self, x, y, w, spacing=0):
#Creates a new hexagonal at position x, y
#with the given width w, and optional spacing.
#Adds itself to the hexwork list.
self.x = x
self.y = y
self.w = w
self.spacing = spacing
self.sides = []
for i in range(6):
self.sides.append(None)
global hexwork
hexwork[(self.x,self.y)] = self
self.index = len(hexwork)
def draw(self, tag=False, visit=None):
#Draws this hexagonal on screen.
#Optionally, tags the hexagonal with its index
#in the hexwork list.
#Additionally, you can supply a visit function
#that accepts this self as a parameter.
if visit != None: visit(self)
w = self.w * 0.5
star(self.x, self.y, 6, w, w*1.155)
if tag:
fontsize(w*0.25)
f = fill()
fill(f.r, f.g, f.b, 1)
align(CENTER)
text(str(self.index), self.x-self.w*0.5, self.y, self.w)
fill(f)
def rdraw(self, tag=False, visit=None, degrade=True, root=None):
#Recursive draw:
#draw all neighbours as well,
#and their neighbours, and so on.
if degrade == True:
f = fill()
fill(f.r, f.g, f.b, f.a * 0.98)
self.draw(tag, visit)
if root != None: line(self.x,self.y,root.x,root.y)
for side in self.sides:
if side != None and side != root:
side.rdraw(tag, visit, degrade, root=self)
def grow(self, max=6):
#Creates neighbouring hexes for this hexagonal.
#Creates all neighbours by default, or a given max
#of random neighbours.
if max < 1 or max > 6: return
#The centerpoint offsets for neighbouring hexes.
from random import shuffle
center = [(0,-1),
(-0.865,-0.5),
(-0.865,0.5),
(0,1),
(0.865,0.5),
(0.865,-0.5)]
shuffle(center)
center = center[:max]
#center.sort() #doesn't do what supposed to do
#Create neighbours only if the neighbour does
#not exist yet: if it is not defined by this
#hex as a neighbour already, or its position
#occurs in the hexwork list (and thus it is
#already defined as someone else's neighbour).
for i in range(max):
dx, dy = center[i]
dx = dx * (self.w+self.spacing) + self.x
dy = dy * (self.w+self.spacing) + self.y
global hexwork
if self.sides[i] == None and not hexwork.has_key((dx,dy)):
self.sides[i] = Hex(dx, dy, self.w)
self.sides[i].sides[(i+3)%6] = self
def rgrow(self, max=6):
#Recursive growth:
#grow neighbours for this hex,
#grow neighbours for each neighbour, and so on.
if max > 0:
self.grow(max)
for side in self.sides:
if side != None:
side.rgrow(max-1)
def visit(hex):
scale(random(0.98,1.01))
rotate(0.1)
root = Hex(400,400,70, spacing=100)
root.rgrow()
nofill()
stroke(0.2,0.2,0.2)
strokewidth(0.5)
rect(0,0,WIDTH,HEIGHT)
font("Arial")
r = random(0.5,1)
fill(0,0.5,r,0.75)
stroke(0,0.5,r,0.75)
strokewidth(0.25)
root.rdraw(tag=True, visit=visit)