Skip to content

Instantly share code, notes, and snippets.

@jtickle
Last active May 7, 2019 18:05
Show Gist options
  • Save jtickle/d4797e2b8866cbee9c2e399b5da8eedd to your computer and use it in GitHub Desktop.
Save jtickle/d4797e2b8866cbee9c2e399b5da8eedd to your computer and use it in GitHub Desktop.
Hilbert Terminal Filling Curve
#!/usr/bin/env python3
import shutil;
import collections;
import math;
import sys;
import argparse;
Point = collections.namedtuple('Point', ['x', 'y', 'n'])
HilbertAt = collections.namedtuple('HilbertAt', ['x', 'y', 'n'])
def hilbert (x, y, xi, xj, yi, yj, n):
if n <= 0:
yield Point(x = x + (xi + yi) / 2, y = y + (xj + yj) / 2, n=0)
else:
for i in hilbert(x, y,
yi/2, yj/2, xi/2, xj/2, n-1):
yield i
for i in hilbert(x + xi/2, y + xj/2,
xi/2, xj/2, yi/2, yj/2, n-1):
yield i
for i in hilbert(x + xi/2 + yi/2, y + xj/2 + yj/2,
xi/2, xj/2, yi/2, yj/2, n-1):
yield i
for i in hilbert(x + xi/2 + yi, y + xj/2 + yj,
-yi/2, -yj/2, -xi/2, -xj/2, n-1):
yield i
def roundPoints(p):
for pt in p:
yield Point(x=round(pt.x), y=round(pt.y), n=round(pt.n))
def getHilbertLinePoints(hil):
prev = False
i = 0
for cur in roundPoints(hil):
if prev:
if cur.x != prev.x:
neg = -1 if cur.x - prev.x < 0 else 1
for x in range(prev.x + neg, cur.x, neg):
yield Point(x = x, y = cur.y, n=i)
elif cur.y != prev.y:
neg = -1 if cur.y - prev.y < 0 else 1
for y in range(prev.y + neg, cur.y, neg):
yield Point(x = cur.x, y = y, n=i)
else:
print("Both X and Y changed")
exit();
i+=1
prev = cur
yield HilbertAt(**cur._asdict())
def ESC(val):
print("\033[" + val, end="")
def putAt(L, C, s):
ESC("{0};{1}H{2}".format(L, C, s))
def putOff(p, o, o2, s):
putAt(p.y + o.y + o2, p.x + o.x + o2, s)
def saveCursor():
ESC("s")
def restoreCursor():
ESC("u")
def clearScreen():
ESC("2J")
alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
def base36char(n):
return alphabet[ n % len(alphabet) ]
def main(depth, label, square):
ts = shutil.get_terminal_size()
width = ts.columns - 1
height = ts.lines - 4
off = Point(x=0, y=0, n=0)
if(square):
if(width < height):
height = width
off = Point(
x=off.x,
y=math.floor(((ts.lines - 4) - height) / 2),
n=off.n)
if(width > height):
width = height
off = Point(
x=math.floor(((ts.columns - 1) - width) / 2),
y=off.y,
n=off.n)
gen = hilbert(0, 0, width, 0, 0, height, depth)
points = getHilbertLinePoints(gen)
clearScreen()
for i in points:
if isinstance(i, HilbertAt):
putOff(i, off, 0, "#")
if(label):
putOff(i, off, 1, "\\")
putOff(i, off, 2, "({0},{1})".format(i.x, i.y))
else:
putOff(i, off, 0, base36char(i.n))
putAt(ts.lines - 4, 0, "HILBERT SPACE FILLING FOR YOUR TERMINAL!")
print( "\n----------------------------------------")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Fill your terminal with a Hilbert curve')
parser.add_argument('depth', type=int, default=1, nargs='?',
help="Depth of the hilbert curve")
parser.add_argument('--label', '-l', dest='label', action='store_true')
parser.add_argument('--square', '-s', dest='square', action='store_true')
args = parser.parse_args()
main(args.depth, args.label, args.square)
if(len(sys.argv) < 2):
print("Pro Tip: specify a nonzero integer depth as an argument for")
print("more interesting space-filling. Also, try -l or -s.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment