colorful PCB; better round rects
This commit is contained in:
parent
5492defb20
commit
e6feb1cd38
6 changed files with 288 additions and 56 deletions
|
|
@ -3,10 +3,9 @@ All sizes are in millimeters.
|
|||
"""
|
||||
from typing import Tuple
|
||||
|
||||
from solid import OpenSCADObject, cube, linear_extrude, text, translate, scale, rotate, cylinder, union, intersection, \
|
||||
color
|
||||
from solid import OpenSCADObject, cube, linear_extrude, text, translate, scale, rotate, cylinder, union, color, square, offset
|
||||
|
||||
from util import round_rect, get_label_size, FILAMENT_LAYER, LAYOUTS, forward
|
||||
from util import get_label_size, FILAMENT_LAYER, LAYOUTS, forward, right, backward
|
||||
|
||||
|
||||
def key(
|
||||
|
|
@ -51,14 +50,23 @@ def key(
|
|||
)
|
||||
) * forward(v=2)(
|
||||
linear_extrude(height=dome_height / 2)(
|
||||
round_rect(width=width, height=height, radius=corner_radius)
|
||||
translate(v=(corner_radius, corner_radius, 0))(
|
||||
offset(r=corner_radius)(
|
||||
square(size=(width - 2 * corner_radius, height - 2 * corner_radius))
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
linear_extrude(height=2)(
|
||||
round_rect(width=width, height=height, radius=corner_radius)
|
||||
# round_rect(width=width, height=height, radius=corner_radius)
|
||||
translate(v=(corner_radius, corner_radius, 0))(
|
||||
offset(r=corner_radius)(
|
||||
square(size=(width - 2 * corner_radius, height - 2 * corner_radius))
|
||||
)
|
||||
)
|
||||
)
|
||||
) - translate(v=(width / 2, height / 2, thickness + dome_height / 2 - dome_height * 2 * FILAMENT_LAYER))(
|
||||
linear_extrude(height=dome_height * 2 * FILAMENT_LAYER)(
|
||||
) - translate(v=(width / 2, height / 2, thickness + dome_height / 2 - dome_height * 3 * FILAMENT_LAYER))(
|
||||
linear_extrude(height=dome_height * 3 * FILAMENT_LAYER)(
|
||||
text(text=label, size=get_label_size(label), font=font, halign='center', valign='center')
|
||||
)
|
||||
)
|
||||
|
|
@ -74,7 +82,9 @@ def key_mat(
|
|||
key_thickness: float,
|
||||
layout: str,
|
||||
variant: str,
|
||||
font: str
|
||||
font: str,
|
||||
keys_h: int = 13,
|
||||
keys_v: int = 5
|
||||
) -> OpenSCADObject:
|
||||
"""
|
||||
Generates elastic mat with fixed layout but variable sizes
|
||||
|
|
@ -97,6 +107,8 @@ def key_mat(
|
|||
+---------------------------------------------+
|
||||
\\ thickness
|
||||
|
||||
:param keys_v:
|
||||
:param keys_h:
|
||||
:param variant:
|
||||
:param margin: left, right, top and bottom margin, can be single number to set all at once.
|
||||
:param padding: Horizontal and vertical padding, can be single number to set both at once.
|
||||
|
|
@ -109,8 +121,6 @@ def key_mat(
|
|||
:param font:
|
||||
:return:
|
||||
"""
|
||||
keys_h = 13
|
||||
keys_v = 5
|
||||
spacebar_start = 4 # horizontal start key of space bar (0 index)
|
||||
spacebar_width = 3 # space bar length in keys
|
||||
|
||||
|
|
@ -128,6 +138,7 @@ def key_mat(
|
|||
thickness
|
||||
])
|
||||
|
||||
# add keys to mat
|
||||
for x in range(keys_h):
|
||||
for y in range(keys_v):
|
||||
if (x == keys_h - 1 and (y in [0, 2, 3] and layout.startswith("ansi") or y in [0, 2] and layout == "iso")) \
|
||||
|
|
@ -175,12 +186,52 @@ def key_mat(
|
|||
label=LAYOUTS[f"{layout}_{variant}"][y][x]
|
||||
))
|
||||
|
||||
# add holes to keys for better "pressability"
|
||||
for x in range(keys_h):
|
||||
for y in range(keys_v):
|
||||
mat -= translate(v=(padding_h + x * (key_width + padding_h) + 1, padding_v + (keys_v - y - 1) * (key_height + padding_v) + 1, 0))(
|
||||
cube((key_width - 2, key_height - 2, key_thickness + thickness - 2 * FILAMENT_LAYER)) - translate(v=(key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
if (x == keys_h - 1 and (y in [0, 2, 3] and layout.startswith("ansi") or y in [0, 2] and layout == "iso")) \
|
||||
or (spacebar_start < x < spacebar_start + spacebar_width and y == keys_v - 1):
|
||||
# skip for wide keys (backspace, enter, shift and space bar)
|
||||
continue
|
||||
elif x == keys_h - 1 and y == 1 and layout in ["ansi_big_enter", "iso"]:
|
||||
# big enter
|
||||
mat -= translate(v=(padding_h + x * (key_width + padding_h) + 1, padding_v + (keys_v - y - 2) * (key_height + padding_v) + 1, 0))(
|
||||
cube((key_width - 2, 2 * key_height + padding_v - 2, key_thickness + thickness - 2 * FILAMENT_LAYER)) - translate(v=(key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
) - translate(v=(key_width / 2 - 1, key_height + padding_v + key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
) - translate(v=(key_width / 2 - 2, key_height / 2 - 1, 0))(
|
||||
cube((2, padding_v + key_height, key_thickness + thickness - 2 * FILAMENT_LAYER))
|
||||
)
|
||||
)
|
||||
elif x == keys_h - 2 and (y == 0 or (y == 2 and layout == "ansi") or (y == 3 and layout != "iso")):
|
||||
# wide key
|
||||
mat -= translate(v=(padding_h + x * (key_width + padding_h) + 1, padding_v + (keys_v - y - 1) * (key_height + padding_v) + 1, 0))(
|
||||
cube((2 * key_width + padding_h - 2, key_height - 2, key_thickness + thickness - 2 * FILAMENT_LAYER)) - translate(v=(key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
) - translate(v=(key_width + padding_h + key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
) - translate(v=(key_width / 2 - 1, key_height / 2 - 2, 0))(
|
||||
cube((padding_h + key_width, 2, key_thickness + thickness - 2 * FILAMENT_LAYER))
|
||||
)
|
||||
)
|
||||
elif x == spacebar_start and y == keys_v - 1:
|
||||
# space bar
|
||||
mat -= translate(v=(padding_h + x * (key_width + padding_h) + 1, padding_v + (keys_v - y - 1) * (key_height + padding_v) + 1, 0))(
|
||||
cube((spacebar_width * key_width + (spacebar_width - 1) * padding_h - 2, key_height - 2, key_thickness + thickness - 2 * FILAMENT_LAYER)) - translate(v=(key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
) - translate(v=((spacebar_width - 1) * key_width + (spacebar_width - 1) * padding_h + key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
) - translate(v=(key_width / 2 - 1, key_height / 2 - 2, 0))(
|
||||
cube(((spacebar_width - 1) * padding_h + (spacebar_width - 1) * key_width, 2, key_thickness + thickness - 2 * FILAMENT_LAYER))
|
||||
)
|
||||
)
|
||||
else:
|
||||
# normal key
|
||||
mat -= translate(v=(padding_h + x * (key_width + padding_h) + 1, padding_v + (keys_v - y - 1) * (key_height + padding_v) + 1, 0))(
|
||||
cube((key_width - 2, key_height - 2, key_thickness + thickness - 2 * FILAMENT_LAYER)) - translate(v=(key_width / 2 - 1, key_height / 2 - 1, 0))(
|
||||
cylinder(d=2, h=key_thickness + thickness - 2 * FILAMENT_LAYER)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return color("DarkSlateGray")(mat)
|
||||
|
|
|
|||
101
mkbd65/lower_case.py
Normal file
101
mkbd65/lower_case.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
from solid import OpenSCADObject, hull, translate, sphere, cube, scale, offset, square
|
||||
|
||||
from util import PCB_WIDTH, PCB_HEIGHT, PCB_RADIUS
|
||||
|
||||
|
||||
def lower_case(phone_width: float, phone_height: float, phone_radius: float) -> OpenSCADObject:
|
||||
"""
|
||||
Rounded bottom part of the case
|
||||
|
||||
:param phone_width:
|
||||
:param phone_height:
|
||||
:param phone_radius:
|
||||
:return:
|
||||
"""
|
||||
thickness = 2
|
||||
window_thickness = 0.5
|
||||
|
||||
return (scale(v=(1, 1, thickness / phone_radius))(
|
||||
hull()(
|
||||
translate(v=(phone_radius, phone_radius, 0))(
|
||||
sphere(r=phone_radius),
|
||||
translate(v=(0, phone_height - 2 * phone_radius, 0))(
|
||||
sphere(r=phone_radius)
|
||||
),
|
||||
translate(v=(phone_width - 2 * phone_radius, 0, 0))(
|
||||
sphere(r=phone_radius)
|
||||
),
|
||||
translate(v=(phone_width - 2 * phone_radius, phone_height - 2 * phone_radius, 0))(
|
||||
sphere(r=phone_radius)
|
||||
)
|
||||
)
|
||||
)
|
||||
) * translate(v=(0, 0, -1 * thickness))(
|
||||
cube([phone_width, phone_height, thickness])
|
||||
)) - translate(v=(2 * phone_radius, 2 * phone_radius, -1 * thickness / 2))(
|
||||
scale(v=(1, 1, thickness))(
|
||||
offset(r=phone_radius)(
|
||||
square([phone_width - 4 * phone_radius, phone_height - 4 * phone_radius])
|
||||
)
|
||||
)
|
||||
) - translate(v=(phone_width - PCB_WIDTH, phone_radius, -1 * thickness / 2 + window_thickness))(
|
||||
scale(v=(1, 1, thickness))(
|
||||
offset(r=PCB_RADIUS)(
|
||||
square([PCB_WIDTH - 2 * PCB_RADIUS, PCB_HEIGHT - 2 * PCB_RADIUS])
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
# width = 160.7;
|
||||
# height = 74.1;
|
||||
# radius = 10;
|
||||
# thickness = 2;
|
||||
|
||||
# pcb_radius = 5;
|
||||
# pcb_width = 150;
|
||||
# pcb_height = 64;
|
||||
# window_thickness = 0.5;
|
||||
#
|
||||
#
|
||||
# translate([0, 0, thickness]) {
|
||||
# difference() {
|
||||
# intersection() {
|
||||
# scale([1, 1, thickness / radius]) {
|
||||
# hull() {
|
||||
# translate([radius, radius, 0]) {
|
||||
# sphere(r=radius);
|
||||
# translate([0, height-2*radius, 0]) {
|
||||
# sphere(r=radius);
|
||||
# }
|
||||
# translate([width-2*radius, 0, 0]) {
|
||||
# sphere(r=radius);
|
||||
# }
|
||||
# translate([width-2*radius, height-2*radius, 0]) {
|
||||
# sphere(r=radius);
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# translate([0, 0, -thickness]) {
|
||||
# cube([width, height, thickness]);
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# translate([2*radius, 2*radius, -thickness/2]) {
|
||||
# scale([1, 1, thickness]) {
|
||||
# offset(r=radius) {
|
||||
# square([width - 4 * radius, height - 4 * radius]);
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# translate([width - pcb_width, radius, -1*thickness/2+window_thickness]) {
|
||||
# scale([1,1,thickness]) {
|
||||
# offset(r=pcb_radius) {
|
||||
# square([pcb_width - 2 * pcb_radius, pcb_height - 2 * pcb_radius]);
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
All sizes are in millimeters.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from subprocess import run
|
||||
from configparser import ConfigParser
|
||||
|
|
@ -10,6 +8,7 @@ import click
|
|||
from solid import scad_render_to_file
|
||||
|
||||
from key_mat import key_mat, key
|
||||
from pcb import pcb
|
||||
from phone import phone
|
||||
|
||||
|
||||
|
|
@ -56,6 +55,25 @@ def cli(layout, variant, stl, emf, amf, detail, config_file):
|
|||
layout=layout,
|
||||
variant=variant,
|
||||
font=config.get("key_mat", "font", fallback="DejaVu Sans:style=Bold")
|
||||
)],
|
||||
["pcb", pcb(
|
||||
key_width=config.getfloat("key_mat", "key_width", fallback=9),
|
||||
key_height=config.getfloat("key_mat", "key_height", fallback=6),
|
||||
key_padding=config.getfloat("key_mat", "padding", fallback=1)
|
||||
)],
|
||||
["test_key_mat", key_mat(
|
||||
margin=config.getfloat("key_mat", "margin", fallback=1),
|
||||
padding=config.getfloat("key_mat", "padding", fallback=1),
|
||||
thickness=config.getfloat("key_mat", "thickness", fallback=0.5),
|
||||
key_width=config.getfloat("key_mat", "key_width", fallback=9),
|
||||
key_height=config.getfloat("key_mat", "key_height", fallback=6),
|
||||
key_radius=config.getfloat("key_mat", "key_corner_radius", fallback=1),
|
||||
key_thickness=config.getfloat("key_mat", "key_thickness", fallback=2),
|
||||
layout=layout,
|
||||
variant=variant,
|
||||
font=config.get("key_mat", "font", fallback="DejaVu Sans:style=Bold"),
|
||||
keys_h=5,
|
||||
keys_v=3
|
||||
)]
|
||||
]
|
||||
|
||||
|
|
|
|||
88
mkbd65/pcb.py
Normal file
88
mkbd65/pcb.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
from solid import OpenSCADObject, color, linear_extrude, polygon, translate, scale, offset, square, union, cylinder
|
||||
|
||||
from util import PCB_WIDTH, PCB_HEIGHT, PCB_RADIUS
|
||||
|
||||
|
||||
def switch() -> OpenSCADObject:
|
||||
"""
|
||||
Alps SKTKABE010
|
||||
|
||||
6 +----+ 5
|
||||
/ \
|
||||
7 + + 4 | 2mm
|
||||
8 + + 3 |
|
||||
\ 4mm /
|
||||
1 +----+ 2
|
||||
|
||||
:return:
|
||||
"""
|
||||
thickness = 0.78
|
||||
|
||||
return color("Silver")(
|
||||
linear_extrude(height=0.5)(
|
||||
polygon(points=[(1, 0), (5, 0), (6, 1), (6, 3), (5, 4), (1, 4), (0, 3), (0, 1)]),
|
||||
)
|
||||
) + color("Black")(
|
||||
translate(v=(3, 2, 0))(
|
||||
cylinder(r=0.5, h=thickness)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def pcb(key_width: float, key_height: float, key_padding: float) -> OpenSCADObject:
|
||||
"""
|
||||
|
||||
:return:
|
||||
"""
|
||||
pcb_thickness = 0.5
|
||||
rows = 5
|
||||
columns = 12
|
||||
|
||||
board = color(c="Purple")(
|
||||
translate(v=(PCB_RADIUS, PCB_RADIUS, pcb_thickness/2))(
|
||||
scale(v=(1, 1, pcb_thickness))(
|
||||
offset(r=PCB_RADIUS)(
|
||||
square([PCB_WIDTH - 2 * PCB_RADIUS, PCB_HEIGHT - 2 * PCB_RADIUS])
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
switches = []
|
||||
margin_x = (PCB_WIDTH - (columns * key_width + (columns - 1) * key_padding)) / 2
|
||||
margin_y = 3
|
||||
|
||||
for x in range(columns):
|
||||
for y in range(rows):
|
||||
switches.append(
|
||||
translate(v=(margin_x + x * (key_width + key_padding), margin_y + y * (key_height + key_padding), pcb_thickness))(
|
||||
switch()
|
||||
)
|
||||
)
|
||||
|
||||
return union()(
|
||||
board,
|
||||
*switches
|
||||
)
|
||||
# TODO: Add ATMEGA and flat cable connector
|
||||
|
||||
# rows = 5
|
||||
# columns = 12
|
||||
# hspacing = 4
|
||||
# vspacing = 3
|
||||
# width = 6
|
||||
# height = 4
|
||||
#
|
||||
# board = color("Green")(cube([123, 49, 0.6])) + translate((13, 36, 0.6))(
|
||||
# color("BlackPaint")(cube([7, 7, 1]))
|
||||
# ) + translate((23, 35.75, 0.6))(
|
||||
# color("BlackPaint")(cube([2.5, 2, 0.55]))
|
||||
# )
|
||||
#
|
||||
# for row in range(rows):
|
||||
# for col in range(columns):
|
||||
# board += translate((3.5 + (hspacing + width) * col, 2 + (vspacing + height) * row, 0.6))(
|
||||
# switch()
|
||||
# )
|
||||
#
|
||||
# return board
|
||||
|
|
@ -2,9 +2,7 @@
|
|||
All sizes are in millimeters.
|
||||
"""
|
||||
|
||||
from solid import OpenSCADObject, linear_extrude
|
||||
|
||||
from util import round_rect
|
||||
from solid import OpenSCADObject, linear_extrude, translate, offset, square
|
||||
|
||||
|
||||
def phone(
|
||||
|
|
@ -24,6 +22,10 @@ def phone(
|
|||
:return:
|
||||
"""
|
||||
return linear_extrude(height=thickness)(
|
||||
round_rect(width=width, height=height, radius=corner_radius)
|
||||
translate(v=(corner_radius, corner_radius, 0))(
|
||||
offset(r=corner_radius)(
|
||||
square(size=(width - 2 * corner_radius, height - 2 * corner_radius))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
from solid import polygon, circle, translate, OpenSCADObject
|
||||
|
||||
|
||||
PCB_RADIUS = 5
|
||||
PCB_WIDTH = 150
|
||||
PCB_HEIGHT = 64
|
||||
FILAMENT_LAYER = 0.1
|
||||
|
||||
# TODO: Add iso_fr (AZERTY) just for Slim :P
|
||||
LAYOUTS = {
|
||||
"ansi_en": [
|
||||
["Esc", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "⌫", None],
|
||||
|
|
@ -42,7 +45,9 @@ def get_label_size(label: str) -> float:
|
|||
:param label:
|
||||
:return:
|
||||
"""
|
||||
if label in ["Esc", "Alt", "Fn", "Ä", "Ü", "Ö"]:
|
||||
if label == "↵":
|
||||
return 4
|
||||
elif label in ["Esc", "Alt", "Fn", "Ä", "Ü", "Ö"]:
|
||||
return 3
|
||||
elif label == "Ctrl":
|
||||
return 2.5
|
||||
|
|
@ -50,39 +55,6 @@ def get_label_size(label: str) -> float:
|
|||
return 3.5
|
||||
|
||||
|
||||
def round_rect(width: float | int, height: float | int, radius: float | int) -> OpenSCADObject:
|
||||
"""
|
||||
Rectangle with rounded corners.
|
||||
|
||||
Combines a polygon and four circles to form the round corners.
|
||||
|
||||
O/-----\O
|
||||
/ \
|
||||
| |
|
||||
\ /
|
||||
O\_____/O
|
||||
|
||||
:param width: Width of the rectangle
|
||||
:param height: Height of the rectangle
|
||||
:param radius: Radius of rectangle corners
|
||||
:return:
|
||||
"""
|
||||
return polygon(points=[
|
||||
(0, radius),
|
||||
(0, height - radius),
|
||||
(radius, height),
|
||||
(width - radius, height),
|
||||
(width, height - radius),
|
||||
(width, radius),
|
||||
(width - radius, 0),
|
||||
(radius, 0)]
|
||||
) \
|
||||
+ translate(v=(radius, radius, 0))(circle(r=radius)) \
|
||||
+ translate(v=(radius, height - radius, 0))(circle(r=radius)) \
|
||||
+ translate(v=(width - radius, height - radius, 0))(circle(r=radius)) \
|
||||
+ translate(v=(width - radius, radius, 0))(circle(r=radius))
|
||||
|
||||
|
||||
def up(v: float) -> translate:
|
||||
return translate(v=(0, v, 0))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue