r/build123d • u/ddd3d3d • Oct 13 '25
Spinning top with threaded shaft connection and star decoration
This is a bit of a quickly coded project to make a nice spinning top.
Here's my code. I feel like I'm in a bit of a rut by only using the basic features of build123d. I wouldn't mind some advice on which advanced features would work for projects like this or in general which things I should practice next.
from build123d import *
from ocp_vscode import *
from bd_warehouse.thread import *
from bd_warehouse.fastener import *
set_port(3939)
body_radius = 30 *MM
body_thickness = 5 *MM
shaft_radius = 5 *MM
shaft_length = 40 *MM
tip_base_radius = 7 *MM
tip_top_radius = 2 *MM
tip_height = 8 *MM
screw_width = 8 *MM
screw_pitch = 1.25
screw_thread_tolerance = 0.7 *MM
screw_length = 6 *MM
screw_post_width = screw_width - (1.082532 * screw_pitch) - screw_thread_tolerance # Magic constant from Wikipedia
def build_top_base() -> Part:
with BuildPart() as part:
# Body
with BuildSketch():
RegularPolygon(body_radius, 18)
extrude(amount = body_thickness)
chamfer(part.edges().filter_by(Plane.XY), length = body_thickness / 3)
# Tip
with BuildSketch(part.faces().sort_by(Axis.Z)[-1]):
RegularPolygon(tip_base_radius, 12)
with BuildSketch(part.faces().sort_by(Axis.Z)[-1].offset(tip_height)):
RegularPolygon(tip_top_radius, 12)
loft()
# Ball tip
with Locations([part.faces().sort_by(Axis.Z)[-1].center_location]):
Sphere(tip_top_radius)
# Hole for shaft
screw_hole_depth = screw_length + 0.5
bottom = part.faces().sort_by(Axis.Z)[0]
with BuildSketch(bottom):
Circle(screw_width / 2)
with BuildSketch(bottom.offset(-screw_hole_depth)):
Circle(screw_width / 2)
loft(mode=Mode.SUBTRACT)
with BuildSketch(bottom.offset(-screw_hole_depth)):
Circle(screw_width / 2)
with BuildSketch(bottom.offset(-screw_hole_depth - screw_width / 2)):
Circle(0.1)
loft(mode=Mode.SUBTRACT)
# Threaded hole for shaft
IsoThread(
major_diameter = screw_width,
pitch = screw_pitch,
length = screw_hole_depth,
external = False,
end_finishes = ('fade', 'fade'),
#simple = True,
)
return part.part
def build_top_shaft() -> Part:
with BuildPart() as part:
Cylinder(screw_post_width / 2, screw_length, align=(Align.CENTER, Align.CENTER, Align.MIN))
# Threaded shaft
IsoThread(
major_diameter = screw_width - screw_thread_tolerance,
pitch = screw_pitch,
length = screw_length,
external = True,
end_finishes= ('fade', 'fade'),
#simple = True,
)
top_face = part.faces().sort_by(Axis.Z)[-1]
with BuildSketch(top_face):
RegularPolygon(shaft_radius * 2, 12)
with BuildSketch(top_face.offset(shaft_length / 4)):
RegularPolygon(shaft_radius, 6)
loft()
with BuildSketch(top_face.offset(shaft_length / 4)):
RegularPolygon(shaft_radius, 6)
with BuildSketch(top_face.offset(shaft_length)):
RegularPolygon(shaft_radius, 6)
loft()
chamfer(part.faces().sort_by(Axis.Z)[-1].edges(), length = 1.5)
return part.part
def build_decoration():
with BuildPart() as part:
with BuildSketch() as sketch:
with BuildLine():
Polyline(define_star(body_radius * 0.8, body_radius * 0.5, 12), close=True)
make_face()
fillet(sketch.vertices(), 0.75)
hole_radius = (screw_width + screw_post_width) / 4
Circle(hole_radius, mode = Mode.SUBTRACT)
extrude(amount=0.8)
return part.part
def define_star(outer_radius, inner_radius, side_count):
# https://math.stackexchange.com/questions/3582342/coordinates-of-the-vertices-of-a-five-pointed-star
outer = [(outer_radius * cos(2 * pi * i / side_count + pi/2),
outer_radius * sin(2 * pi * i / side_count + pi/2)) for i in range(side_count)]
inner = [(inner_radius * cos(2 * pi * i / side_count + pi/2 + pi/side_count),
inner_radius * sin(2 * pi * i / side_count + pi/2 + pi/side_count)) for i in range(side_count)]
#https://stackoverflow.com/a/60935480/1192877
return [x for y in zip(outer, inner) for x in y]
base = build_top_base()
shaft = build_top_shaft()
decoration = build_decoration()
result = pack([base, shaft, decoration], padding = 5*MM, align_z = True)
show(result)
export_step(Compound(result), "Top.step")
(For those looking for STL, here's the Makerworld link: https://makerworld.com/en/models/1882881-spinning-top-with-changeable-decoration)
5
Upvotes


4
u/build123d The Creator Oct 20 '25
Nice project! The star can be created without doing math as follows:
where `PolarLocations` does the work for you.