A space-filling curve visits every cell of a grid exactly once without crossing itself. The Gosper curve (flowsnake) does it on a hexagonal grid, and you can draw it with a six-line L-system. This post turns it into a flat, 3D-printable ornament with manifold3d.
The L-system
Both symbols mean "step forward". Turn 60 degrees left or right between steps.
import math
rules = {'A': 'A-B--B+A++AA+B-', 'B': '+A-BB--B-A++A+B'}
s = 'A'
for _ in range(3): # 3 rounds = 343 steps
s = ''.join(rules.get(c, c) for c in s)
ang = x = y = 0.0
pts = [(0.0, 0.0)]
for c in s:
if c in 'AB':
x += math.cos(math.radians(ang))
y += math.sin(math.radians(ang))
pts.append((x, y))
elif c == '+':
ang += 60
elif c == '-':
ang -= 60
From path to printable plate
Thicken each step into a thin rectangle, union them all, and extrude 2.4 mm.
import manifold3d as M3
from manifold3d import CrossSection
xs = [p[0] for p in pts]; ys = [p[1] for p in pts]
cx, cy = (max(xs) + min(xs)) / 2, (max(ys) + min(ys)) / 2
sc = 76 / max(max(xs) - min(xs), max(ys) - min(ys)) # fit 76 mm
P = [((a - cx) * sc, (b - cy) * sc) for a, b in pts]
w = 0.75 # half line width: 1.5 mm line
segs, seen = [], set()
for a, b in zip(P, P[1:]):
k = tuple(sorted((tuple(round(v, 3) for v in a), tuple(round(v, 3) for v in b))))
if k in seen: # curve reuses some edges
continue
seen.add(k)
dx, dy = b[0] - a[0], b[1] - a[1]
seg = CrossSection.square([math.hypot(dx, dy) + 2 * w, 2 * w], True)
segs.append(seg.rotate(math.degrees(math.atan2(dy, dx)))
.translate([(a[0] + b[0]) / 2, (a[1] + b[1]) / 2]))
plate = CrossSection.batch_boolean(segs, M3.OpType.Add)
plate = max(plate.decompose(), key=lambda c: c.area()) # drop loose bits
solid = plate.extrude(2.4)
The + 2 * w in the rectangle length makes neighbouring segments overlap at the joints, so the path stays one piece.
Gotchas
- Round coordinates before hashing edges, or floating-point noise defeats the duplicate check.
- Keep the gap between lines at least 1.5 times the nozzle width (0.6 mm for a 0.4 mm nozzle), or the print fuses into a blob. Heighway dragon curve at 11 folds did exactly that for me; 9 folds works.
- Same trick works in 3D: Skilling's transpose algorithm gives a 3D Hilbert curve, and
Manifold.batch_hullof two spheres makes each tube segment.
Finished ornaments from this: Gosper curve and 3D Hilbert cube on Cults3D, $1.27 each.
Top comments (0)