DEV Community

Cover image for The Tusi couple: 8 beads in straight lines that roll as a circle (3D printable, Python)
Black
Black

Posted on

The Tusi couple: 8 beads in straight lines that roll as a circle (3D printable, Python)

Eight beads, each locked in its own straight slot. Push one and all eight roll around the dial as a perfect circle. This is the Tusi couple, found by the Persian astronomer Nasir al-Din al-Tusi in 1247, and it takes surprisingly little code to turn it into a support-free desk toy. The model is generated in Python with manifold3d.

Tusi couple astrolabe

The geometry in one line

Roll a disc of radius r = R/2 inside a circle of radius R. Every point on the small disc's rim moves along a straight diameter of the big circle. For a bead on slot angle b, its distance from the centre when the disc has turned to angle th is:

q = 2*r*math.cos(th - b/2)
pos = (q*math.cos(b/2), q*math.sin(b/2))
Enter fullscreen mode Exit fullscreen mode

q swings between +R and -R, so the bead slides end to end of its slot and never leaves the line. Put eight pegs evenly round the small disc and you get eight beads on eight lines, 22.5 degrees apart. Seen together they trace a circle that appears to roll, even though nothing in the dial moves in a circle except the hidden disc.

Building the parts

The dial is a cylinder with 16 half-slots cut through the cover (8 diameters = 16 radii), each a rectangle plus a round end:

def slot2d(a):
    L = R + SLOT/2 + 0.1
    s = CS.square([L, SLOT]).translate([0, -SLOT/2])
    s = s + CS.circle(SLOT/2, 24).translate([L, 0])
    return s.rotate(math.degrees(a))

cut2d = batch_union([slot2d(math.pi*k/NB) for k in range(2*NB)] + [CS.circle(14.0, 96)])
Enter fullscreen mode Exit fullscreen mode

The rolling disc carries eight pegs on its rim circle, and each bead is a truncated sphere with a blind hole that presses onto a peg. The bead holes are 0.16 mm wider than the pegs, enough for a snug press fit on most printers.

Checking it before printing

The script places every part at a given disc angle and checks the overlaps:

b, f, p, bb = assembled(40)
print('body^disc', (b ^ p).volume(), 'body^beads', (b ^ bb).volume())
Enter fullscreen mode Exit fullscreen mode

Any non-zero volume means two parts collide at that angle. Sweeping th through a full turn catches a slot that is too short or a peg that hits the cover. len(m.decompose()) confirms each part is one solid piece.

Making it look like an astrolabe

The engraving is all 2D cross-sections cut 0.6 mm into the top face: 64 degree ticks (long every fourth), three rings, and sixteen eight-point stars made from two rotated hollow squares. The hanging "kursi" (throne) on top is a few unioned circles rounded with offset(+1.2) then offset(-1.2), which fillets every inside corner in two calls.

Tusi Couple Astrolabe on Cults3D · on Payhip

Takeaways

  • Find the closed-form motion first (q = 2r cos(th - b/2)), then build parts around it.
  • Intersect assembled parts at several angles to catch collisions before printing.
  • offset(+d).offset(-d) is a cheap fillet for 2D outlines.

The model is licensed so you can print it and sell the prints; the files stay mine. More designs: Cults3D · patreon.com/123black

Top comments (0)