Hex Pattern Lampshade
A bell-shaped pendant lampshade for an E26/E27 socket, perforated with 252 staggered tall hexagonal holes that cast a pattern of light and shadow. The outline is one formula, and each row's hole width follows the local circumference, so the holes grow larger as the shade flares out. The top plate has a 40.5 mm hole meant to be clamped by the socket's shade ring; measure your own socket and adjust socket_d. It measures 170 x 170 x 140 mm. Print it upside down with the top plate on the bed: the walls stay within 27 degrees of vertical and the hole roofs are 50 degrees from horizontal, so no supports are needed. Use PETG and LED bulbs only (no incandescent or halogen); you can change the height, top and bottom radius, flare, wall and top plate thickness, socket hole diameter, hole count, rows, row pitch, rib width and roof angle.
# Hex Pattern Pendant Lampshade - bell-shaped shade with staggered hexagonal holes (E26 socket)
# Instead of an irregular cell pattern, the holes are tall hexagons in a staggered
# arrangement that can be placed by calculation.
# In use: the top plate (z=H) has the socket hole. The bottom is open.
# Print it upside down (top plate on the bed).
@param 100..200 desc:"Height (mm)"
H = 140
@param 30..60 desc:"Top (top plate) radius (mm)"
r_top = 40
@param 50..120 desc:"Bottom (opening) radius (mm)"
r_bot = 85
@param 1.0..3.0 step:0.1 desc:"Flare exponent (higher = more bell-shaped)"
flare = 1.6
@param 1.2..3 step:0.1 desc:"Wall thickness (mm)"
wall = 2.0
@param 2..5 step:0.5 desc:"Top plate thickness (mm)"
top_t = 3.0
@param 28..45 step:0.5 desc:"Socket hole diameter (for an E26/E27 shade ring) (mm)"
socket_d = 40.5
@param 12..36 desc:"Holes per ring"
n_cell = 28
@param 3..14 desc:"Number of hole rows"
n_row = 9
@param 8..20 step:0.5 desc:"Row pitch (mm)"
pv = 12.0
@param 1.2..4 step:0.1 desc:"Rib width between holes (mm)"
rib = 2.0
@param 45..60 desc:"Hole roof angle from horizontal (deg)"
roof_deg = 50
s3 = sqrt(3)
# Outline radius: r_top at the top (rising vertically) -> r_bot at the bottom (flared)
def rr(z) = r_top + (r_bot - r_top) * (1 - z / H) ** flare
# ---- Shell: walk down the outer points, then up the inner ones, to make a band profile and revolve it ----
n_sp = 20
dz = H / n_sp
prof = [(if i <= n_sp then (rr(i * dz), i * dz) else (rr((2 * n_sp + 1 - i) * dz) - wall, (2 * n_sp + 1 - i) * dz)) for i in range(2 * n_sp + 2)]
$shell = workplane XZ | polyline prof | revolve Z
# ---- Top plate (with socket hole) ----
$top = cylinder (r_top - wall / 2) top_t | floor | translate 0 0 (H - top_t)
socket = cylinder (socket_d / 2) (top_t + 2) | floor | translate 0 0 (H - top_t - 1)
body = ($shell + $top) - socket
# ---- Holes: tall hexagons with vertices at top and bottom. Width = circumference of that row / hole count ----
z0 = 16
tr = tan(roof_deg)
# Hole half-width: circumference / hole count minus the rib, capped so the roof fits within the row pitch
def ha(z) = min(pi * rr(z) / n_cell - rib / 2, (pv - rib * 1.3 - 1) / tr)
# Hole half-height (row pitch = full height - roof, so adjacent rows interlock) and half-length of the vertical sides
def hh(z) = (pv + ha(z) * tr - rib * 1.3) / 2
def sv(z) = hh(z) - ha(z) * tr
def cellhole(z, ang) = workplane YZ
| polyline [(0, hh(z)), (ha(z), sv(z)), (ha(z), -sv(z)),
(0, -hh(z)), (-ha(z), -sv(z)), (-ha(z), sv(z))]
| extrude 14
| translate (rr(z) - 8) 0 z
| rotate 0 0 ang
def row(j) = union [cellhole(z0 + j * pv, (360 / n_cell) * (i + (j % 2) * 0.5)) for i in range(n_cell)]
holes = union [row(j) for j in range(n_row)]
body - holes