lockerKeys/key_decoder.py

64 lines
1.5 KiB
Python
Executable File

#!/usr/bin/env python3
import cadquery as cq
from cadquery import exporters
import key_bittings
from key_bittings import BittingSpecification
kerf = .11
bitting_width = 5
text_size = 5
text_gap = 2
margins = 5
margin_radius = 2
def bitting(loc: cq.Location, name: str, depth: float):
# can only make text in a 3D workplane, so make it in 3D and extract the face
text = (
cq.Workplane()
.text(name, fontsize=text_size, distance=1, valign="top", halign="center")
.edges("<Z")
)
return (
cq.Sketch()
.push([(0, depth/2)]).rect(bitting_width, depth - kerf)
.push([(0, -text_gap)]).face(text.vals())
.moved(loc)
)
def decoder_card(spec: BittingSpecification):
result = (
cq.Sketch()
.rect(margins * 2 + bitting_width * len(spec.depths),
margins * 2 + text_size + text_gap + max(*spec.depths.values()))
.vertices().fillet(margin_radius).reset()
)
depths = iter(spec.depths.items())
result = (
result
.rarray(bitting_width, 0, len(spec.depths), 1)
.each(lambda loc: bitting(loc, *next(depths)), mode="s")
)
return result
sketch = decoder_card(key_bittings.national_disc_tumbler)
# for preview/export purposes, a 3D object is more convenient
result = cq.Workplane("front").workplane().placeSketch(sketch).extrude(1)
exporters.export(result, "national_disc_tumbler_decoder.svg", opt={
"showAxes": False,
"projectionDir": (0, 0, 1),
"strokeColor": (255, 0, 0),
})