Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active December 31, 2015 08:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nitaku/7960622 to your computer and use it in GitHub Desktop.
Save nitaku/7960622 to your computer and use it in GitHub Desktop.
Gosper hexes generator

See this Gist for the full source.

A python script that generates hexagons from a Gosper hex tiling. It returns 7^ORDER hexagons, where ORDER is the Gosper fractal order (hardcoded to 7, yielding 823,543 hexagons). The script can be modified to generate more hexagons. If you want to accommodate for N hexagons, you can find the order you need by using this equation: ORDER = ceil(log(N, 7)).

Unlike the client-side L-system implementations (see for example, the Gosper curve or the Hilbert curve), this program does not load at once into memory a huge string representing the whole fractal, but instead computes the L-system rules while writing the results to the output file. The memory occupation is always O(ORDER*L), where L is the length of strings in the system rules.

In order to write to the file line by line, Python's open() line buffering has been set up.

The result is saved in a CSV-compliant file (without header) named hexes.wkt.csv, in which each line represents a hexagon as a WKT POLYGON. This simple format offers the possibility for consumer scripts to load only the necessary amount of hexagons into memory, by reading them line by line. Therefore, the generator script can be run once to create a big file that can be used by different scripts, even if they do not need that many hexagons.

from __future__ import print_function
# hexagonal tiling walk directions
directions = [
{'x':+1, 'y':-1, 'z': 0},
{'x':+1, 'y': 0, 'z':-1},
{'x': 0, 'y':+1, 'z':-1},
{'x':-1, 'y':+1, 'z': 0},
{'x':-1, 'y': 0, 'z':+1},
{'x': 0, 'y':-1, 'z':+1}
]
# write a new hexagon
from shapely.geometry.polygon import Polygon
def write_hex(c, file):
# conversion from hex coordinates to rect
x = int(2*(c['x'] + c['z']/2.0))
y = 2*c['z']
hex = Polygon(((x, y+2),(x+1, y+1),(x+1, y),(x, y-1),(x-1, y),(x-1, y+1)))
print(hex.wkt, file=file)
# start the walk from the origin cell, facing east
position = {'x':0,'y':0,'z':0}
dir_i = 0
# print hexagons according to the given sequence and the global status
def emit(sequence, file):
global dir_i, position
for char in sequence:
if char == '+':
dir_i = (dir_i+1) % len(directions)
elif char == '-':
dir_i = dir_i-1
if dir_i == -1:
dir_i = 5
elif char == 'F':
dir = directions[dir_i]
position = {'x':position['x']+dir['x'], 'y':position['y']+dir['y'], 'z':position['z']+dir['z']}
write_hex(position, file)
# emit characters executing a Lindenmayer system given an axiom, a number of steps and rules
def fractalize(input, steps, rules, file):
if steps == 0:
emit(input, file)
return
for char in input:
output = ''
if char in rules:
output += rules[char]
else:
output += char
fractalize(output, steps-1, rules, file)
# determine the order of the fractal
ORDER = 8
# bufsize is 1: line-by-line
with open('hexes.wkt.csv', 'w', 1) as output:
# write the origin
write_hex(position, output)
fractalize(
file = output,
input = 'A',
steps = ORDER,
rules = {
'A': 'A+BF++BF-FA--FAFA-BF+',
'B': '-FA+BFBF++BF+FA--FA-B'
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment