component
Adom Machine Pins, Fusion Library + Sample Board
Public Made by Adomby adom
One Fusion 360 .lbr with all four Adom press-fit machine pins (working 3D), plus a sample board (2D/3D/silkscreen) ganging all four together. Fully documented and rebuildable.
← Commit history
GLB: hemisphere solder paste (was full spheres), cut-out letter counters (fixed dropped-glyph bug), PRESS-FIT callout with arrow showing hole Ø vs pin Ø + gas-tight explanation, removed fake baked shadows
5 files changed
+56−22
AdomMachinePins-4pin-animated.glb⋯ 1 unchanged line ⋯
AdomMachinePins-complete.zip⋯ 1 unchanged line ⋯
screenshots/board-3d-render.png⋯ 1 unchanged line ⋯
screenshots/board-3d-top-silk.png⋯ 1 unchanged line ⋯
scripts/build_board_glb.py+56−22@@ -10,12 +10,23 @@ from shapely.geometry import Polygon, MultiPolygon from shapely.ops import unary_union def text_mesh(s, height_mm, thick_mm=0.12):- """Extruded silk text, normal +Z, reads correctly viewed from +Z (the wiki view). Centered on origin."""+ """Extruded silk text with REAL cut-out counters (holes in D,R,0,e...), normal +Z,+ reads correctly viewed from +Z (the wiki view). Centered on origin.""" tp=TextPath((0,0), s, size=height_mm, prop=FontProperties(family="DejaVu Sans", weight="bold"))- polys=[Polygon(pp).buffer(0) for pp in tp.to_polygons(closed_only=True) if len(pp)>=3]- geom=unary_union(polys)+ raw=[Polygon(pp).buffer(0) for pp in tp.to_polygons(closed_only=True) if len(pp)>=3]+ # even-odd fill: a contour is a HOLE if it sits inside an odd number of others.+ # Robust: union all solids, union all holes, subtract -> correct counters, nothing dropped.+ solids=[]; holes=[]+ for i,s_ in enumerate(raw):+ # depth = how many OTHER contours fully contain this one (full-polygon containment;+ # a centroid point would fall in the counter for O/D/e and misclassify the outline).+ depth=sum(1 for j,o in enumerate(raw) if j!=i and o.contains(s_))+ (holes if depth%2 else solids).append(s_)+ geom=unary_union(solids)+ if holes: geom=geom.difference(unary_union(holes)) parts=list(geom.geoms) if isinstance(geom,MultiPolygon) else [geom]- m=trimesh.util.concatenate([trimesh.creation.extrude_polygon(p,height=thick_mm) for p in parts if p.area>1e-6])+ meshes=[trimesh.creation.extrude_polygon(p, height=thick_mm) for p in parts if p.area>1e-6]+ m=trimesh.util.concatenate(meshes) m.apply_translation([-(m.bounds[0][0]+m.bounds[1][0])/2, -(m.bounds[0][1]+m.bounds[1][1])/2, 0]) return m @@ -115,30 +126,53 @@ for k,(c,barrel_r) in pin_info.items(): for j in range(n): th=2*np.pi*j/n s=trimesh.creation.icosphere(subdivisions=2,radius=BALL_R)- # seat the ball so it rests ON the pad surface (center one radius above board top)- s.apply_translation([c[0]+ring_r*np.cos(th), c[1]+ring_r*np.sin(th), board_top+BALL_R])+ s=s.slice_plane([0,0,0],[0,0,1],cap=True) # HEMISPHERE: flat bottom sits on the pad+ s.apply_translation([c[0]+ring_r*np.cos(th), c[1]+ring_r*np.sin(th), board_top]) add_mesh(s.vertices,s.faces,[0.62,0.63,0.66,1.0],f"ball_{k}_{j}",metal=True)- print(f" balls PIN_{k}: {n} x {BALL_D*1000:.2f}mm on ring r={ring_r*1000:.2f}mm")+ print(f" balls PIN_{k}: {n} hemispheres x {BALL_D*1000:.2f}mm on ring r={ring_r*1000:.2f}mm") -# --- silkscreen: real white text geometry on the board top (matches the Fusion 2D silk) ----LABELS={0:("MP-MED-STD","D1.1 R0.25"), 1:("MP-MED-SHORT","D1.1 R0.25"),- 2:("MP-LRG-STD","D3.45 R0.875"), 3:("MP-LRG-SHORT","D3.45 R0.875")}-SILK_H=0.0014 # 1.4mm text+# --- silkscreen: real white text with cut-out counters; shows hole Ø + pin Ø per pad ---+def place_text(txt, cx, cy, h_mm, color, name):+ t=text_mesh(txt, h_mm); t.apply_scale(0.001)+ t.apply_translation([cx, cy, board_top+0.00005])+ add_mesh(t.vertices, t.faces, color, name)++LABELS={0:("MP-MED-STD","hole Ø1.1 pin Ø1.2"),+ 1:("MP-MED-SHORT","hole Ø1.1 pin Ø1.2"),+ 2:("MP-LRG-STD","hole Ø3.45 pin Ø3.6"),+ 3:("MP-LRG-SHORT","hole Ø3.45 pin Ø3.6")}+WHITE=[0.97,0.97,0.97,1.0] for k,(c,barrel_r) in pin_info.items(): name,spec_s=LABELS[k]- y0 = c[1]-barrel_r-0.0028 # first line just below the pad- for li,txt in enumerate((name,spec_s)):- tm_txt=text_mesh(txt, SILK_H*1000) # returns mm-scaled, centered- tm_txt.apply_scale(0.001) # mm -> meters- tm_txt.apply_translation([c[0], y0-li*0.0019, board_top+0.00005])- add_mesh(tm_txt.vertices,tm_txt.faces,[0.97,0.97,0.97,1.0],f"silk_{k}_{li}")+ y0=c[1]-barrel_r-0.0028+ place_text(name, c[0], y0, 1.3, WHITE, f"silk_{k}_0")+ place_text(spec_s, c[0], y0-0.0018, 1.1, WHITE, f"silk_{k}_1") print(f" silk PIN_{k}: '{name}' / '{spec_s}'") -# --- animated contact shadow: a flat dark disc under each pin on the board top ----for k,(c,barrel_r) in pin_info.items():- disc=trimesh.creation.cylinder(radius=barrel_r*1.05, height=0.00002, sections=48)- disc.apply_translation([c[0], c[1], board_top+0.00003])- add_mesh(disc.vertices,disc.faces,[0.02,0.02,0.02,0.42],f"SHADOW_{k}")+# --- PRESS-FIT callout: amber text + leader line/arrow pointing at a hole, explaining pin>hole ---+AMBER=[0.98,0.74,0.10,1.0]+cxr,cyr=0.0245,0.0225 # empty board-centre anchor+place_text("PRESS-FIT", cxr, cyr+0.0022, 2.4, AMBER, "callout_0")+place_text("hole Ø1.1 pin Ø1.2", cxr, cyr, 1.5, AMBER, "callout_1")+place_text("pin 0.1mm wider = gas-tight fit", cxr, cyr-0.0020, 1.4, AMBER, "callout_2")+# leader line from the callout to the medium pin @ (40,10) base, on the board surface+tip=np.array([0.0385,0.0112]); start=np.array([0.0315,0.0175])+lead=trimesh.creation.cylinder(radius=0.00016, segment=[[start[0],start[1],board_top+0.00006],+ [tip[0],tip[1],board_top+0.00006]])+add_mesh(lead.vertices,lead.faces,AMBER,"callout_leader",metal=False)+# arrowhead cone at the tip+d=tip-start; d=d/np.linalg.norm(d)+head=trimesh.creation.cone(radius=0.00045,height=0.0011,sections=16)+# orient cone (+Z) to lie flat pointing along d+zc=np.array([0,0,1.]); axd=np.array([d[0],d[1],0.]); axd/=np.linalg.norm(axd)+v=np.cross(zc,axd); s_=np.linalg.norm(v); cth=np.dot(zc,axd)+if s_>1e-6:+ vx=np.array([[0,-v[2],v[1]],[v[2],0,-v[0]],[-v[1],v[0],0]])+ R=np.eye(3)+vx+vx@vx*((1-cth)/(s_*s_)); M=np.eye(4); M[:3,:3]=R+ head.apply_transform(M)+head.apply_translation([tip[0],tip[1],board_top+0.00006])+add_mesh(head.vertices,head.faces,AMBER,"callout_arrow",metal=False)+print(" callout: PRESS-FIT leader -> medium pin @ (40,10)") scene.export(OUT) print("exported",OUT)