mirror of
https://github.com/ervanalb/keygen.git
synced 2025-12-17 05:45:23 +00:00
The sad realization that STL import/export is not good enough to cache keyblanks
This commit is contained in:
27
scad/fm.scad
Normal file
27
scad/fm.scad
Normal file
@@ -0,0 +1,27 @@
|
||||
use <keygen.scad>
|
||||
include <fm.gen.scad>
|
||||
|
||||
bitting_code = "1526985";
|
||||
|
||||
// The FM keyblank can be used in many key systems
|
||||
// This is the depth table for Best A2 system
|
||||
|
||||
cut_locations = [for(i=[.080, .230, .380, .530, .680, .830, .980]) -i*25.4];
|
||||
|
||||
depth_table = [for(i=[0.318:-0.0125:0.205]) i*25.4];
|
||||
|
||||
heights = key_code_to_heights(bitting_code, depth_table);
|
||||
|
||||
difference() {
|
||||
key_blank(outline_points,
|
||||
warding_points,
|
||||
outline_paths=outline_paths,
|
||||
engrave_right_points=engrave_points,
|
||||
engrave_right_paths=engrave_paths,
|
||||
engrave_left_points=engrave_points,
|
||||
engrave_left_paths=engrave_paths,
|
||||
offset=[-outline_points[103][0], -outline_points[96][1]],
|
||||
milling_offset=30,
|
||||
plug_diameter=10.8712);
|
||||
key_bitting(heights, cut_locations, .7874);
|
||||
}
|
||||
169
scad/keygen.scad
Normal file
169
scad/keygen.scad
Normal file
@@ -0,0 +1,169 @@
|
||||
$inf=1000;
|
||||
$eps=.01;
|
||||
|
||||
function key_move(points, offset) = [
|
||||
for(p=points) [p[0] + offset[0],
|
||||
p[1] + offset[1]]
|
||||
];
|
||||
|
||||
module key_outline(outline_points, thickness, outline_paths=undef) {
|
||||
rotate(-90, [0, 1, 0]) rotate(-90, [0, 0, 1]) // Rotate into the correct plane
|
||||
linear_extrude(height=thickness, center=true) // Extrude the key outline
|
||||
polygon(points=outline_points, paths=outline_paths); // Draw the outline
|
||||
}
|
||||
|
||||
module key_blade(warding, plug_diameter=0) {
|
||||
// Draw the blade to infinity in Y
|
||||
// optionally intersected with the plug cylinder
|
||||
// to round the bottom
|
||||
intersection() {
|
||||
rotate(180, [0, 0, 1]) rotate(90, [1, 0, 0])
|
||||
linear_extrude(height=2*$inf, center=true)
|
||||
polygon(warding);
|
||||
|
||||
// Draw the plug, if a plug diameter is specified
|
||||
if(plug_diameter > 0) {
|
||||
// Draw infinite cylinder in -Y
|
||||
translate([0, 0, 0.5*plug_diameter]) rotate(90, [1, 0, 0])
|
||||
cylinder(r=0.5*plug_diameter, h=$inf, center=true, $fn=$fn ? 4*$fn : 48);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module key_x_line(length) {
|
||||
// Hack to draw a line in X
|
||||
// since OpenSCAD does not support line primitives
|
||||
// Take a 2D square and rotate it
|
||||
// When it is orthogonal to the XY plane,
|
||||
// it projects down to a line
|
||||
rotate(90, [1, 0, 0])
|
||||
square([length, length], center=true);
|
||||
}
|
||||
|
||||
module key_warding_cutter(warding, blade_height, cutter_radius, left) {
|
||||
neg = left ? -1 : 1;
|
||||
translate([neg * cutter_radius, 0, 0])
|
||||
rotate_extrude($fn=$fn ? 4*$fn : 48)
|
||||
translate([neg * cutter_radius, 0])
|
||||
difference() {
|
||||
translate([0, 0.5*blade_height])
|
||||
square([2 * cutter_radius, blade_height], center=true);
|
||||
minkowski() {
|
||||
translate([neg * 1.5 * cutter_radius, 0])
|
||||
key_x_line(3 * cutter_radius);
|
||||
polygon(warding);
|
||||
}
|
||||
polygon(warding);
|
||||
}
|
||||
}
|
||||
|
||||
module key_engrave(engrave_points, engrave_depth, left, thickness, engrave_paths=undef) {
|
||||
translate([(left ? -1 : 1) * 0.5*thickness, 0, 0]) rotate(-90, [0, 1, 0]) rotate(-90, [0, 0, 1]) // Translate and rotate into the correct soot
|
||||
linear_extrude(height=2*engrave_depth, center=true) // Extrude the key outline
|
||||
polygon(points=engrave_points, paths=engrave_paths); // Draw the outline
|
||||
}
|
||||
|
||||
module key_blank(outline_points,
|
||||
warding,
|
||||
outline_paths=undef,
|
||||
engrave_right_points=[],
|
||||
engrave_right_paths=undef,
|
||||
engrave_left_points=[],
|
||||
engrave_left_paths=undef,
|
||||
bow_thickness=0,
|
||||
engrave_depth=.1,
|
||||
plug_diameter=0,
|
||||
offset=[0, 0],
|
||||
cutter_radius=18,
|
||||
milling_offset=0) {
|
||||
|
||||
// Find the bounding box of the warding
|
||||
warding_min = [min([for(e=warding) e[0]]), min([for(e=warding) e[1]])];
|
||||
warding_max = [max([for(e=warding) e[0]]), max([for(e=warding) e[1]])];
|
||||
|
||||
// Apply the given offset to the outline,
|
||||
// holes, and engrave
|
||||
outline_adj = key_move(outline_points, offset);
|
||||
engrave_left_adj = key_move(engrave_left_points, offset);
|
||||
engrave_right_adj = key_move(engrave_right_points, offset);
|
||||
|
||||
// Move the warding profile
|
||||
// so that it is centered in X
|
||||
// and non-negative in Y
|
||||
warding_offset = [-0.5 * (warding_min[0] + warding_max[0]),
|
||||
-warding_min[1]];
|
||||
warding_adj = key_move(warding, warding_offset);
|
||||
|
||||
// Infer various key properties
|
||||
thickness = (bow_thickness == 0) ? abs(warding_max[0] - warding_min[0]) : bow_thickness;
|
||||
blade_height = abs(warding_max[1] - warding_min[1]);
|
||||
|
||||
// Cut out the warding milling artifacts
|
||||
// from the bow
|
||||
difference() {
|
||||
// Create the bulk of the keyblank
|
||||
// by intersecting the outline
|
||||
// with the warding profile
|
||||
// and the plug
|
||||
intersection() {
|
||||
// Draw the key outline and holes
|
||||
key_outline(outline_adj, thickness, outline_paths);
|
||||
|
||||
// Draw the blade, and a giant box where the bow is
|
||||
// so that we don't wipe out the bow
|
||||
// when the intersection happens
|
||||
union() {
|
||||
// Fill +Y half-space
|
||||
translate([0, $inf/2+milling_offset, 0])
|
||||
cube([$inf, $inf, $inf], center=true);
|
||||
|
||||
key_blade(warding_adj, plug_diameter);
|
||||
}
|
||||
}
|
||||
// Draw the milling wheels that cut the warding
|
||||
if(cutter_radius != 0) {
|
||||
translate([0, milling_offset, 0])
|
||||
union() {
|
||||
key_warding_cutter(warding_adj, blade_height, cutter_radius, false);
|
||||
key_warding_cutter(warding_adj, blade_height, cutter_radius, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the engraveing
|
||||
key_engrave(engrave_right_adj, engrave_depth, false, thickness, engrave_right_paths);
|
||||
key_engrave(engrave_left_adj, engrave_depth, true, thickness, engrave_left_paths);
|
||||
}
|
||||
}
|
||||
|
||||
function key_code_to_heights(code, depth_table) = [for(i=key_enum(code)) depth_table[search(code[i], "0123456789")[0]]];
|
||||
|
||||
module key_bitting_cutter(flat, angle, tool_height) {
|
||||
polygon([[-0.5 * flat, 0],
|
||||
[0.5 * flat, 0],
|
||||
[0.5 * flat + tan(0.5 * angle) * tool_height, tool_height],
|
||||
[0.5 * flat - tan(0.5 * angle) * tool_height, tool_height]]);
|
||||
}
|
||||
|
||||
module key_bitting(heights,
|
||||
locations,
|
||||
flat,
|
||||
angle=100,
|
||||
cutter_width=5,
|
||||
cutter_height=5) {
|
||||
// Rotate the cutting tool to the proper orientation
|
||||
rotate(-90, [0, 0, 1]) rotate(90, [1, 0, 0])
|
||||
// Union together a handful of trapezoids
|
||||
// that comprise the cuts
|
||||
union() {
|
||||
for(i=key_enum(heights)) {
|
||||
// Move to the proper location and height
|
||||
translate([locations[i], heights[i]])
|
||||
linear_extrude(height=cutter_width, center=true)
|
||||
key_bitting_cutter(flat, angle, cutter_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function key_lkup(ks, vs, k) = vs[search([k], [for(ki=ks) [ki]])[0]];
|
||||
|
||||
function key_enum(l) = len(l) > 0 ? [for(i=[0:len(l)-1]) i] : [];
|
||||
82
scad/schlage.scad
Normal file
82
scad/schlage.scad
Normal file
@@ -0,0 +1,82 @@
|
||||
use <keygen.scad>
|
||||
include <schlage.gen.scad>
|
||||
|
||||
module schlage_classic(bitting="",
|
||||
outline_name="5-pin",
|
||||
warding_name="C") {
|
||||
|
||||
name = "Schlage Classic";
|
||||
|
||||
/*
|
||||
Bitting is specified from bow to tip, 0-9, with 0 being the shallowest cut and 9 being the deepest.
|
||||
Example: 25363
|
||||
*/
|
||||
|
||||
outlines_k = ["5-pin",
|
||||
"6-pin"];
|
||||
outlines_v = [[outline_5pin_points, outline_5pin_paths,
|
||||
[-outline_5pin_points[92][0], -outline_5pin_points[98][1]],
|
||||
engrave_5pin_points,
|
||||
engrave_5pin_paths],
|
||||
[outline_6pin_points, outline_6pin_paths,
|
||||
[-outline_6pin_points[92][0], -outline_6pin_points[98][1]],
|
||||
engrave_6pin_points,
|
||||
engrave_6pin_paths]];
|
||||
wardings_k = ["C",
|
||||
"CE",
|
||||
"E",
|
||||
"EF",
|
||||
"F",
|
||||
"FG",
|
||||
"H",
|
||||
"J",
|
||||
"K",
|
||||
"L"];
|
||||
wardings_v = [warding_c_points,
|
||||
warding_ce_points,
|
||||
warding_e_points,
|
||||
warding_ef_points,
|
||||
warding_f_points,
|
||||
warding_fg_points,
|
||||
warding_h_points,
|
||||
warding_j_points,
|
||||
warding_k_points,
|
||||
warding_l_points];
|
||||
|
||||
outline_param = key_lkup(outlines_k, outlines_v, outline_name);
|
||||
outline_points = outline_param[0];
|
||||
outline_paths = outline_param[1];
|
||||
offset = outline_param[2];
|
||||
engrave_points = outline_param[3];
|
||||
engrave_paths = outline_param[4];
|
||||
|
||||
warding_points = key_lkup(wardings_k, wardings_v, warding_name);
|
||||
|
||||
cut_locations = [for(i=[.231, .3872, .5434, .6996, .8558, 1.012]) i*25.4];
|
||||
depth_table = [for(i=[0.335:-0.015:0.199]) i*25.4];
|
||||
|
||||
heights = key_code_to_heights(bitting, depth_table);
|
||||
|
||||
difference() {
|
||||
if($children == 0) {
|
||||
key_blank(outline_points,
|
||||
warding_points,
|
||||
outline_paths=outline_paths,
|
||||
engrave_right_points=engrave_points,
|
||||
engrave_right_paths=engrave_paths,
|
||||
engrave_left_points=engrave_points,
|
||||
engrave_left_paths=engrave_paths,
|
||||
offset=offset,
|
||||
plug_diameter=12.7);
|
||||
} else {
|
||||
children(0);
|
||||
}
|
||||
key_bitting(heights, cut_locations, .7874);
|
||||
}
|
||||
}
|
||||
|
||||
// Defaults
|
||||
bitting="";
|
||||
outline="5-pin";
|
||||
warding="C";
|
||||
schlage_classic(bitting, outline, warding);
|
||||
Reference in New Issue
Block a user