lockerKeys/snap_on_templates.py

105 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python3
import cadquery as cq
from cadquery import exporters
import key_bittings
from key_bittings import BittingSpecification
MM_PER_IN = 25.4
extra_key_thickness = 0.2
text_size = 4
text_depth = 0.5
text_margin = 2
lishi_width = 18 - 0.3
lishi_depth = 5
lishi_height = 9.98
lishi_overhang_height = 2.25
lishi_overhang_width = 1
lishi_overhang_radius = 1 - .000000001 # workaround to fillet a part with the same thickness
corner_radius = 0.5
side_thickness = 1
bottom_thickness = 2
back_thickness = 1.5
# this number is somewhat estimated, but quite important
# it is the offset from the end of the pliers to the point of the cutter
lishi_cutter_offset = .54 * MM_PER_IN
key_guide_height = 12.5
notch_width = 1
notch_height = 1.5
notch_depth = 0.5
def lishi_template(spec: BittingSpecification, name: str, depth: float, profile: cq.Sketch):
key_guide_width = lishi_width/2 + side_thickness + spec.TFC - spec.BCC/2
result = (
cq
.Workplane("front")
.box(lishi_width + side_thickness * 2, lishi_depth + lishi_overhang_width, lishi_height + bottom_thickness)
.tag("lishi_interface")
.edges("not >Y").fillet(corner_radius)
)
# TODO: positioning could be better
result = (
result
.faces("<Y").workplane().move(0, bottom_thickness/2)
.rect(lishi_width, lishi_height).cutBlind(-lishi_depth)
)
result = (
result
.faces("<X", tag="lishi_interface").vertices(">Y and >Z")
.workplane(offset=-side_thickness, centerOption="CenterOfMass")
.rect(lishi_overhang_width, lishi_overhang_height, centered=False).extrude(-lishi_width)
.edges(">Z").edges("<Y").fillet(lishi_overhang_radius)
)
result = (
result
.faces(">Y", tag="lishi_interface").vertices(">X and <Z")
.workplane(centerOption="CenterOfMass")
.rect(key_guide_width, key_guide_height, centered=False).extrude(spec.key_thickness + extra_key_thickness + back_thickness, combine=False)
.tag("key_guide")
.edges("not <Y").fillet(corner_radius)
.faces(">X", tag="key_guide").vertices("<Z and <Y").workplane(centerOption="CenterOfMass").center(0, bottom_thickness + lishi_cutter_offset - depth)
.placeSketch(profile).cutThruAll()
.union(result) # this seems like a fairly bad way to do this, but it does work
)
result = (
result
.add(result.objects[0].Edges())
.faces(">Y", tag="key_guide").vertices(">XZ").workplane(centerOption="CenterOfMass")
# TODO: better positioning
.moveTo(lishi_width / 2 + side_thickness, -notch_height/2)
.rect(notch_width, notch_height).cutBlind(-notch_depth)
.faces(">Y").workplane(centerOption="CenterOfMass").text(name, text_size, -text_depth)
)
return result
spec = key_bittings.national_disc_tumbler
for name, depth in spec.depths.items():
profile = (
cq.Sketch()
.push([((spec.key_thickness + extra_key_thickness)/2, depth/2)])
.rect(spec.key_thickness + extra_key_thickness, depth)
# notch to hold key straight
.push([(spec.key_thickness + extra_key_thickness - 0.5, 0.5 + 0.5)])
.rect(1, 1, mode="s")
# fillet inner corners
.reset().vertices("not(>X or <X)") .fillet(0.3)
)
result = lishi_template(spec, name, depth, profile)
exporters.export(result, f'national_disc_tumbler_{name}.stl')