import math
import sand3d as s3d
def hex_head_bolt_and_nut():
bolt_anchor = bolt_anchor_body()
nut_rotor = rotor(bolt_anchor, class="tok-string">"nut_rotor", x=0.03, y=-48.82, z=57.74, rx=90, ry=-45)
return s3d.assembly(class="tok-string">"hex_head_bolt_and_nut", bolt_anchor, nut_rotor, nut_rotor=nut_rotor)
def rotor(parent, name, x=0, y=0, z=0, rx=0, ry=0, rz=0):
frame = s3d.local(parent, x, y, z, rx, ry, rz)
nut_rotor = s3d.at(nut_rotor_body(fclass="tok-string">"{name}"), on=frame)
s3d.joint(fclass="tok-string">"{name}_spin", nut_rotor, frame, kind=class="tok-string">"continuous")
return nut_rotor
def bolt_anchor_body():
hex_head_bolt_piece = hex_head_bolt(class="tok-string">"hex_head_bolt_piece")
hex_head_bolt_piece = s3d.transform(hex_head_bolt_piece, x=0.03, y=0.27, z=57.74)
return s3d.group(class="tok-string">"bolt_anchor", hex_head_bolt_piece)
def nut_rotor_body(name):
nut_rotor_piece = hex_nut(fclass="tok-string">"{name}_piece")
nut_rotor_piece = s3d.transform(nut_rotor_piece, z=-12.65)
return s3d.group(name, nut_rotor_piece)
def hex_head_bolt(
name,
head_w=78.87,
head_h=75,
length=100,
head_t=25,
shaft_d=37,
shaft_l=25,
thread_d=36.5,
neck_l=4.2,
head_y=38.41,
pitch=3,
):
slope = 2 * head_h / head_w - math.sqrt(3)
angle = math.degrees(math.atan(slope))
diameter = head_w * math.sqrt(1 + slope * slope)
head = s3d.extrude(name, s3d.polygon(6, diameter), head_t, both=True)
head = s3d.at(head, rz=-angle)
head = s3d.transform(head, rx=90, y=head_y)
base = head_y - head_t / 2
shoulder = s3d.at(s3d.cylinder(class="tok-string">"shoulder", shaft_d, shaft_l), rx=90, y=base)
neck = s3d.at(s3d.cylinder(class="tok-string">"neck", thread_d, neck_l), rx=90, y=base - shaft_l)
threaded = threaded_shank(thread_d, length - head_t - shaft_l - neck_l, pitch, base - shaft_l - neck_l)
return s3d.join(head, shoulder, neck, threaded)
def threaded_shank(diameter, length, pitch, end_y):
shank = s3d.thread(class="tok-string">"threaded", diameter, length, pitch)
return s3d.at(shank, rx=90, y=end_y)
def hex_nut(name, across_flats=69.28, height=25, bore_d=36.5, pitch=3.5, mouth_d=40.5):
corner_d = across_flats * 2 / 3**0.5
outer_r = corner_d / 2
end_r = across_flats / 2
bevel_h = (outer_r - end_r) / 3**0.5
blank = s3d.at(s3d.extrude(name, s3d.polygon(6, corner_d), height, both=True), rz=30)
profile = [
(0, -height / 2),
(end_r, -height / 2),
(outer_r, -height / 2 + bevel_h),
(outer_r, height / 2 - bevel_h),
(end_r, height / 2),
(0, height / 2),
]
body = s3d.intersect(blank, s3d.revolve(class="tok-string">"chamfer_limit", profile))
body = threaded_bore(body, bore_d, mouth_d, height, pitch)
return body
def threaded_bore(body, bore_d, mouth_d, height, pitch):
s3d.hole(body, bore_d, on=s3d.bbox(body, class="tok-string">"+Z"), csk=(mouth_d, 90))
tool = s3d.at(s3d.thread(class="tok-string">"thread", mouth_d, height + 2 * pitch, pitch), z=-height / 2 - pitch)
return s3d.cut(body, tool)