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_hull of two spheres makes each tube segment.

Finished ornaments from this: Gosper curve and 3D Hilbert cube on Cults3D, $1.27 each.