Bag Clip
A one-piece bag clip that needs no assembly: a C-shaped leaf-spring hinge joins the two arms, and a snap hook at the tip locks them shut. A half-round ridge on the upper arm presses into a groove in the lower arm to crimp the bag closed. The clip is printed slightly open, so the hinge spring keeps the arm pressed against the hook when closed. It measures about 115 x 24 x 12 mm and prints flat with no supports; PETG is recommended for the hinge and hook. You can change the arm length, clip width, hinge thickness, snap engagement and the opening angle as printed.
# Bag Clip - one-piece print with a flexure hinge and a snap hook
#
# A single part printed flat (an XY profile extruded clip_w along Z).
# Lower arm: y = -gap/2 - t .. -gap/2 (fixed side). Its tip carries a foot and the hook (post + barb)
# Upper arm: y = gap/2 .. gap/2 + t when closed. Printed open by open_deg
# Hinge: a strip of width hinge_t bent into a C-shaped leaf spring (wire | offset). The open state is its
# natural shape, so when closed the hinge spring presses the upper arm against the underside of the barb
# Seal: a half-round ridge under the upper arm enters a groove in the lower arm and crimps the bag
# Origin: at the hinge-side root of the arms, in the middle of the gap (0,0).
@param 60..200 step:5 desc:"Clip length (arm length, mm)"
length = 100
@param 8..20 step:1 desc:"Clip width (print height, mm)"
clip_w = 12
@param 0.8..2 step:0.1 desc:"Hinge strip thickness (mm)"
hinge_t = 1.2
@param 0.4..1.2 step:0.1 desc:"Snap engagement (mm)"
engage = 0.7
@param 0..20 step:1 desc:"Opening angle as printed (deg)"
open_deg = 8
t = 4 # arm thickness
gap = 1 # gap between the arms when closed
L = length
w = clip_w
# --- Hinge (C-shaped leaf spring) -------------------------------------------
leg = 8 # length of the straight hinge sections
yc = gap / 2 + t - hinge_t / 2 # strip center line (flush with the outer arm faces)
hinge = wire [(2, yc), (-leg, yc),
arc (-leg, yc) (-leg - yc, 0) (-leg, -yc),
(2, -yc)]
| offset (hinge_t / 2)
| extrude w
# --- Seal (ridge and groove; concentric when closed, radius difference bag_clear leaves room for the bag) ----
rr = 1.0 # ridge radius (centered in the gap, y=0)
bag_clear = 0.15
seal_x0 = 10
seal_x1 = L - 8
seal_len = seal_x1 - seal_x0
ridge = cylinder rr seal_len | rotate 0 90 0
| translate ((seal_x0 + seal_x1) / 2) 0 (w / 2)
groove = cylinder (rr + bag_clear) (seal_len + 2) | rotate 0 90 0
| translate ((seal_x0 + seal_x1) / 2) 0 (w / 2)
# --- Upper arm (opened by open_deg about the lower corner of its root) -------------------------
upper = box L t w | floor | translate (L / 2) (gap / 2 + t / 2) 0
| union ridge
| rotate 0 0 open_deg origin:(0, gap / 2, 0)
# --- Lower arm + snap hook ----------------------------------------
c = 0.5 # clearance between arm tip and post
post_t = 1.8 # post thickness (cantilever beam)
foot_t = 1.5 # foot below the lower arm (lowers the post root to lengthen the beam)
y_low = -(gap / 2 + t) # underside of the lower arm
by = gap / 2 + t + 0.2 # underside of the barb (closed upper arm top + 0.2)
ramp_h = 1.2 * (c + engage + 0.2) # height of the barb ramp (about 50 deg)
post_top = by + ramp_h + 0.5
px = L + c # inner face of the post
lower = box L t w | floor | translate (L / 2) (-(gap / 2 + t / 2)) 0
| diff groove
foot = box (6 + c + post_t) foot_t w | floor
| translate (L - 6 + (6 + c + post_t) / 2) (y_low - foot_t / 2) 0
post = box post_t (post_top - y_low + foot_t) w | floor
| translate (px + post_t / 2) ((post_top + y_low - foot_t) / 2) 0
# The barb tip sits engage inside the arm tip (x=L); it reaches out further by the post clearance c
barb = polyline [(px + 0.2, by), (L - engage, by), (px + 0.2, by + ramp_h)]
| extrude w
union [lower, foot, post, barb, hinge, upper]