From fe4fb0b264c88c1b32445c2f855614c46ca088bb Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 24 Oct 2022 19:23:27 +0000 Subject: [PATCH 01/11] Add initial pyproject.toml stub --- pyproject.toml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..e4fbe816b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,36 @@ +[build-system] +requires = [ + "setuptools>=61.0", + "setuptools-scm", +] +build-backend = "setuptools.build_meta" + +[project] +name = "dactyl_keyboard" +authors = [ + { name="Matt Adereth" }, + { name="Tom Short" }, + { name="Josh Reve" }, +] +description = "A package to generate Dactyl(Manuform) keyboards" +readme = "README.md" +requires-python = ">=3.8" +license = { text = "AGPLv3" } +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", + "Operating System :: OS Independent", +] +dependencies = [ + "numpy", +] +dynamic = ["version"] + +[project.optional-dependencies] +cadquery = ["cadquery==2.2.0b2", "cadquery-ocp==7.6.3a0"] +solid = ["solidpython"] + + +[project.urls] +"Homepage" = "https://github.com/joshreve/dactyl-keyboard" +"Bug Tracker" = "https://github.com/joshreve/dactyl-keyboard/issues" From e89c56a1c77e04c695d73da1d09b3bc5bfb09e7e Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 24 Oct 2022 19:28:23 +0000 Subject: [PATCH 02/11] Autoformat/trim whitespace. --- src/dactyl_manuform.py | 751 ++++++++++++----------- src/generate_configuration.py | 91 +-- src/generate_configuration_mklasklasd.py | 89 +-- src/generate_configuration_orbyl_test.py | 93 +-- src/generate_configuration_test.py | 89 +-- src/helpers_blender.py | 10 +- src/helpers_cadquery.py | 7 +- src/helpers_solid.py | 7 +- src/model_builder.py | 11 +- 9 files changed, 591 insertions(+), 557 deletions(-) diff --git a/src/dactyl_manuform.py b/src/dactyl_manuform.py index 72135e7b4..e8d915ad0 100644 --- a/src/dactyl_manuform.py +++ b/src/dactyl_manuform.py @@ -1,13 +1,17 @@ +import math +import generate_configuration as cfg import numpy as np from numpy import pi import os.path as path -import getopt, sys +import getopt +import sys import json import os import copy from scipy.spatial import ConvexHull as sphull + def deg2rad(degrees: float) -> float: return degrees * pi / 180 @@ -20,8 +24,7 @@ def rad2deg(rad: float) -> float: # EXTREMELY UGLY BUT FUNCTIONAL BOOTSTRAP ############################################### -## IMPORT DEFAULT CONFIG IN CASE NEW PARAMETERS EXIST -import generate_configuration as cfg +# IMPORT DEFAULT CONFIG IN CASE NEW PARAMETERS EXIST for item in cfg.shape_config: locals()[item] = cfg.shape_config[item] @@ -31,7 +34,7 @@ def rad2deg(rad: float) -> float: data = json.load(fid) else: - ## CHECK FOR CONFIG FILE AND WRITE TO ANY VARIABLES IN FILE. + # CHECK FOR CONFIG FILE AND WRITE TO ANY VARIABLES IN FILE. opts, args = getopt.getopt(sys.argv[1:], "", ["config="]) for opt, arg in opts: if opt in ('--config'): @@ -76,9 +79,10 @@ def rad2deg(rad: float) -> float: #################################################### -debug_exports = False +debug_exports = False debug_trace = False + def debugprint(info): if debug_trace: print(info) @@ -94,7 +98,7 @@ def debugprint(info): centerrow = nrows - centerrow_offset lastrow = nrows - 1 -if reduced_outer_cols>0 or reduced_inner_cols>0: +if reduced_outer_cols > 0 or reduced_inner_cols > 0: cornerrow = lastrow - 1 else: cornerrow = lastrow @@ -124,15 +128,14 @@ def debugprint(info): mount_height = keyswitch_height + 2 * plate_rim mount_thickness = plate_thickness -if default_1U_cluster and thumb_style=='DEFAULT': +if default_1U_cluster and thumb_style == 'DEFAULT': double_plate_height = (.7*sa_double_length - mount_height) / 3 -elif thumb_style=='DEFAULT': +elif thumb_style == 'DEFAULT': double_plate_height = (.95*sa_double_length - mount_height) / 3 else: double_plate_height = (sa_double_length - mount_height) / 3 - if oled_mount_type is not None and oled_mount_type != "NONE": left_wall_x_offset = oled_left_wall_x_offset_override left_wall_z_offset = oled_left_wall_z_offset_override @@ -140,18 +143,15 @@ def debugprint(info): left_wall_lower_z_offset = oled_left_wall_lower_z_offset - cap_top_height = plate_thickness + sa_profile_key_height row_radius = ((mount_height + extra_height) / 2) / (np.sin(alpha / 2)) + cap_top_height column_radius = ( - ((mount_width + extra_width) / 2) / (np.sin(beta / 2)) - ) + cap_top_height + ((mount_width + extra_width) / 2) / (np.sin(beta / 2)) +) + cap_top_height column_x_delta = -1 - column_radius * np.sin(beta) column_base_angle = beta * (centercol - 2) - - teensy_width = 20 teensy_height = 12 teensy_length = 33 @@ -206,7 +206,7 @@ def single_plate(cylinder_segments=100, side="right"): plate = box(mount_width, mount_height, mount_thickness) plate = translate(plate, (0.0, 0.0, mount_thickness / 2.0)) - shape_cut = box(keyswitch_width, keyswitch_height, mount_thickness * 2 +.02) + shape_cut = box(keyswitch_width, keyswitch_height, mount_thickness * 2 + .02) shape_cut = translate(shape_cut, (0.0, 0.0, mount_thickness-.01)) plate = difference(plate, [shape_cut]) @@ -226,16 +226,16 @@ def single_plate(cylinder_segments=100, side="right"): mount_thickness ) undercut = union([undercut, - box( - keyswitch_width + 2 * clip_undercut, - notch_width, - mount_thickness - ) - ]) + box( + keyswitch_width + 2 * clip_undercut, + notch_width, + mount_thickness + ) + ]) undercut = translate(undercut, (0.0, 0.0, -clip_thickness + mount_thickness / 2.0)) - if ENGINE=='cadquery' and undercut_transition > 0: + if ENGINE == 'cadquery' and undercut_transition > 0: undercut = undercut.faces("+Z").chamfer(undercut_transition, clip_undercut) plate = difference(plate, [undercut]) @@ -245,7 +245,6 @@ def single_plate(cylinder_segments=100, side="right"): socket = translate(socket, [0, 0, plate_thickness + plate_offset]) plate = union([plate, socket]) - if plate_holes: half_width = plate_holes_width/2. half_height = plate_holes_height/2. @@ -276,6 +275,7 @@ def single_plate(cylinder_segments=100, side="right"): return plate + def plate_pcb_cutout(side="right"): shape = box(*plate_pcb_size) shape = translate(shape, (0, 0, -plate_pcb_size[2]/2)) @@ -286,6 +286,7 @@ def plate_pcb_cutout(side="right"): return shape + def trackball_cutout(segments=100, side="right"): if trackball_modular: hole_diameter = ball_diameter + 2 * (ball_gap + ball_wall_thickness + trackball_modular_clearance+trackball_modular_lip_width)-.1 @@ -294,6 +295,7 @@ def trackball_cutout(segments=100, side="right"): shape = cylinder(trackball_hole_diameter / 2, trackball_hole_height) return shape + def trackball_socket(segments=100, side="right"): if trackball_modular: hole_diameter = ball_diameter + 2 * (ball_gap + ball_wall_thickness + trackball_modular_clearance) @@ -322,6 +324,7 @@ def trackball_socket(segments=100, side="right"): # return shape, cutter return shape, cutter, sensor + def trackball_ball(segments=100, side="right"): shape = sphere(ball_diameter / 2) return shape @@ -330,6 +333,7 @@ def trackball_ball(segments=100, side="right"): ## SA Keycaps ## ################ + def keycap(*args, **kwargs): if show_caps == 'CHOC': return choc_cap(*args, **kwargs) @@ -338,6 +342,7 @@ def keycap(*args, **kwargs): else: return sa_cap(*args, **kwargs) + def sa_cap(Usize=1): # MODIFIED TO NOT HAVE THE ROTATION. NEEDS ROTATION DURING ASSEMBLY # sa_length = 18.25 @@ -417,7 +422,6 @@ def choc_cap(Usize=1): return key_cap - def key_pcb(): shape = box(pcb_width, pcb_height, pcb_thickness) shape = translate(shape, (0, 0, -pcb_thickness/2)) @@ -462,8 +466,6 @@ def rotate_around_y(position, angle): return np.matmul(t_matrix, position) - - def apply_key_geometry( shape, translate_fn, @@ -556,6 +558,7 @@ def key_holes(side="right"): return shape + def plate_pcb_cutouts(side="right"): debugprint('plate_pcb_cutouts()') # hole = single_plate() @@ -589,7 +592,6 @@ def caps(cap_type="MX"): #################### - def web_post(): debugprint('web_post()') post = box(post_size, post_size, web_thickness) @@ -630,7 +632,6 @@ def web_post_br(wide=False): return translate(web_post(), ((mount_width / w_divide) - post_adj, -(mount_height / 2) + post_adj, 0)) - def connectors(): debugprint('connectors()') hulls = [] @@ -674,7 +675,6 @@ def connectors(): places.append(key_place(web_post_tl(), column + 1, row + 1)) hulls.append(triangle_hulls(places)) - if column == (reduced_inner_cols-1): places = [] places.append(key_place(web_post_bl(), column + 1, iterrows)) @@ -690,9 +690,8 @@ def connectors(): places.append(key_place(web_post_br(), column, iterrows + 1)) hulls.append(triangle_hulls(places)) - return union(hulls) - #return add(hulls) + # return add(hulls) ############ @@ -730,6 +729,7 @@ def default_thumb_tr_place(shape): shape = translate(shape, [-12, -16, 3]) return shape + def default_thumb_mr_place(shape): debugprint('thumb_mr_place()') shape = rotate(shape, [-6, -34, 48]) @@ -780,21 +780,23 @@ def default_thumb_1x_layout(shape, cap=False): else: shape_list = [ - default_thumb_mr_place(rotate(shape, [0, 0, thumb_plate_mr_rotation])), - default_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])), - default_thumb_br_place(rotate(shape, [0, 0, thumb_plate_br_rotation])), - default_thumb_bl_place(rotate(shape, [0, 0, thumb_plate_bl_rotation])), - ] + default_thumb_mr_place(rotate(shape, [0, 0, thumb_plate_mr_rotation])), + default_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])), + default_thumb_br_place(rotate(shape, [0, 0, thumb_plate_br_rotation])), + default_thumb_bl_place(rotate(shape, [0, 0, thumb_plate_bl_rotation])), + ] if default_1U_cluster: shape_list.append(default_thumb_tr_place(rotate(rotate(shape, (0, 0, 90)), [0, 0, thumb_plate_tr_rotation]))) shapes = union(shape_list) return shapes + def default_thumb_pcb_plate_cutouts(side="right"): shape = default_thumb_1x_layout(plate_pcb_cutout(side=side)) shape = union([shape, default_thumb_15x_layout(plate_pcb_cutout(side=side))]) return shape + def default_thumb_15x_layout(shape, cap=False, plate=True): debugprint('thumb_15x_layout()') if plate: @@ -830,6 +832,7 @@ def default_thumb_15x_layout(shape, cap=False, plate=True): def adjustable_plate_size(Usize=1.5): return (Usize * sa_length - mount_height) / 2 + def usize_dimention(Usize=1.5): return Usize * sa_length @@ -843,11 +846,13 @@ def adjustable_plate_half(Usize=1.5): ) return top_plate + def adjustable_plate(Usize=1.5): debugprint('double_plate()') top_plate = adjustable_plate_half(Usize) return union((top_plate, mirror(top_plate, 'XZ'))) + def adjustable_square_plate(Uwidth=1.5, Uheight=1.5): width = usize_dimention(Usize=Uwidth) height = usize_dimention(Usize=Uheight) @@ -857,6 +862,7 @@ def adjustable_square_plate(Uwidth=1.5, Uheight=1.5): shape = translate(shape, (0, 0, web_thickness/2)) return shape + def double_plate_half(): debugprint('double_plate()') top_plate = box(mount_width, double_plate_height, web_thickness) @@ -865,6 +871,7 @@ def double_plate_half(): ) return top_plate + def double_plate(): debugprint('double_plate()') top_plate = double_plate_half() @@ -935,7 +942,7 @@ def thumb_connectors(side='right', style_override=None): return minidox_thumb_connectors() elif _thumb_style == "CARBONFET": return carbonfet_thumb_connectors() - + elif "TRACKBALL" in _thumb_style: if (side == ball_side or ball_side == 'both'): if _thumb_style == "TRACKBALL_ORBYL": @@ -944,7 +951,7 @@ def thumb_connectors(side='right', style_override=None): return tbcj_thumb_connectors() else: return thumb_connectors(side, style_override=other_thumb) - + else: return default_thumb_connectors() @@ -974,6 +981,7 @@ def thumb_pcb_plate_cutouts(side='right', style_override=None): else: return default_thumb_pcb_plate_cutouts(side) + def default_thumbcaps(): t1 = default_thumb_1x_layout(keycap(1), cap=True) if not default_1U_cluster: @@ -1178,7 +1186,7 @@ def default_thumb_connectors(): ) ) - #return add(hulls) + # return add(hulls) return union(hulls) ############################ @@ -1228,7 +1236,7 @@ def mini_thumb_bl_place(shape): def mini_thumb_1x_layout(shape): return union([ - #return add([ + # return add([ mini_thumb_mr_place(rotate(shape, [0, 0, thumb_plate_mr_rotation])), mini_thumb_br_place(rotate(shape, [0, 0, thumb_plate_br_rotation])), mini_thumb_tl_place(rotate(shape, [0, 0, thumb_plate_tl_rotation])), @@ -1238,7 +1246,7 @@ def mini_thumb_1x_layout(shape): def mini_thumb_15x_layout(shape): return union([mini_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation]))]) - #return add([mini_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation]))]) + # return add([mini_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation]))]) def mini_thumbcaps(): @@ -1254,6 +1262,7 @@ def mini_thumb(side="right"): return shape + def mini_thumb_pcb_plate_cutouts(side="right"): shape = mini_thumb_1x_layout(plate_pcb_cutout(side=side)) shape = union([shape, mini_thumb_15x_layout(plate_pcb_cutout(side=side))]) @@ -1263,26 +1272,26 @@ def mini_thumb_pcb_plate_cutouts(side="right"): def mini_thumb_post_tr(): return translate(web_post(), - [(mount_width / 2) - post_adj, (mount_height / 2) - post_adj, 0] - ) + [(mount_width / 2) - post_adj, (mount_height / 2) - post_adj, 0] + ) def mini_thumb_post_tl(): return translate(web_post(), - [-(mount_width / 2) + post_adj, (mount_height / 2) - post_adj, 0] - ) + [-(mount_width / 2) + post_adj, (mount_height / 2) - post_adj, 0] + ) def mini_thumb_post_bl(): return translate(web_post(), - [-(mount_width / 2) + post_adj, -(mount_height / 2) + post_adj, 0] - ) + [-(mount_width / 2) + post_adj, -(mount_height / 2) + post_adj, 0] + ) def mini_thumb_post_br(): return translate(web_post(), - [(mount_width / 2) - post_adj, -(mount_height / 2) + post_adj, 0] - ) + [(mount_width / 2) - post_adj, -(mount_height / 2) + post_adj, 0] + ) def mini_thumb_connectors(): @@ -1380,7 +1389,7 @@ def mini_thumb_connectors(): ) return union(hulls) - #return add(hulls) + # return add(hulls) ############################ @@ -1393,21 +1402,24 @@ def minidox_thumb_tl_place(shape): shape = translate(shape, [-35, -16, -2]) return shape + def minidox_thumb_tr_place(shape): shape = rotate(shape, [14, -15, 10]) shape = translate(shape, thumborigin()) shape = translate(shape, [-15, -10, 5]) return shape + def minidox_thumb_ml_place(shape): shape = rotate(shape, [6, -34, 40]) shape = translate(shape, thumborigin()) shape = translate(shape, [-53, -26, -12]) return shape + def minidox_thumb_1x_layout(shape): return union([ - #return add([ + # return add([ minidox_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation])), minidox_thumb_tl_place(rotate(shape, [0, 0, thumb_plate_tl_rotation])), minidox_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])), @@ -1416,12 +1428,13 @@ def minidox_thumb_1x_layout(shape): def minidox_thumb_fx_layout(shape): return union([ - #return add([ + # return add([ minidox_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation])), minidox_thumb_tl_place(rotate(shape, [0, 0, thumb_plate_tl_rotation])), minidox_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])), ]) + def minidox_thumbcaps(): t1 = minidox_thumb_1x_layout(keycap(1)) # t1.add(minidox_thumb_15x_layout(rotate(keycap(1), [0, 0, rad2deg(pi / 2)]))) @@ -1436,12 +1449,14 @@ def minidox_thumb(side="right"): # shape = minidox_thumb_1x_layout(single_plate(side=side)) return shape + def minidox_thumb_pcb_plate_cutouts(side="right"): shape = minidox_thumb_fx_layout(plate_pcb_cutout(side=side)) shape = union([shape, minidox_thumb_fx_layout(plate_pcb_cutout())]) #shape = add([shape, minidox_thumb_fx_layout(plate_pcb_cutout())]) return shape + def minidox_thumb_post_tr(): debugprint('thumb_post_tr()') return translate(web_post(), @@ -1497,7 +1512,6 @@ def minidox_thumb_connectors(): ) ) - # top two to the main keyboard, starting on the left hulls.append( triangle_hulls( @@ -1521,7 +1535,7 @@ def minidox_thumb_connectors(): ) return union(hulls) - #return add(hulls) + # return add(hulls) ############################ @@ -1535,30 +1549,35 @@ def carbonfet_thumb_tl_place(shape): shape = translate(shape, [-13, -9.8, 4]) return shape + def carbonfet_thumb_tr_place(shape): shape = rotate(shape, [6, -25, 10]) shape = translate(shape, thumborigin()) shape = translate(shape, [-7.5, -29.5, 0]) return shape + def carbonfet_thumb_ml_place(shape): shape = rotate(shape, [8, -31, 14]) shape = translate(shape, thumborigin()) shape = translate(shape, [-30.5, -17, -6]) return shape + def carbonfet_thumb_mr_place(shape): shape = rotate(shape, [4, -31, 14]) shape = translate(shape, thumborigin()) shape = translate(shape, [-22.2, -41, -10.3]) return shape + def carbonfet_thumb_br_place(shape): shape = rotate(shape, [2, -37, 18]) shape = translate(shape, thumborigin()) shape = translate(shape, [-37, -46.4, -22]) return shape + def carbonfet_thumb_bl_place(shape): shape = rotate(shape, [6, -37, 18]) shape = translate(shape, thumborigin()) @@ -1568,7 +1587,7 @@ def carbonfet_thumb_bl_place(shape): def carbonfet_thumb_1x_layout(shape): return union([ - #return add([ + # return add([ carbonfet_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation])), carbonfet_thumb_mr_place(rotate(shape, [0, 0, thumb_plate_mr_rotation])), carbonfet_thumb_br_place(rotate(shape, [0, 0, thumb_plate_br_rotation])), @@ -1579,13 +1598,13 @@ def carbonfet_thumb_1x_layout(shape): def carbonfet_thumb_15x_layout(shape, plate=True): if plate: return union([ - #return add([ + # return add([ carbonfet_thumb_bl_place(rotate(shape, [0, 0, thumb_plate_bl_rotation])), carbonfet_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])) ]) else: return union([ - #return add([ + # return add([ carbonfet_thumb_bl_place(shape), carbonfet_thumb_ml_place(shape) ]) @@ -1606,34 +1625,37 @@ def carbonfet_thumb(side="right"): return shape + def carbonfet_thumb_pcb_plate_cutouts(side="right"): shape = carbonfet_thumb_1x_layout(plate_pcb_cutout(side=side)) shape = union([shape, carbonfet_thumb_15x_layout(plate_pcb_cutout())]) #shape = add([shape, carbonfet_thumb_15x_layout(plate_pcb_cutout())]) return shape + def carbonfet_thumb_post_tr(): return translate(web_post(), - [(mount_width / 2) - post_adj, (mount_height / 1.15) - post_adj, 0] - ) + [(mount_width / 2) - post_adj, (mount_height / 1.15) - post_adj, 0] + ) def carbonfet_thumb_post_tl(): return translate(web_post(), - [-(mount_width / 2) + post_adj, (mount_height / 1.15) - post_adj, 0] - ) + [-(mount_width / 2) + post_adj, (mount_height / 1.15) - post_adj, 0] + ) def carbonfet_thumb_post_bl(): return translate(web_post(), - [-(mount_width / 2) + post_adj, -(mount_height / 1.15) + post_adj, 0] - ) + [-(mount_width / 2) + post_adj, -(mount_height / 1.15) + post_adj, 0] + ) def carbonfet_thumb_post_br(): return translate(web_post(), - [(mount_width / 2) - post_adj, -(mount_height / 2) + post_adj, 0] - ) + [(mount_width / 2) - post_adj, -(mount_height / 2) + post_adj, 0] + ) + def carbonfet_thumb_connectors(): hulls = [] @@ -1748,7 +1770,7 @@ def carbonfet_thumb_connectors(): ) return union(hulls) - #return add(hulls) + # return add(hulls) ############################ @@ -1783,22 +1805,24 @@ def tbjs_thumb_tl_place(shape): t_off = tbjs_key_translation_offsets[0] shape = rotate(shape, tbjs_key_rotation_offsets[0]) shape = translate(shape, (t_off[0], t_off[1]+tbjs_key_diameter/2, t_off[2])) - shape = rotate(shape, [0,0,-80]) + shape = rotate(shape, [0, 0, -80]) shape = tbjs_place(shape) return shape + def tbjs_thumb_mr_place(shape): debugprint('thumb_mr_place()') shape = rotate(shape, [0, 0, 0]) shape = rotate(shape, tbjs_key_rotation_offsets[1]) t_off = tbjs_key_translation_offsets[1] shape = translate(shape, (t_off[0], t_off[1]+tbjs_key_diameter/2, t_off[2])) - shape = rotate(shape, [0,0,-130]) + shape = rotate(shape, [0, 0, -130]) shape = tbjs_place(shape) return shape + def tbjs_thumb_br_place(shape): debugprint('thumb_br_place()') @@ -1806,7 +1830,7 @@ def tbjs_thumb_br_place(shape): shape = rotate(shape, tbjs_key_rotation_offsets[2]) t_off = tbjs_key_translation_offsets[2] shape = translate(shape, (t_off[0], t_off[1]+tbjs_key_diameter/2, t_off[2])) - shape = rotate(shape, [0,0,-180]) + shape = rotate(shape, [0, 0, -180]) shape = tbjs_place(shape) return shape @@ -1818,7 +1842,7 @@ def tbjs_thumb_bl_place(shape): shape = rotate(shape, tbjs_key_rotation_offsets[3]) t_off = tbjs_key_translation_offsets[3] shape = translate(shape, (t_off[0], t_off[1]+tbjs_key_diameter/2, t_off[2])) - shape = rotate(shape, [0,0,-230]) + shape = rotate(shape, [0, 0, -230]) shape = tbjs_place(shape) return shape @@ -1826,13 +1850,14 @@ def tbjs_thumb_bl_place(shape): def tbjs_thumb_1x_layout(shape): return union([ - #return add([ + # return add([ tbjs_thumb_tl_place(rotate(shape, [0, 0, thumb_plate_tr_rotation])), tbjs_thumb_mr_place(rotate(shape, [0, 0, thumb_plate_mr_rotation])), tbjs_thumb_bl_place(rotate(shape, [0, 0, thumb_plate_bl_rotation])), tbjs_thumb_br_place(rotate(shape, [0, 0, thumb_plate_br_rotation])), ]) + def tbjs_thumb_pcb_plate_cutouts(side="right"): return tbjs_thumb_1x_layout(plate_pcb_cutout(side=side)) @@ -1845,9 +1870,10 @@ def tbjs_thumb_fx_layout(shape): tbjs_thumb_br_place(rotate(shape, [0, 0, thumb_plate_br_rotation])), ] + def trackball_layout(shape): return union([ - #return add([ + # return add([ tbjs_place(shape), ]) @@ -1930,6 +1956,7 @@ def tbjs_post_l(): [-1.0*(radius - post_adj), 0.0*(radius - post_adj), 0] ) + def tbjs_post_bl(): debugprint('tbjs_post_bl()') radius = ball_diameter/2+ball_wall_thickness + ball_gap @@ -1946,7 +1973,6 @@ def tbjs_post_br(): ) - def tbjs_thumb_connectors(): print('thumb_connectors()') hulls = [] @@ -2014,10 +2040,7 @@ def tbjs_thumb_connectors(): ) return union(hulls) - #return add(hulls) - - - + # return add(hulls) ############################ @@ -2032,65 +2055,72 @@ def tbcj_thumb_tr_place(shape): shape = translate(shape, [-12, -16, 3]) return shape + def tbcj_thumb_tl_place(shape): shape = rotate(shape, [7.5, -18, 10]) shape = translate(shape, thumborigin()) shape = translate(shape, [-32.5, -14.5, -2.5]) return shape + def tbcj_thumb_ml_place(shape): shape = rotate(shape, [6, -34, 40]) shape = translate(shape, thumborigin()) shape = translate(shape, [-51, -25, -12]) return shape + def tbcj_thumb_bl_place(shape): shape = rotate(shape, [-4, -35, 52]) shape = translate(shape, thumborigin()) shape = translate(shape, [-56.3, -43.3, -23.5]) return shape + def tbcj_thumb_layout(shape): return union([ - #return add([ - tbcj_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation])), - tbcj_thumb_tl_place(rotate(shape, [0, 0, thumb_plate_tl_rotation])), - tbcj_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])), - tbcj_thumb_bl_place(rotate(shape, [0, 0, thumb_plate_bl_rotation])), - ]) + # return add([ + tbcj_thumb_tr_place(rotate(shape, [0, 0, thumb_plate_tr_rotation])), + tbcj_thumb_tl_place(rotate(shape, [0, 0, thumb_plate_tl_rotation])), + tbcj_thumb_ml_place(rotate(shape, [0, 0, thumb_plate_ml_rotation])), + tbcj_thumb_bl_place(rotate(shape, [0, 0, thumb_plate_bl_rotation])), + ]) -#def oct_corner(i, radius, shape): +# def oct_corner(i, radius, shape): # i = (i+1)%8 -# +# # points_x = [1, 2, 2, 1, -1, -2, -2, -1] # points_y = [2, 1, -1, -2, -2, -1, 1, 2] # # return translate(shape, (points_x[i] * radius / 2, points_y[i] * radius / 2, 0)) -import math + def oct_corner(i, diameter, shape): radius = diameter / 2 - i = (i+1)%8 + i = (i+1) % 8 r = radius m = radius * math.tan(math.pi / 8) - + points_x = [m, r, r, m, -m, -r, -r, -m] points_y = [r, m, -m, -r, -r, -m, m, r] return translate(shape, (points_x[i], points_y[i], 0)) + def tbcj_edge_post(i): shape = box(post_size, post_size, tbcj_thickness) shape = oct_corner(i, tbcj_outer_diameter, shape) return shape + def tbcj_web_post(i): shape = box(post_size, post_size, tbcj_thickness) shape = oct_corner(i, tbcj_outer_diameter, shape) return shape + def tbcj_holder(): center = box(post_size, post_size, tbcj_thickness) @@ -2100,17 +2130,18 @@ def tbcj_holder(): center, tbcj_edge_post(i), tbcj_edge_post(i + 1), - ]) + ]) shape.append(shape_) shape = union(shape) shape = difference( - shape, - [cylinder(tbcj_inner_diameter/2, tbcj_thickness + 0.1)] - ) + shape, + [cylinder(tbcj_inner_diameter/2, tbcj_thickness + 0.1)] + ) return shape + def tbcj_thumb_position_rotation(): pos = np.array([-15, -60, -12]) + thumborigin() rot = (0, 0, 0) @@ -2123,16 +2154,19 @@ def tbcj_place(shape): shape = rotate(shape, (0, 0, 0)) return shape + def tbcj_thumb(side="right"): t = tbcj_thumb_layout(single_plate(side=side)) tb = tbcj_place(tbcj_holder()) return union([t, tb]) - #return add([t, tb]) + # return add([t, tb]) + def tbcj_thumb_pcb_plate_cutouts(side="right"): t = tbcj_thumb_layout(plate_pcb_cutout(side=side)) return t + def tbcj_thumbcaps(): t = tbcj_thumb_layout(keycap(1)) return t @@ -2274,8 +2308,7 @@ def tbcj_thumb_connectors(): ) return union(hulls) - #return add(hulls) - + # return add(hulls) ########## @@ -2298,7 +2331,6 @@ def left_key_position(row, direction, low_corner=False, side='right'): y_offset = 0.0 z_offset = 0.0 - return list(pos - np.array([ tbiw_left_wall_x_offset_override - x_offset, -y_offset, @@ -2380,7 +2412,7 @@ def wall_brace(place1, dx1, dy1, post1, place2, dx2, dy2, post2, back=False, ske if not skeleton or skel_bottom: hulls.append(place2(translate(post2, wall_locate3(dx2, dy2, back)))) - if len(hulls)>0: + if len(hulls) > 0: shape2 = bottom_hull(hulls) shape1 = union([shape1, shape2]) #shape1 = add([shape1, shape2]) @@ -2418,7 +2450,7 @@ def back_wall(skeleton=False): x, 0, 0, 1, web_post_tl(), x, 0, 0, 1, web_post_tr(), back=True, )]) - skelly = skeleton and not x==1 + skelly = skeleton and not x == 1 shape = union([shape, key_wall_brace( x, 0, 0, 1, web_post_tl(), x - 1, 0, 0, 1, web_post_tr(), back=True, skeleton=skelly, skel_bottom=True, @@ -2430,10 +2462,10 @@ def back_wall(skeleton=False): )]) if not skeleton: shape = union([shape, - key_wall_brace( - lastcol, 0, 0, 1, web_post_tr(), lastcol, 0, 1, 0, web_post_tr() - ) - ]) + key_wall_brace( + lastcol, 0, 0, 1, web_post_tr(), lastcol, 0, 1, 0, web_post_tr() + ) + ]) return shape @@ -2461,7 +2493,7 @@ def right_wall(skeleton=False): lastcol, y, 1, 0, web_post_tr(), lastcol, y, 1, 0, web_post_br(), skeleton=skeleton, )]) - #STRANGE PARTIAL OFFSET + # STRANGE PARTIAL OFFSET shape = union([ shape, @@ -2495,7 +2527,7 @@ def left_wall(side='right', skeleton=False): temp_shape1 = wall_brace( (lambda sh: left_key_place(sh, y, 1, side=side)), -1, 0, web_post(), (lambda sh: left_key_place(sh, y, -1, low_corner=low, side=side)), -1, 0, web_post(), - skeleton=skeleton and (y < (corner)), + skeleton=skeleton and (y < (corner)), ) shape = union([shape, temp_shape1]) @@ -2557,7 +2589,7 @@ def front_wall(skeleton=False): # corner = lastrow if 4 < (ncols - reduced_outer_cols) else cornerrow corner = cornerrow - if reduced_outer_cols>0: + if reduced_outer_cols > 0: offset_col = ncols - reduced_outer_cols else: offset_col = 99 @@ -2602,7 +2634,6 @@ def front_wall(skeleton=False): x, cornerrow, 0, -1, web_post_bl(), x, cornerrow, 0, -1, web_post_br() )]) - else: print("post offset") shape = union([shape, key_wall_brace( @@ -2612,7 +2643,6 @@ def front_wall(skeleton=False): x, cornerrow, 0, -1, web_post_bl(), x, corner, 0, -1, web_post_br() )]) - return shape @@ -2641,6 +2671,7 @@ def thumb_walls(side='right', style_override=None, skeleton=False): else: return default_thumb_walls(skeleton=skeleton) + def thumb_connection(side='right', style_override=None, skeleton=False): if style_override is None: _thumb_style = thumb_style @@ -2653,7 +2684,7 @@ def thumb_connection(side='right', style_override=None, skeleton=False): return minidox_thumb_connection(side=side, skeleton=skeleton) elif _thumb_style == "CARBONFET": return carbonfet_thumb_connection(side=side, skeleton=skeleton) - + elif "TRACKBALL" in _thumb_style: if (side == ball_side or ball_side == 'both'): if _thumb_style == "TRACKBALL_ORBYL": @@ -2708,16 +2739,16 @@ def default_thumb_connection(side='right', skeleton=False): )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - default_thumb_ml_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), - default_thumb_ml_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), - default_thumb_tl_place(thumb_post_tl()), - ] - ) - ]) # ) + hull_from_shapes( + [ + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + default_thumb_ml_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), + default_thumb_ml_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), + default_thumb_tl_place(thumb_post_tl()), + ] + ) + ]) # ) shape = union([shape, hull_from_shapes( [ @@ -2849,16 +2880,16 @@ def tbcj_thumb_connection(side='right', skeleton=False): )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - default_thumb_ml_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), - default_thumb_ml_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), - default_thumb_tl_place(web_post_tl()), - ] - ) - ]) # ) + hull_from_shapes( + [ + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + default_thumb_ml_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), + default_thumb_ml_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), + default_thumb_tl_place(web_post_tl()), + ] + ) + ]) # ) shape = union([shape, hull_from_shapes( [ @@ -2890,6 +2921,7 @@ def tbcj_thumb_connection(side='right', skeleton=False): return shape + def tbcj_thumb_walls(skeleton=False): shape = union([wall_brace(tbcj_thumb_ml_place, -0.3, 1, web_post_tr(), tbcj_thumb_ml_place, 0, 1, web_post_tl())]) shape = union([shape, wall_brace(tbcj_thumb_bl_place, 0, 1, web_post_tr(), tbcj_thumb_bl_place, 0, 1, web_post_tl())]) @@ -2897,7 +2929,7 @@ def tbcj_thumb_walls(skeleton=False): shape = union([shape, wall_brace(tbcj_thumb_bl_place, -1, 0, web_post_tl(), tbcj_thumb_bl_place, 0, 1, web_post_tl())]) shape = union([shape, wall_brace(tbcj_thumb_ml_place, 0, 1, web_post_tl(), tbcj_thumb_bl_place, 0, 1, web_post_tr())]) - corner = box(1,1,tbcj_thickness) + corner = box(1, 1, tbcj_thickness) points = [ (tbcj_thumb_bl_place, -1, 0, web_post_bl()), @@ -2908,7 +2940,7 @@ def tbcj_thumb_walls(skeleton=False): (tbcj_place, 1, 0, tbcj_web_post(0)), ((lambda sh: key_place(sh, 3, lastrow)), 0, -1, web_post_bl()), ] - for i,_ in enumerate(points[:-1]): + for i, _ in enumerate(points[:-1]): (pa, dxa, dya, sa) = points[i] (pb, dxb, dyb, sb) = points[i + 1] @@ -2935,6 +2967,7 @@ def mini_thumb_walls(skeleton=False): return shape + def mini_thumb_connection(side='right', skeleton=False): # clunky bit on the top left thumb connection (normal connectors don't work well) shape = union([bottom_hull( @@ -2947,50 +2980,51 @@ def mini_thumb_connection(side='right', skeleton=False): )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - mini_thumb_bl_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), - mini_thumb_bl_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), - mini_thumb_tl_place(web_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + mini_thumb_bl_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), + mini_thumb_bl_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), + mini_thumb_tl_place(web_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - mini_thumb_tl_place(web_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + mini_thumb_tl_place(web_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), - key_place(web_post_bl(), 0, cornerrow), - mini_thumb_tl_place(web_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), + key_place(web_post_bl(), 0, cornerrow), + mini_thumb_tl_place(web_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - mini_thumb_bl_place(web_post_tr()), - mini_thumb_bl_place(translate(web_post_tr(), wall_locate1(-0.3, 1))), - mini_thumb_bl_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), - mini_thumb_bl_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), - mini_thumb_tl_place(web_post_tl()), - ] - )]) + hull_from_shapes( + [ + mini_thumb_bl_place(web_post_tr()), + mini_thumb_bl_place(translate(web_post_tr(), wall_locate1(-0.3, 1))), + mini_thumb_bl_place(translate(web_post_tr(), wall_locate2(-0.3, 1))), + mini_thumb_bl_place(translate(web_post_tr(), wall_locate3(-0.3, 1))), + mini_thumb_tl_place(web_post_tl()), + ] + )]) return shape + def minidox_thumb_walls(skeleton=False): # thumb, walls @@ -3007,9 +3041,9 @@ def minidox_thumb_walls(skeleton=False): shape = union([shape, wall_brace(minidox_thumb_ml_place, 0, 1, minidox_thumb_post_tr(), minidox_thumb_ml_place, 0, 1, minidox_thumb_post_tl())]) shape = union([shape, wall_brace(minidox_thumb_tr_place, 0, -1, minidox_thumb_post_br(), (lambda sh: key_place(sh, 3, lastrow)), 0, -1, web_post_bl())]) - return shape + def minidox_thumb_connection(side='right', skeleton=False): # clunky bit on the top left thumb connection (normal connectors don't work well) shape = union([bottom_hull( @@ -3022,52 +3056,51 @@ def minidox_thumb_connection(side='right', skeleton=False): )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate2(-0.3, 1))), - minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate3(-0.3, 1))), - minidox_thumb_tl_place(minidox_thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate2(-0.3, 1))), + minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate3(-0.3, 1))), + minidox_thumb_tl_place(minidox_thumb_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - minidox_thumb_tl_place(minidox_thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + minidox_thumb_tl_place(minidox_thumb_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), - key_place(web_post_bl(), 0, cornerrow), - minidox_thumb_tl_place(minidox_thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), + key_place(web_post_bl(), 0, cornerrow), + minidox_thumb_tl_place(minidox_thumb_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - minidox_thumb_ml_place(minidox_thumb_post_tr()), - minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate1(0, 1))), - minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate2(0, 1))), - minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate3(0, 1))), - minidox_thumb_tl_place(minidox_thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + minidox_thumb_ml_place(minidox_thumb_post_tr()), + minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate1(0, 1))), + minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate2(0, 1))), + minidox_thumb_ml_place(translate(minidox_thumb_post_tr(), wall_locate3(0, 1))), + minidox_thumb_tl_place(minidox_thumb_post_tl()), + ] + )]) return shape - def carbonfet_thumb_walls(skeleton=False): # thumb, walls shape = union([wall_brace(carbonfet_thumb_mr_place, 0, -1, web_post_br(), carbonfet_thumb_tr_place, 0, -1, web_post_br())]) @@ -3085,6 +3118,7 @@ def carbonfet_thumb_walls(skeleton=False): shape = union([shape, wall_brace(carbonfet_thumb_tr_place, 0, -1, web_post_br(), (lambda sh: key_place(sh, 3, lastrow)), 0, -1, web_post_bl())]) return shape + def carbonfet_thumb_connection(side='right', skeleton=False): # clunky bit on the top left thumb connection (normal connectors don't work well) shape = bottom_hull( @@ -3097,50 +3131,51 @@ def carbonfet_thumb_connection(side='right', skeleton=False): ) shape = union([shape, - hull_from_shapes( - [ - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate2(-0.3, 1))), - carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate3(-0.3, 1))), - carbonfet_thumb_ml_place(thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate2(-0.3, 1))), + carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate3(-0.3, 1))), + carbonfet_thumb_ml_place(thumb_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), - carbonfet_thumb_ml_place(thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate2(-1, 0)), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate3(-1, 0)), cornerrow, -1, low_corner=True, side=side), + carbonfet_thumb_ml_place(thumb_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), - left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), - key_place(web_post_bl(), 0, cornerrow), - carbonfet_thumb_ml_place(thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + left_key_place(web_post(), cornerrow, -1, low_corner=True, side=side), + left_key_place(translate(web_post(), wall_locate1(-1, 0)), cornerrow, -1, low_corner=True, side=side), + key_place(web_post_bl(), 0, cornerrow), + carbonfet_thumb_ml_place(thumb_post_tl()), + ] + )]) shape = union([shape, - hull_from_shapes( - [ - carbonfet_thumb_bl_place(thumb_post_tr()), - carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate1(-0.3, 1))), - carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate2(-0.3, 1))), - carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate3(-0.3, 1))), - carbonfet_thumb_ml_place(thumb_post_tl()), - ] - )]) + hull_from_shapes( + [ + carbonfet_thumb_bl_place(thumb_post_tr()), + carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate1(-0.3, 1))), + carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate2(-0.3, 1))), + carbonfet_thumb_bl_place(translate(thumb_post_tr(), wall_locate3(-0.3, 1))), + carbonfet_thumb_ml_place(thumb_post_tl()), + ] + )]) return shape + def case_walls(side='right', skeleton=False): print('case_walls()') return ( @@ -3205,12 +3240,12 @@ def usb_holder(): usb_holder_size[2] + usb_holder_thickness, ) shape = translate(shape, - ( - usb_holder_position[0], - usb_holder_position[1], - (usb_holder_size[2] + usb_holder_thickness) / 2, - ) - ) + ( + usb_holder_position[0], + usb_holder_position[1], + (usb_holder_size[2] + usb_holder_thickness) / 2, + ) + ) return shape @@ -3218,12 +3253,12 @@ def usb_holder_hole(): debugprint('usb_holder_hole()') shape = box(*usb_holder_size) shape = translate(shape, - ( - usb_holder_position[0], - usb_holder_position[1], - (usb_holder_size[2] + usb_holder_thickness) / 2, - ) - ) + ( + usb_holder_position[0], + usb_holder_position[1], + (usb_holder_size[2] + usb_holder_thickness) / 2, + ) + ) return shape @@ -3239,25 +3274,25 @@ def usb_holder_hole(): ) ) + def external_mount_hole(): print('external_mount_hole()') shape = box(external_holder_width, 20.0, external_holder_height+.1) undercut = box(external_holder_width+8, 10.0, external_holder_height+8+.1) - shape = union([shape, translate(undercut,(0, -5, 0))]) + shape = union([shape, translate(undercut, (0, -5, 0))]) shape = translate(shape, - ( - external_start[0] + external_holder_xoffset, - external_start[1] + external_holder_yoffset, - external_holder_height / 2-.05, - ) - ) + ( + external_start[0] + external_holder_xoffset, + external_start[1] + external_holder_yoffset, + external_holder_height / 2-.05, + ) + ) return shape - pcb_mount_ref_position = key_position( - #TRRS POSITION IS REFERENCE BY CONVENIENCE + # TRRS POSITION IS REFERENCE BY CONVENIENCE list(np.array(wall_locate3(0, 1)) + np.array([0, (mount_height / 2), 0])), 0, 0 ) @@ -3265,6 +3300,7 @@ def external_mount_hole(): pcb_mount_ref_position[1] = pcb_mount_ref_position[1] + pcb_mount_ref_offset[1] pcb_mount_ref_position[2] = 0.0 + pcb_mount_ref_offset[2] + def pcb_usb_hole(): debugprint('pcb_holder()') pcb_usb_position = copy.deepcopy(pcb_mount_ref_position) @@ -3274,32 +3310,32 @@ def pcb_usb_hole(): shape = box(*pcb_usb_hole_size) shape = translate(shape, - ( - pcb_usb_position[0], - pcb_usb_position[1], - pcb_usb_hole_size[2] / 2 + usb_holder_thickness, - ) - ) + ( + pcb_usb_position[0], + pcb_usb_position[1], + pcb_usb_hole_size[2] / 2 + usb_holder_thickness, + ) + ) return shape - pcb_holder_position = copy.deepcopy(pcb_mount_ref_position) pcb_holder_position[0] = pcb_holder_position[0] + pcb_holder_offset[0] pcb_holder_position[1] = pcb_holder_position[1] + pcb_holder_offset[1] pcb_holder_position[2] = pcb_holder_position[2] + pcb_holder_offset[2] pcb_holder_thickness = pcb_holder_size[2] + def pcb_holder(): debugprint('pcb_holder()') shape = box(*pcb_holder_size) shape = translate(shape, - ( - pcb_holder_position[0], - pcb_holder_position[1] - pcb_holder_size[1] / 2, - pcb_holder_thickness / 2, - ) - ) + ( + pcb_holder_position[0], + pcb_holder_position[1] - pcb_holder_size[1] / 2, + pcb_holder_thickness / 2, + ) + ) return shape @@ -3307,17 +3343,15 @@ def wall_thinner(): debugprint('wall_thinner()') shape = box(*wall_thinner_size) shape = translate(shape, - ( - pcb_holder_position[0], - pcb_holder_position[1] - wall_thinner_size[1]/2, - wall_thinner_size[2]/2 + pcb_holder_thickness, - ) - ) + ( + pcb_holder_position[0], + pcb_holder_position[1] - wall_thinner_size[1]/2, + wall_thinner_size[2]/2 + pcb_holder_thickness, + ) + ) return shape - - def trrs_hole(): debugprint('trrs_hole()') trrs_position = copy.deepcopy(pcb_mount_ref_position) @@ -3327,21 +3361,22 @@ def trrs_hole(): trrs_hole_size = [3, 20] - shape = cylinder(*trrs_hole_size) shape = rotate(shape, [0, 90, 90]) shape = translate(shape, - ( - trrs_position[0], - trrs_position[1], - trrs_hole_size[0] + pcb_holder_thickness, - ) - ) + ( + trrs_position[0], + trrs_position[1], + trrs_hole_size[0] + pcb_holder_thickness, + ) + ) return shape + pcb_screw_position = copy.deepcopy(pcb_mount_ref_position) pcb_screw_position[1] = pcb_screw_position[1] + pcb_screw_y_offset + def pcb_screw_hole(): debugprint('pcb_screw_hole()') holes = [] @@ -3374,8 +3409,6 @@ def pcb_screw_hole(): oled_mount_rotation_xyz = (rad2deg(angle_x), 0, -rad2deg(angle_z)) + np.array(oled_rotation_offset) - - def generate_trackball(pos, rot): precut = trackball_cutout() precut = rotate(precut, tb_socket_rotation_offset) @@ -3416,6 +3449,7 @@ def generate_trackball(pos, rot): # return precut, shape, cutout, ball return precut, shape, cutout, sensor, ball + def generate_trackball_in_cluster(): if thumb_style == 'TRACKBALL_ORBYL': pos, rot = tbjs_thumb_position_rotation() @@ -3424,7 +3458,6 @@ def generate_trackball_in_cluster(): return generate_trackball(pos, rot) - def tbiw_position_rotation(): base_pt1 = key_position( list(np.array([-mount_width/2, 0, 0]) + np.array([0, (mount_height / 2), 0])), @@ -3442,9 +3475,9 @@ def tbiw_position_rotation(): left_wall_x_offset = tbiw_left_wall_x_offset_override tbiw_mount_location_xyz = ( - (np.array(base_pt1)+np.array(base_pt2))/2. - + np.array(((-left_wall_x_offset/2), 0, 0)) - + np.array(tbiw_translational_offset) + (np.array(base_pt1)+np.array(base_pt2))/2. + + np.array(((-left_wall_x_offset/2), 0, 0)) + + np.array(tbiw_translational_offset) ) # tbiw_mount_location_xyz[2] = (oled_translation_offset[2] + base_pt0[2])/2 @@ -3455,12 +3488,12 @@ def tbiw_position_rotation(): return tbiw_mount_location_xyz, tbiw_mount_rotation_xyz + def generate_trackball_in_wall(): pos, rot = tbiw_position_rotation() return generate_trackball(pos, rot) - def oled_position_rotation(side='right'): _oled_center_row = None if trackball_in_wall and (side == ball_side or ball_side == 'both'): @@ -3503,12 +3536,13 @@ def oled_position_rotation(side='right'): return oled_mount_location_xyz, oled_mount_rotation_xyz + def oled_sliding_mount_frame(side='right'): mount_ext_width = oled_mount_width + 2 * oled_mount_rim mount_ext_height = ( - oled_mount_height + 2 * oled_edge_overlap_end - + oled_edge_overlap_connector + oled_edge_overlap_clearance - + 2 * oled_mount_rim + oled_mount_height + 2 * oled_edge_overlap_end + + oled_edge_overlap_connector + oled_edge_overlap_clearance + + 2 * oled_mount_rim ) mount_ext_up_height = oled_mount_height + 2 * oled_mount_rim top_hole_start = -mount_ext_height / 2.0 + oled_mount_rim + oled_edge_overlap_end + oled_edge_overlap_connector @@ -3525,8 +3559,8 @@ def oled_sliding_mount_frame(side='right'): conn_hole_start = -mount_ext_height / 2.0 + oled_mount_rim conn_hole_length = ( - oled_edge_overlap_end + oled_edge_overlap_connector - + oled_edge_overlap_clearance + oled_thickness + oled_edge_overlap_end + oled_edge_overlap_connector + + oled_edge_overlap_clearance + oled_thickness ) conn_hole = box(oled_mount_width, conn_hole_length + .01, oled_mount_depth) conn_hole = translate(conn_hole, ( @@ -3536,7 +3570,7 @@ def oled_sliding_mount_frame(side='right'): )) end_hole_length = ( - oled_edge_overlap_end + oled_edge_overlap_clearance + oled_edge_overlap_end + oled_edge_overlap_clearance ) end_hole_start = mount_ext_height / 2.0 - oled_mount_rim - end_hole_length end_hole = box(oled_mount_width, end_hole_length + .01, oled_mount_depth) @@ -3583,29 +3617,29 @@ def oled_sliding_mount_frame(side='right'): shape = rotate(shape, oled_mount_rotation_xyz) shape = translate(shape, - ( - oled_mount_location_xyz[0], - oled_mount_location_xyz[1], - oled_mount_location_xyz[2], - ) - ) + ( + oled_mount_location_xyz[0], + oled_mount_location_xyz[1], + oled_mount_location_xyz[2], + ) + ) hole = rotate(hole, oled_mount_rotation_xyz) hole = translate(hole, - ( - oled_mount_location_xyz[0], - oled_mount_location_xyz[1], - oled_mount_location_xyz[2], - ) - ) + ( + oled_mount_location_xyz[0], + oled_mount_location_xyz[1], + oled_mount_location_xyz[2], + ) + ) return hole, shape def oled_clip_mount_frame(side='right'): mount_ext_width = oled_mount_width + 2 * oled_mount_rim mount_ext_height = ( - oled_mount_height + 2 * oled_clip_thickness - + 2 * oled_clip_undercut + 2 * oled_clip_overhang + 2 * oled_mount_rim + oled_mount_height + 2 * oled_clip_thickness + + 2 * oled_clip_undercut + 2 * oled_clip_overhang + 2 * oled_mount_rim ) hole = box(mount_ext_width, mount_ext_height, oled_mount_cut_depth + .01) @@ -3641,21 +3675,21 @@ def oled_clip_mount_frame(side='right'): shape = rotate(shape, oled_mount_rotation_xyz) shape = translate(shape, - ( - oled_mount_location_xyz[0], - oled_mount_location_xyz[1], - oled_mount_location_xyz[2], - ) - ) + ( + oled_mount_location_xyz[0], + oled_mount_location_xyz[1], + oled_mount_location_xyz[2], + ) + ) hole = rotate(hole, oled_mount_rotation_xyz) hole = translate(hole, - ( - oled_mount_location_xyz[0], - oled_mount_location_xyz[1], - oled_mount_location_xyz[2], - ) - ) + ( + oled_mount_location_xyz[0], + oled_mount_location_xyz[1], + oled_mount_location_xyz[2], + ) + ) return hole, shape @@ -3663,8 +3697,8 @@ def oled_clip_mount_frame(side='right'): def oled_clip(): mount_ext_width = oled_mount_width + 2 * oled_mount_rim mount_ext_height = ( - oled_mount_height + 2 * oled_clip_thickness + 2 * oled_clip_overhang - + 2 * oled_clip_undercut + 2 * oled_mount_rim + oled_mount_height + 2 * oled_clip_thickness + 2 * oled_clip_overhang + + 2 * oled_clip_undercut + 2 * oled_mount_rim ) oled_leg_depth = oled_mount_depth + oled_clip_z_gap @@ -3743,28 +3777,23 @@ def oled_undercut_mount_frame(side='right'): shape = rotate(shape, oled_mount_rotation_xyz) shape = translate(shape, ( - oled_mount_location_xyz[0], - oled_mount_location_xyz[1], - oled_mount_location_xyz[2], - ) + oled_mount_location_xyz[0], + oled_mount_location_xyz[1], + oled_mount_location_xyz[2], + ) ) hole = rotate(hole, oled_mount_rotation_xyz) hole = translate(hole, ( - oled_mount_location_xyz[0], - oled_mount_location_xyz[1], - oled_mount_location_xyz[2], - ) + oled_mount_location_xyz[0], + oled_mount_location_xyz[1], + oled_mount_location_xyz[2], + ) ) return hole, shape - - - - - def teensy_holder(): print('teensy_holder()') teensy_top_xy = key_position(wall_locate3(-1, 0), 0, centerrow - 1) @@ -3866,22 +3895,22 @@ def screw_insert(column, row, bottom_radius, top_radius, height, side='right'): ) elif shift_left: position = list( - np.array(left_key_position(row, 0, side=side)) + np.array(wall_locate3(-1, 0)) + np.array((shift_left_adjust,0,0)) + np.array(left_key_position(row, 0, side=side)) + np.array(wall_locate3(-1, 0)) + np.array((shift_left_adjust, 0, 0)) ) else: position = key_position( - list(np.array(wall_locate2(1, 0)) + np.array([(mount_height / 2), 0, 0]) + np.array((shift_right_adjust,0,0)) + list(np.array(wall_locate2(1, 0)) + np.array([(mount_height / 2), 0, 0]) + np.array((shift_right_adjust, 0, 0)) ), column, row, ) - shape = screw_insert_shape(bottom_radius, top_radius, height) shape = translate(shape, [position[0], position[1], height / 2]) return shape + def thumb_screw_insert(bottom_radius, top_radius, height, offset=None, side='right'): shape = screw_insert_shape(bottom_radius, top_radius, height) shapes = [] @@ -3938,13 +3967,14 @@ def thumb_screw_insert(bottom_radius, top_radius, height, offset=None, side='rig return shapes + def screw_insert_all_shapes(bottom_radius, top_radius, height, offset=0, side='right'): print('screw_insert_all_shapes()') shape = ( translate(screw_insert(0, 0, bottom_radius, top_radius, height, side=side), (0, 0, offset)), translate(screw_insert(0, cornerrow, bottom_radius, top_radius, height, side=side), (0, left_wall_lower_y_offset, offset)), translate(screw_insert(3, lastrow, bottom_radius, top_radius, height, side=side), (0, 0, offset)), - translate(screw_insert(3, 0, bottom_radius, top_radius, height, side=side), (0,0, offset)), + translate(screw_insert(3, 0, bottom_radius, top_radius, height, side=side), (0, 0, offset)), translate(screw_insert(lastcol, 0, bottom_radius, top_radius, height, side=side), (0, 0, offset)), translate(screw_insert(lastcol, cornerrow, bottom_radius, top_radius, height, side=side), (0, 0, offset)), # translate(screw_insert_thumb(bottom_radius, top_radius, height), (0, 0, offset)), @@ -3952,11 +3982,13 @@ def screw_insert_all_shapes(bottom_radius, top_radius, height, offset=0, side='r return shape + def thumb_screw_insert_holes(side='right'): return thumb_screw_insert( screw_insert_bottom_radius, screw_insert_top_radius, screw_insert_height+.02, offset=-.01, side=side ) + def thumb_screw_insert_outers(offset=0.0, side='right'): # screw_insert_bottom_radius + screw_insert_wall # screw_insert_top_radius + screw_insert_wall @@ -3965,11 +3997,13 @@ def thumb_screw_insert_outers(offset=0.0, side='right'): height = screw_insert_height + 1.5 return thumb_screw_insert(bottom_radius, top_radius, height, offset=offset, side=side) + def screw_insert_holes(side='right'): return screw_insert_all_shapes( screw_insert_bottom_radius, screw_insert_top_radius, screw_insert_height+.02, offset=-.01, side=side ) + def screw_insert_outers(offset=0.0, side='right'): # screw_insert_bottom_radius + screw_insert_wall # screw_insert_top_radius + screw_insert_wall @@ -3978,12 +4012,11 @@ def screw_insert_outers(offset=0.0, side='right'): height = screw_insert_height + 1.5 return screw_insert_all_shapes(bottom_radius, top_radius, height, offset=offset, side=side) + def screw_insert_screw_holes(side='right'): return screw_insert_all_shapes(1.7, 1.7, 350, side=side) - - def wire_post(direction, offset): debugprint('wire_post()') s1 = box( @@ -4061,7 +4094,7 @@ def model_side(side="right"): s2 = difference(s2, pcb_screw_hole()) if controller_mount_type in [None, 'None']: - 0 # do nothing, only here to expressly state inaction. + 0 # do nothing, only here to expressly state inaction. s2 = difference(s2, [union(screw_insert_holes(side=side))]) shape = union([shape, s2]) @@ -4104,7 +4137,7 @@ def model_side(side="right"): main_shape = shape - #BUILD THUMB + # BUILD THUMB thumb_shape = thumb(side=side) if debug_exports: @@ -4117,7 +4150,6 @@ def model_side(side="right"): thumb_wall_shape = union([thumb_wall_shape, *thumb_screw_insert_outers(side=side)]) thumb_connection_shape = thumb_connection(side=side, skeleton=skeletal) - if debug_exports: thumb_test = union([thumb_shape, thumb_connector_shape, thumb_wall_shape, thumb_connection_shape]) export_file(shape=thumb_test, fname=path.join(r"..", "things", r"debug_thumb_test_{}_shape".format(side))) @@ -4183,10 +4215,6 @@ def model_side(side="right"): if show_caps: main_shape = add([main_shape, ball]) - - - - if show_caps: main_shape = add([main_shape, caps()]) @@ -4198,12 +4226,11 @@ def model_side(side="right"): # NEEDS TO BE SPECIAL FOR CADQUERY -#def baseplate(main_shape, base_shape, wedge_angle=None, side='right'): +# def baseplate(main_shape, base_shape, wedge_angle=None, side='right'): def baseplate(wedge_angle=None, side='right'): if ENGINE == 'cadquery': # shape = mod_r - thumb_shape = thumb(side=side) thumb_wall_shape = thumb_walls(side=side, skeleton=skeletal) thumb_wall_shape = union([thumb_wall_shape, *thumb_screw_insert_outers(side=side)]) @@ -4251,7 +4278,7 @@ def baseplate(wedge_angle=None, side='right'): sizes.append(0) if not is_outside: sizes.append(len(wire.Vertices())) - if sizes[-1]>max_val: + if sizes[-1] > max_val: inner_index = i_wire max_val = sizes[-1] debugprint(sizes) @@ -4271,7 +4298,7 @@ def baseplate(wedge_angle=None, side='right'): cutout = [*holes, inner_wire] shape = cq.Workplane('XY').add(cq.Solid.extrudeLinear(outer_wire, cutout, cq.Vector(0, 0, base_rim_thickness))) - hole_shapes=[] + hole_shapes = [] for hole in holes: loc = hole.Center() hole_shapes.append( @@ -4285,7 +4312,6 @@ def baseplate(wedge_angle=None, side='right'): shape = translate(shape, (0, 0, -base_rim_thickness)) shape = union([shape, inner_shape]) - return shape else: @@ -4305,6 +4331,7 @@ def baseplate(wedge_angle=None, side='right'): return sl.projection(cut=True)(shape) + def run(): mod_r, tmb_r = model_side(side="right") @@ -4333,9 +4360,6 @@ def run(): export_file(shape=lbase, fname=path.join(save_path, config_name + r"_left_plate")) export_dxf(shape=lbase, fname=path.join(save_path, config_name + r"_left_plate")) - - - if oled_mount_type == 'UNDERCUT': export_file(shape=oled_undercut_mount_frame()[1], fname=path.join(save_path, config_name + r"_oled_undercut_test")) @@ -4347,9 +4371,10 @@ def run(): oled_mount_rotation_xyz = (0.0, 0.0, 0.0) export_file(shape=oled_clip(), fname=path.join(save_path, config_name + r"_oled_clip")) export_file(shape=oled_clip_mount_frame()[1], - fname=path.join(save_path, config_name + r"_oled_clip_test")) + fname=path.join(save_path, config_name + r"_oled_clip_test")) export_file(shape=union((oled_clip_mount_frame()[1], oled_clip())), - fname=path.join(save_path, config_name + r"_oled_clip_assy_test")) + fname=path.join(save_path, config_name + r"_oled_clip_assy_test")) + # base = baseplate() # export_file(shape=base, fname=path.join(save_path, config_name + r"_plate")) diff --git a/src/generate_configuration.py b/src/generate_configuration.py index c6ed586b7..084fe516a 100644 --- a/src/generate_configuration.py +++ b/src/generate_configuration.py @@ -22,10 +22,10 @@ 'config_name': "DM", 'show_caps': 'MX', - 'show_pcbs': False, #only runs if caps are shown, easist place to initially inject geometry + 'show_pcbs': False, # only runs if caps are shown, easist place to initially inject geometry - 'nrows': 5, #5, # key rows - 'ncols': 6, #6, # key columns + 'nrows': 5, # 5, # key rows + 'ncols': 6, # 6, # key columns 'alpha': pi / 12.0, # curvature of the columns 'beta': pi / 36.0, # curvature of the rows @@ -38,7 +38,7 @@ 'column_style_gt5': "orthographic", 'column_style': "standard", # options include :standard, :orthographic, and :fixed - 'reduced_inner_cols': 2, #currently supports 0 or 2 due to thumb cluster attachment + 'reduced_inner_cols': 2, # currently supports 0 or 2 due to thumb cluster attachment 'reduced_outer_cols': 0, @@ -63,7 +63,7 @@ # 'DEFAULT' 6-key, 'MINI' 5-key, 'CARBONFET' 6-key, 'MINIDOX' 3-key, 'TRACKBALL_ORBYL', 'TRACKBALL_CJ' 'thumb_style': 'DEFAULT', - 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U + 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U # Thumb key size. May need slight oversizing, check w/ caps. Additional spacing will be automatically added for larger keys. 'minidox_Usize': 1.6, # Thumb plate rotations, anything other than 90 degree increments WILL NOT WORK. @@ -94,14 +94,14 @@ 'thumb_plate_bl_rotation': 0.0, # Bottom right plate rotation tweaks as thumb cluster is crowded for hot swap, etc. ############################## # EXPERIMENTAL - 'separable_thumb': False, #creates a separable thumb section with additional screws to hold it down. Only attached at base. + 'separable_thumb': False, # creates a separable thumb section with additional screws to hold it down. Only attached at base. ############################## ################################### ## Trackball in Wall ## ################################### 'trackball_in_wall': False, # Separate trackball option, placing it in the OLED area - 'tbiw_ball_center_row': 0.2, # up from cornerrow instead of down from top + 'tbiw_ball_center_row': 0.2, # up from cornerrow instead of down from top 'tbiw_translational_offset': (0.0, 0.0, 0.0), 'tbiw_rotation_offset': (0.0, 0.0, 0.0), 'tbiw_left_wall_x_offset_override': 50.0, @@ -130,7 +130,7 @@ ########################################### ## Trackball JS / ORBYL Thumb Cluster ## ########################################## - 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' + 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' 'tbjs_key_diameter': 70, 'tbjs_Uwidth': 1.2, # size for inner key near trackball 'tbjs_Uheight': 1.2, # size for inner key near trackball @@ -171,7 +171,7 @@ 'trackball_modular_ring_height': 10.0, # height mount ring down from ball height. Covers gaps on elevated ball. 'trackball_modular_clearance': 0.5, # height of ball from ring, used to create identical position to fixed. - 'ball_side': 'both', #'left', 'right', or 'both' + 'ball_side': 'both', # 'left', 'right', or 'both' 'ball_diameter': 34.0, 'ball_wall_thickness': 3, # should not be changed unless the import models are changed. 'ball_gap': 1.0, @@ -182,8 +182,8 @@ # Removed trackball_rotation, ball_z_offset. and trackball_sensor_rotation and added more flexibility. 'tb_socket_translation_offset': (0, 0, 2.0), # applied to the socket and sensor, large values will cause web/wall issues. 'tb_socket_rotation_offset': (0, 0, 0), # applied to the socket and sensor, large values will cause web/wall issues. - 'tb_sensor_translation_offset': (0, 0, 0), #deviation from socket offsets, for fixing generated geometry issues - 'tb_sensor_rotation_offset': (0, 0, 0), #deviation from socket offsets, for changing the sensor roll orientation + 'tb_sensor_translation_offset': (0, 0, 0), # deviation from socket offsets, for fixing generated geometry issues + 'tb_sensor_rotation_offset': (0, 0, 0), # deviation from socket offsets, for changing the sensor roll orientation ############################## # EXPERIMENTAL PARAMETERS @@ -211,11 +211,11 @@ 'wall_base_back_thickness': 4.5, # wall thickness at the lower stage in the specifically in back for interface. - ## Settings for column_style == :fixed - ## The defaults roughly match Maltron settings - ## http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png - ## fixed_z overrides the z portion of the column ofsets above. - ## NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. + # Settings for column_style == :fixed + # The defaults roughly match Maltron settings + # http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png + # fixed_z overrides the z portion of the column ofsets above. + # NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. 'fixed_angles': [d2r * 10, d2r * 10, 0, 0, 0, d2r * -15, d2r * -15], 'fixed_x': [-41.5, -22.5, 0, 20.3, 41.4, 65.5, 89.6], # relative to the middle finger 'fixed_z': [12.1, 8.3, 0, 5, 10.7, 14.5, 17.5], @@ -246,7 +246,7 @@ 'undercut_keyswitch_height': 14.0, 'undercut_keyswitch_width': 14.0, - 'notch_width': 6.0, # If using notch, it is identical to undecut, but only locally by the switch clip + 'notch_width': 6.0, # If using notch, it is identical to undecut, but only locally by the switch clip 'sa_profile_key_height': 12.7, 'sa_length': 18.5, @@ -264,7 +264,7 @@ 'plate_offset': 0.0, ########################## - ## OLED Mount Location + # OLED Mount Location ########################## # Initial pass will be manual placement. Can be used to create other mounts as well. # Mount type options: @@ -274,20 +274,20 @@ # 'CLIP' = Features to set the OLED in a frame a snap a bezel down to hold it in place. 'oled_mount_type': 'CLIP', - 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings - 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. + 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings + 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. 'oled_rotation_offset': (0, 0, 0), 'oled_configurations': { - 'UNDERCUT':{ + 'UNDERCUT': { # Common parameters 'oled_mount_width': 15.0, 'oled_mount_height': 35.0, 'oled_mount_rim': 3.0, 'oled_mount_depth': 6.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 28.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -304,8 +304,8 @@ 'oled_mount_rim': 2.5, 'oled_mount_depth': 8.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -326,8 +326,8 @@ 'oled_mount_rim': 2.0, 'oled_mount_depth': 7.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -353,7 +353,7 @@ } }, - 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' + 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' 'screw_insert_height': 3.8, @@ -388,7 +388,7 @@ 'external_holder_height': 12.5, 'external_holder_width': 28.75, 'external_holder_xoffset': -5.0, - 'external_holder_yoffset': -4.5, #Tweak this value to get the right undercut for the tray engagement. + 'external_holder_yoffset': -4.5, # Tweak this value to get the right undercut for the tray engagement. # Offset is from the top inner corner of the top inner key. @@ -408,18 +408,18 @@ "trrs_offset": [0, 0, 1.5], "pcb_screw_hole_size": [.5, 10], - "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference + "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference "pcb_screw_y_offset": -2, ################################### - ## Bottom Plate Dimensions + # Bottom Plate Dimensions ################################### # COMMON DIMENSION 'screw_hole_diameter': 3, # USED FOR CADQUERY ONLY - 'base_thickness': 3.0, # thickness in the middle of the plate - 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) + 'base_thickness': 3.0, # thickness in the middle of the plate + 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) 'base_rim_thickness': 5.0, # thickness on the outer frame with screws 'screw_cbore_diameter': 6.0, 'screw_cbore_depth': 2.5, @@ -427,7 +427,7 @@ # Offset is from the top inner corner of the top inner key. ################################### - ## HOLES ON PLATE FOR PCB MOUNT + # HOLES ON PLATE FOR PCB MOUNT ################################### 'plate_holes': True, 'plate_holes_xy_offset': (0.0, 0.0), @@ -437,14 +437,14 @@ 'plate_holes_depth': 20.0, ################################### - ## EXPERIMENTAL + # EXPERIMENTAL 'plate_pcb_clear': False, 'plate_pcb_size': (18.5, 18.5, 5), - 'plate_pcb_offset': (0, 0, 0),# this is off of the back of the plate size. + 'plate_pcb_offset': (0, 0, 0), # this is off of the back of the plate size. ################################### ################################### - ## SHOW PCB FOR FIT CHECK + # SHOW PCB FOR FIT CHECK ################################### 'pcb_width': 18.0, 'pcb_height': 18.0, @@ -454,7 +454,7 @@ 'pcb_hole_pattern_height': 14.3, ################################### - ## COLUMN OFFSETS + # COLUMN OFFSETS #################################### 'column_offsets': [ @@ -462,16 +462,17 @@ [0, 0, 0], [0, 2.82, -4.5], [0, 0, 0], - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# NOT USED IN MOST FORMATS (7th column) + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # NOT USED IN MOST FORMATS (7th column) ], } - #################################### - ## END CONFIGURATION SECTION - #################################### +#################################### +# END CONFIGURATION SECTION +#################################### + def save_config(): # Check to see if the user has specified an alternate config @@ -504,6 +505,6 @@ def save_config(): if __name__ == '__main__': save_config() - ## HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT + # HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT # from dactyl_manuform import * # run() diff --git a/src/generate_configuration_mklasklasd.py b/src/generate_configuration_mklasklasd.py index 4263a1f75..c1768f65d 100644 --- a/src/generate_configuration_mklasklasd.py +++ b/src/generate_configuration_mklasklasd.py @@ -22,10 +22,10 @@ 'config_name': "DM", 'show_caps': False, - 'show_pcbs': False, #only runs if caps are shown, easist place to initially inject geometry + 'show_pcbs': False, # only runs if caps are shown, easist place to initially inject geometry - 'nrows': 4, #5, # key rows - 'ncols': 5, #6, # key columns + 'nrows': 4, # 5, # key rows + 'ncols': 5, # 6, # key columns 'alpha': pi / 12.0, # curvature of the columns 'beta': pi / 36.0, # curvature of the rows @@ -38,7 +38,7 @@ 'column_style_gt5': "orthographic", 'column_style': "standard", # options include :standard, :orthographic, and :fixed - 'reduced_inner_cols': 2, #currently supports 0 or 2 due to thumb cluster attachment + 'reduced_inner_cols': 2, # currently supports 0 or 2 due to thumb cluster attachment 'reduced_outer_cols': 0, 'thumb_offsets': [6, -3, 7], @@ -62,7 +62,7 @@ # 'DEFAULT' 6-key, 'MINI' 5-key, 'CARBONFET' 6-key, 'MINIDOX' 3-key, 'TRACKBALL_ORBYL', 'TRACKBALL_CJ' 'thumb_style': 'MINI', - 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U + 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U # Thumb key size. May need slight oversizing, check w/ caps. Additional spacing will be automatically added for larger keys. 'minidox_Usize': 1.6, # Thumb plate rotations, anything other than 90 degree increments WILL NOT WORK. @@ -91,14 +91,14 @@ 'thumb_plate_bl_rotation': 0.0, # Bottom right plate rotation tweaks as thumb cluster is crowded for hot swap, etc. ############################## # EXPERIMENTAL - 'separable_thumb': False, #creates a separable thumb section with additional screws to hold it down. Only attached at base. + 'separable_thumb': False, # creates a separable thumb section with additional screws to hold it down. Only attached at base. ############################## ################################### ## Trackball in Wall ## ################################### 'trackball_in_wall': False, # Separate trackball option, placing it in the OLED area - 'tbiw_ball_center_row': 0.2, # up from cornerrow instead of down from top + 'tbiw_ball_center_row': 0.2, # up from cornerrow instead of down from top 'tbiw_translational_offset': (0.0, 0.0, 0.0), 'tbiw_rotation_offset': (0.0, 0.0, 0.0), 'tbiw_left_wall_x_offset_override': 50.0, @@ -127,7 +127,7 @@ ########################################### ## Trackball JS / ORBYL Thumb Cluster ## ########################################## - 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' + 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' 'tbjs_key_diameter': 70, 'tbjs_Uwidth': 1.2, # size for inner key near trackball 'tbjs_Uheight': 1.2, # size for inner key near trackball @@ -168,7 +168,7 @@ 'trackball_modular_ring_height': 10.0, # height mount ring down from ball height. Covers gaps on elevated ball. 'trackball_modular_clearance': 0.5, # height of ball from ring, used to create identical position to fixed. - 'ball_side': 'both', #'left', 'right', or 'both' + 'ball_side': 'both', # 'left', 'right', or 'both' 'ball_diameter': 34.0, 'ball_wall_thickness': 3, # should not be changed unless the import models are changed. 'ball_gap': 1.0, @@ -179,8 +179,8 @@ # Removed trackball_rotation, ball_z_offset. and trackball_sensor_rotation and added more flexibility. 'tb_socket_translation_offset': (0, 0, 2.0), # applied to the socket and sensor, large values will cause web/wall issues. 'tb_socket_rotation_offset': (0, 0, 0), # applied to the socket and sensor, large values will cause web/wall issues. - 'tb_sensor_translation_offset': (0, 0, 0), #deviation from socket offsets, for fixing generated geometry issues - 'tb_sensor_rotation_offset': (0, 0, 0), #deviation from socket offsets, for changing the sensor roll orientation + 'tb_sensor_translation_offset': (0, 0, 0), # deviation from socket offsets, for fixing generated geometry issues + 'tb_sensor_rotation_offset': (0, 0, 0), # deviation from socket offsets, for changing the sensor roll orientation ############################## # EXPERIMENTAL PARAMETERS @@ -208,11 +208,11 @@ 'wall_base_back_thickness': 4.5, # wall thickness at the lower stage in the specifically in back for interface. - ## Settings for column_style == :fixed - ## The defaults roughly match Maltron settings - ## http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png - ## fixed_z overrides the z portion of the column ofsets above. - ## NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. + # Settings for column_style == :fixed + # The defaults roughly match Maltron settings + # http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png + # fixed_z overrides the z portion of the column ofsets above. + # NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. 'fixed_angles': [d2r * 10, d2r * 10, 0, 0, 0, d2r * -15, d2r * -15], 'fixed_x': [-41.5, -22.5, 0, 20.3, 41.4, 65.5, 89.6], # relative to the middle finger 'fixed_z': [12.1, 8.3, 0, 5, 10.7, 14.5, 17.5], @@ -243,7 +243,7 @@ 'undercut_keyswitch_height': 14.0, 'undercut_keyswitch_width': 14.0, - 'notch_width': 6.0, # If using notch, it is identical to undecut, but only locally by the switch clip + 'notch_width': 6.0, # If using notch, it is identical to undecut, but only locally by the switch clip 'sa_profile_key_height': 12.7, 'sa_length': 18.5, @@ -261,7 +261,7 @@ 'plate_offset': 0.0, ########################## - ## OLED Mount Location + # OLED Mount Location ########################## # Initial pass will be manual placement. Can be used to create other mounts as well. # Mount type options: @@ -271,20 +271,20 @@ # 'CLIP' = Features to set the OLED in a frame a snap a bezel down to hold it in place. 'oled_mount_type': 'CLIP', - 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings - 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. + 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings + 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. 'oled_rotation_offset': (0, 0, 0), 'oled_configurations': { - 'UNDERCUT':{ + 'UNDERCUT': { # Common parameters 'oled_mount_width': 15.0, 'oled_mount_height': 35.0, 'oled_mount_rim': 3.0, 'oled_mount_depth': 6.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 28.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -301,8 +301,8 @@ 'oled_mount_rim': 2.5, 'oled_mount_depth': 8.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -323,8 +323,8 @@ 'oled_mount_rim': 2.0, 'oled_mount_depth': 7.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 5.0, @@ -350,7 +350,7 @@ } }, - 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' + 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' 'screw_insert_height': 3.8, @@ -385,7 +385,7 @@ 'external_holder_height': 12.5, 'external_holder_width': 28.75, 'external_holder_xoffset': -5.0, - 'external_holder_yoffset': -4.5, #Tweak this value to get the right undercut for the tray engagement. + 'external_holder_yoffset': -4.5, # Tweak this value to get the right undercut for the tray engagement. # Offset is from the top inner corner of the top inner key. @@ -405,18 +405,18 @@ "trrs_offset": [0, 0, 1.5], "pcb_screw_hole_size": [.5, 10], - "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference + "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference "pcb_screw_y_offset": -2, ################################### - ## Bottom Plate Dimensions + # Bottom Plate Dimensions ################################### # COMMON DIMENSION 'screw_hole_diameter': 3, # USED FOR CADQUERY ONLY - 'base_thickness': 3.0, # thickness in the middle of the plate - 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) + 'base_thickness': 3.0, # thickness in the middle of the plate + 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) 'base_rim_thickness': 5.0, # thickness on the outer frame with screws 'screw_cbore_diameter': 6.0, 'screw_cbore_depth': 2.5, @@ -424,7 +424,7 @@ # Offset is from the top inner corner of the top inner key. ################################### - ## HOLES ON PLATE FOR PCB MOUNT + # HOLES ON PLATE FOR PCB MOUNT ################################### 'plate_holes': True, 'plate_holes_xy_offset': (0.0, 0.0), @@ -434,14 +434,14 @@ 'plate_holes_depth': 20.0, ################################### - ## EXPERIMENTAL + # EXPERIMENTAL 'plate_pcb_clear': False, 'plate_pcb_size': (18.5, 18.5, 5), - 'plate_pcb_offset': (0, 0, 0),# this is off of the back of the plate size. + 'plate_pcb_offset': (0, 0, 0), # this is off of the back of the plate size. ################################### ################################### - ## SHOW PCB FOR FIT CHECK + # SHOW PCB FOR FIT CHECK ################################### 'pcb_width': 18.0, 'pcb_height': 18.0, @@ -451,7 +451,7 @@ 'pcb_hole_pattern_height': 14.3, ################################### - ## COLUMN OFFSETS + # COLUMN OFFSETS #################################### 'column_offsets': [ @@ -459,16 +459,17 @@ [0, 0, 0], [0, 2.82, -4.5], [0, 0, 0], - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# NOT USED IN MOST FORMATS (7th column) + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # NOT USED IN MOST FORMATS (7th column) ], } - #################################### - ## END CONFIGURATION SECTION - #################################### +#################################### +# END CONFIGURATION SECTION +#################################### + def save_config(): # Check to see if the user has specified an alternate config diff --git a/src/generate_configuration_orbyl_test.py b/src/generate_configuration_orbyl_test.py index 383b8cff6..9c7880605 100644 --- a/src/generate_configuration_orbyl_test.py +++ b/src/generate_configuration_orbyl_test.py @@ -22,10 +22,10 @@ 'config_name': "DM", 'show_caps': False, - 'show_pcbs': False, #only runs if caps are shown, easist place to initially inject geometry + 'show_pcbs': False, # only runs if caps are shown, easist place to initially inject geometry - 'nrows': 5, #5, # key rows - 'ncols': 6, #6, # key columns + 'nrows': 5, # 5, # key rows + 'ncols': 6, # 6, # key columns 'alpha': pi / 12.0, # curvature of the columns 'beta': pi / 36.0, # curvature of the rows @@ -60,7 +60,7 @@ # 'DEFAULT' 6-key, 'MINI' 5-key, 'CARBONFET' 6-key, 'MINIDOX' 3-key, 'TRACKBALL_ORBYL', 'TRACKBALL_CJ' 'thumb_style': 'TRACKBALL_ORBYL', - 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U + 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U # Thumb key size. May need slight oversizing, check w/ caps. Additional spacing will be automatically added for larger keys. 'minidox_Usize': 1.6, # Thumb plate rotations, anything other than 90 degree increments WILL NOT WORK. @@ -89,14 +89,14 @@ 'thumb_plate_bl_rotation': 0.0, # Bottom right plate rotation tweaks as thumb cluster is crowded for hot swap, etc. ############################## # EXPERIMENTAL - 'separable_thumb': True, #creates a separable thumb section with additional screws to hold it down. Only attached at base. + 'separable_thumb': True, # creates a separable thumb section with additional screws to hold it down. Only attached at base. ############################## ################################### ## Trackball in Wall ## ################################### 'trackball_in_wall': False, # Separate trackball option, placing it in the OLED area - 'tbiw_ball_center_row': 0.2, # up from cornerrow instead of down from top + 'tbiw_ball_center_row': 0.2, # up from cornerrow instead of down from top 'tbiw_translational_offset': (0.0, 0.0, 0.0), 'tbiw_rotation_offset': (0.0, 0.0, 0.0), 'tbiw_left_wall_x_offset_override': 50.0, @@ -125,7 +125,7 @@ ########################################### ## Trackball JS / ORBYL Thumb Cluster ## ########################################## - 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' + 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' 'tbjs_key_diameter': 70, 'tbjs_Uwidth': 1.2, # size for inner key near trackball 'tbjs_Uheight': 1.2, # size for inner key near trackball @@ -166,7 +166,7 @@ 'trackball_modular_ring_height': 10.0, # height mount ring down from ball height. Covers gaps on elevated ball. 'trackball_modular_clearance': 0.5, # height of ball from ring, used to create identical position to fixed. - 'ball_side': 'both', #'left', 'right', or 'both' + 'ball_side': 'both', # 'left', 'right', or 'both' 'ball_diameter': 34.0, 'ball_wall_thickness': 3, # should not be changed unless the import models are changed. 'ball_gap': 1.0, @@ -177,8 +177,8 @@ # Removed trackball_rotation, ball_z_offset. and trackball_sensor_rotation and added more flexibility. 'tb_socket_translation_offset': (0, 0, 2.0), # applied to the socket and sensor, large values will cause web/wall issues. 'tb_socket_rotation_offset': (0, 0, 0), # applied to the socket and sensor, large values will cause web/wall issues. - 'tb_sensor_translation_offset': (0, 0, 0), #deviation from socket offsets, for fixing generated geometry issues - 'tb_sensor_rotation_offset': (0, 0, 0), #deviation from socket offsets, for changing the sensor roll orientation + 'tb_sensor_translation_offset': (0, 0, 0), # deviation from socket offsets, for fixing generated geometry issues + 'tb_sensor_rotation_offset': (0, 0, 0), # deviation from socket offsets, for changing the sensor roll orientation ############################## # EXPERIMENTAL PARAMETERS @@ -193,7 +193,7 @@ 'wall_x_offset': 5, # offset in the x and/or y direction for the first downward_sloping part of the wall (negative) 'wall_y_offset': 6, # offset in the x and/or y direction for the first downward_sloping part of the wall (negative) 'left_wall_x_offset': 12, # specific values for the left side due to the minimal wall. - 'left_wall_z_offset': -3, # specific values for the left side due to the minimal wall. + 'left_wall_z_offset': -3, # specific values for the left side due to the minimal wall. 'left_wall_lower_x_offset': 0, # specific values for the lower left corner. 'left_wall_lower_y_offset': 0, # specific values for the lower left corner. 'left_wall_lower_z_offset': 0, @@ -203,11 +203,11 @@ 'wall_base_back_thickness': 4.5, # wall thickness at the lower stage in the specifically in back for interface. - ## Settings for column_style == :fixed - ## The defaults roughly match Maltron settings - ## http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png - ## fixed_z overrides the z portion of the column ofsets above. - ## NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. + # Settings for column_style == :fixed + # The defaults roughly match Maltron settings + # http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png + # fixed_z overrides the z portion of the column ofsets above. + # NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. 'fixed_angles': [d2r * 10, d2r * 10, 0, 0, 0, d2r * -15, d2r * -15], 'fixed_x': [-41.5, -22.5, 0, 20.3, 41.4, 65.5, 89.6], # relative to the middle finger 'fixed_z': [12.1, 8.3, 0, 5, 10.7, 14.5, 17.5], @@ -238,7 +238,7 @@ 'undercut_keyswitch_height': 14.0, 'undercut_keyswitch_width': 14.0, - 'notch_width': 5.0, # If using notch, it is identical to undecut, but only locally by the switch clip + 'notch_width': 5.0, # If using notch, it is identical to undecut, but only locally by the switch clip 'sa_profile_key_height': 12.7, 'sa_length': 18.5, @@ -256,7 +256,7 @@ 'plate_offset': 0.0, ########################## - ## OLED Mount Location + # OLED Mount Location ########################## # Initial pass will be manual placement. Can be used to create other mounts as well. # Mount type options: @@ -266,20 +266,20 @@ # 'CLIP' = Features to set the OLED in a frame a snap a bezel down to hold it in place. 'oled_mount_type': 'CLIP', - 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings - 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. + 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings + 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. 'oled_rotation_offset': (0, 0, 0), 'oled_configurations': { - 'UNDERCUT':{ + 'UNDERCUT': { # Common parameters 'oled_mount_width': 15.0, 'oled_mount_height': 35.0, 'oled_mount_rim': 3.0, 'oled_mount_depth': 6.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 28.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -296,8 +296,8 @@ 'oled_mount_rim': 2.5, 'oled_mount_depth': 8.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -318,8 +318,8 @@ 'oled_mount_rim': 2.0, 'oled_mount_depth': 7.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -345,7 +345,7 @@ } }, - 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' + 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' 'screw_insert_height': 3.8, @@ -380,7 +380,7 @@ 'external_holder_height': 12.5, 'external_holder_width': 28.75, 'external_holder_xoffset': -5.0, - 'external_holder_yoffset': -4.5, #Tweak this value to get the right undercut for the tray engagement. + 'external_holder_yoffset': -4.5, # Tweak this value to get the right undercut for the tray engagement. # Offset is from the top inner corner of the top inner key. @@ -400,18 +400,18 @@ "trrs_offset": [0, 0, 1.5], "pcb_screw_hole_size": [.5, 10], - "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference + "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference "pcb_screw_y_offset": -2, ################################### - ## Bottom Plate Dimensions + # Bottom Plate Dimensions ################################### # COMMON DIMENSION 'screw_hole_diameter': 3, # USED FOR CADQUERY ONLY - 'base_thickness': 3.0, # thickness in the middle of the plate - 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) + 'base_thickness': 3.0, # thickness in the middle of the plate + 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) 'base_rim_thickness': 5.0, # thickness on the outer frame with screws 'screw_cbore_diameter': 6.0, 'screw_cbore_depth': 2.5, @@ -419,7 +419,7 @@ # Offset is from the top inner corner of the top inner key. ################################### - ## HOLES ON PLATE FOR PCB MOUNT + # HOLES ON PLATE FOR PCB MOUNT ################################### 'plate_holes': True, 'plate_holes_xy_offset': (0.0, 0.0), @@ -429,14 +429,14 @@ 'plate_holes_depth': 20.0, ################################### - ## EXPERIMENTAL + # EXPERIMENTAL 'plate_pcb_clear': False, 'plate_pcb_size': (18.5, 18.5, 5), - 'plate_pcb_offset': (0, 0, 0),# this is off of the back of the plate size. + 'plate_pcb_offset': (0, 0, 0), # this is off of the back of the plate size. ################################### ################################### - ## SHOW PCB FOR FIT CHECK + # SHOW PCB FOR FIT CHECK ################################### 'pcb_width': 18.0, 'pcb_height': 18.0, @@ -446,7 +446,7 @@ 'pcb_hole_pattern_height': 14.3, ################################### - ## COLUMN OFFSETS + # COLUMN OFFSETS #################################### 'column_offsets': [ @@ -454,16 +454,17 @@ [0, 0, 0], [0, 2.82, -4.5], [0, 0, 0], - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# NOT USED IN MOST FORMATS (7th column) + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # NOT USED IN MOST FORMATS (7th column) ], } - #################################### - ## END CONFIGURATION SECTION - #################################### +#################################### +# END CONFIGURATION SECTION +#################################### + def save_config(): # Check to see if the user has specified an alternate config @@ -496,6 +497,6 @@ def save_config(): if __name__ == '__main__': save_config() - ## HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT + # HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT from dactyl_manuform import * - run() \ No newline at end of file + run() diff --git a/src/generate_configuration_test.py b/src/generate_configuration_test.py index 26ad0961a..e611dd841 100644 --- a/src/generate_configuration_test.py +++ b/src/generate_configuration_test.py @@ -22,10 +22,10 @@ 'config_name': "DM", 'show_caps': False, - 'show_pcbs': False, #only runs if caps are shown, easist place to initially inject geometry + 'show_pcbs': False, # only runs if caps are shown, easist place to initially inject geometry - 'nrows': 5, #5, # key rows - 'ncols': 6, #6, # key columns + 'nrows': 5, # 5, # key rows + 'ncols': 6, # 6, # key columns 'alpha': pi / 12.0, # curvature of the columns 'beta': pi / 36.0, # curvature of the rows @@ -62,7 +62,7 @@ # 'DEFAULT' 6-key, 'MINI' 5-key, 'CARBONFET' 6-key, 'MINIDOX' 3-key, 'TRACKBALL_ORBYL', 'TRACKBALL_CJ' 'thumb_style': 'CARBONFET', - 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U + 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U # Thumb key size. May need slight oversizing, check w/ caps. Additional spacing will be automatically added for larger keys. 'minidox_Usize': 1.6, # Thumb plate rotations, anything other than 90 degree increments WILL NOT WORK. @@ -91,7 +91,7 @@ 'thumb_plate_bl_rotation': 0.0, # Bottom right plate rotation tweaks as thumb cluster is crowded for hot swap, etc. ############################## # EXPERIMENTAL - 'separable_thumb': False, #creates a separable thumb section with additional screws to hold it down. Only attached at base. + 'separable_thumb': False, # creates a separable thumb section with additional screws to hold it down. Only attached at base. ############################## ################################### @@ -127,7 +127,7 @@ ########################################### ## Trackball JS / ORBYL Thumb Cluster ## ########################################## - 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' + 'other_thumb': 'DEFAULT', # cluster used for second thumb except if ball_side == 'both' 'tbjs_key_diameter': 70, 'tbjs_Uwidth': 1.2, # size for inner key near trackball 'tbjs_Uheight': 1.2, # size for inner key near trackball @@ -168,7 +168,7 @@ 'trackball_modular_ring_height': 10.0, # height mount ring down from ball height. Covers gaps on elevated ball. 'trackball_modular_clearance': 0.5, # height of ball from ring, used to create identical position to fixed. - 'ball_side': 'both', #'left', 'right', or 'both' + 'ball_side': 'both', # 'left', 'right', or 'both' 'ball_diameter': 34.0, 'ball_wall_thickness': 3, # should not be changed unless the import models are changed. 'ball_gap': 1.0, @@ -179,8 +179,8 @@ # Removed trackball_rotation, ball_z_offset. and trackball_sensor_rotation and added more flexibility. 'tb_socket_translation_offset': (0, 0, 2.0), # applied to the socket and sensor, large values will cause web/wall issues. 'tb_socket_rotation_offset': (0, 0, 0), # applied to the socket and sensor, large values will cause web/wall issues. - 'tb_sensor_translation_offset': (0, 0, 0), #deviation from socket offsets, for fixing generated geometry issues - 'tb_sensor_rotation_offset': (0, 0, 0), #deviation from socket offsets, for changing the sensor roll orientation + 'tb_sensor_translation_offset': (0, 0, 0), # deviation from socket offsets, for fixing generated geometry issues + 'tb_sensor_rotation_offset': (0, 0, 0), # deviation from socket offsets, for changing the sensor roll orientation ############################## # EXPERIMENTAL PARAMETERS @@ -205,11 +205,11 @@ 'wall_base_back_thickness': 4.5, # wall thickness at the lower stage in the specifically in back for interface. - ## Settings for column_style == :fixed - ## The defaults roughly match Maltron settings - ## http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png - ## fixed_z overrides the z portion of the column ofsets above. - ## NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. + # Settings for column_style == :fixed + # The defaults roughly match Maltron settings + # http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png + # fixed_z overrides the z portion of the column ofsets above. + # NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. 'fixed_angles': [d2r * 10, d2r * 10, 0, 0, 0, d2r * -15, d2r * -15], 'fixed_x': [-41.5, -22.5, 0, 20.3, 41.4, 65.5, 89.6], # relative to the middle finger 'fixed_z': [12.1, 8.3, 0, 5, 10.7, 14.5, 17.5], @@ -240,7 +240,7 @@ 'undercut_keyswitch_height': 14.0, 'undercut_keyswitch_width': 14.0, - 'notch_width': 5.0, # If using notch, it is identical to undecut, but only locally by the switch clip + 'notch_width': 5.0, # If using notch, it is identical to undecut, but only locally by the switch clip 'sa_profile_key_height': 12.7, 'sa_length': 18.5, @@ -258,7 +258,7 @@ 'plate_offset': 0.0, ########################## - ## OLED Mount Location + # OLED Mount Location ########################## # Initial pass will be manual placement. Can be used to create other mounts as well. # Mount type options: @@ -268,20 +268,20 @@ # 'CLIP' = Features to set the OLED in a frame a snap a bezel down to hold it in place. 'oled_mount_type': 'NONE', - 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings - 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. + 'oled_center_row': 1.25, # if not None, this will override the oled_mount_location_xyz and oled_mount_rotation_xyz settings + 'oled_translation_offset': (0, 0, 4), # Z offset tweaks are expected depending on curvature and OLED mount choice. 'oled_rotation_offset': (0, 0, 0), 'oled_configurations': { - 'UNDERCUT':{ + 'UNDERCUT': { # Common parameters 'oled_mount_width': 15.0, 'oled_mount_height': 35.0, 'oled_mount_rim': 3.0, 'oled_mount_depth': 6.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-80.0, 20.0, 45.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (13.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 28.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -298,8 +298,8 @@ 'oled_mount_rim': 2.5, 'oled_mount_depth': 8.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 10.0, 41.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (6.0, 0.0, -3.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -320,8 +320,8 @@ 'oled_mount_rim': 2.0, 'oled_mount_depth': 7.0, 'oled_mount_cut_depth': 20.0, - 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None - 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None + 'oled_mount_location_xyz': (-78.0, 20.0, 42.0), # will be overwritten if oled_center_row is not None + 'oled_mount_rotation_xyz': (12.0, 0.0, -6.0), # will be overwritten if oled_center_row is not None 'oled_left_wall_x_offset_override': 24.0, 'oled_left_wall_z_offset_override': 0.0, 'oled_left_wall_lower_y_offset': 12.0, @@ -347,7 +347,7 @@ } }, - 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' + 'screws_offset': 'INSIDE', # 'OUTSIDE', 'INSIDE', 'ORIGINAL' 'screw_insert_height': 3.8, @@ -382,7 +382,7 @@ 'external_holder_height': 12.5, 'external_holder_width': 28.75, 'external_holder_xoffset': -5.0, - 'external_holder_yoffset': -4.5, #Tweak this value to get the right undercut for the tray engagement. + 'external_holder_yoffset': -4.5, # Tweak this value to get the right undercut for the tray engagement. # Offset is from the top inner corner of the top inner key. @@ -402,18 +402,18 @@ "trrs_offset": [0, 0, 1.5], "pcb_screw_hole_size": [.5, 10], - "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference + "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference "pcb_screw_y_offset": -2, ################################### - ## Bottom Plate Dimensions + # Bottom Plate Dimensions ################################### # COMMON DIMENSION 'screw_hole_diameter': 3, # USED FOR CADQUERY ONLY - 'base_thickness': 3.0, # thickness in the middle of the plate - 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) + 'base_thickness': 3.0, # thickness in the middle of the plate + 'base_offset': 3.0, # Both start flat/flush on the bottom. This offsets the base up (if positive) 'base_rim_thickness': 5.0, # thickness on the outer frame with screws 'screw_cbore_diameter': 6.0, 'screw_cbore_depth': 2.5, @@ -421,7 +421,7 @@ # Offset is from the top inner corner of the top inner key. ################################### - ## HOLES ON PLATE FOR PCB MOUNT + # HOLES ON PLATE FOR PCB MOUNT ################################### 'plate_holes': True, 'plate_holes_xy_offset': (0.0, 0.0), @@ -431,14 +431,14 @@ 'plate_holes_depth': 20.0, ################################### - ## EXPERIMENTAL + # EXPERIMENTAL 'plate_pcb_clear': False, 'plate_pcb_size': (18.5, 18.5, 5), - 'plate_pcb_offset': (0, 0, 0),# this is off of the back of the plate size. + 'plate_pcb_offset': (0, 0, 0), # this is off of the back of the plate size. ################################### ################################### - ## SHOW PCB FOR FIT CHECK + # SHOW PCB FOR FIT CHECK ################################### 'pcb_width': 18.0, 'pcb_height': 18.0, @@ -448,7 +448,7 @@ 'pcb_hole_pattern_height': 14.3, ################################### - ## COLUMN OFFSETS + # COLUMN OFFSETS #################################### 'column_offsets': [ @@ -456,16 +456,17 @@ [0, 0, 0], [0, 2.82, -4.5], [0, 0, 0], - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# REDUCED STAGGER - [0, -6, 5],# NOT USED IN MOST FORMATS (7th column) + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # REDUCED STAGGER + [0, -6, 5], # NOT USED IN MOST FORMATS (7th column) ], } - #################################### - ## END CONFIGURATION SECTION - #################################### +#################################### +# END CONFIGURATION SECTION +#################################### + def save_config(): # Check to see if the user has specified an alternate config @@ -498,6 +499,6 @@ def save_config(): if __name__ == '__main__': save_config() - ## HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT + # HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT from dactyl_manuform import * - run() \ No newline at end of file + run() diff --git a/src/helpers_blender.py b/src/helpers_blender.py index 00da8e56c..9b86d6d60 100644 --- a/src/helpers_blender.py +++ b/src/helpers_blender.py @@ -10,10 +10,12 @@ debug_trace = False + def debugprint(info): if debug_trace: print(info) + def box(width, height, depth): return bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, 0), scale=(width, height, depth)) @@ -24,7 +26,6 @@ def cylinder(radius, height, segments=100): ) - def sphere(radius): return sl.sphere(radius) @@ -39,11 +40,14 @@ def rotate(shape, angle): bpy.ops.transform.rotate(value=-radians(angle[2]), orient_axis='Z', center_override=(0.0, 0.0, 0.0)) return + def translate(shape, vector): - bpy.ops.transform.translate(value=vector, orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False) + bpy.ops.transform.translate(value=vector, orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=True, + use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False) return + def mirror(shape, plane=None): debugprint('mirror()') planes = { @@ -145,4 +149,4 @@ def export_file(shape, fname): def export_dxf(shape, fname): print("NO DXF EXPORT FOR SOLID".format(fname)) - pass \ No newline at end of file + pass diff --git a/src/helpers_cadquery.py b/src/helpers_cadquery.py index 58a876ab0..1af247875 100644 --- a/src/helpers_cadquery.py +++ b/src/helpers_cadquery.py @@ -5,6 +5,7 @@ debug_trace = False + def debugprint(info): if debug_trace: print(info) @@ -88,6 +89,7 @@ def intersect(shape1, shape2): else: return shape1 + def face_from_points(points): # debugprint('face_from_points()') edges = [] @@ -166,9 +168,6 @@ def triangle_hulls(shapes): return union(hulls) - - - def bottom_hull(p, height=0.001): debugprint("bottom_hull()") shape = None @@ -236,4 +235,4 @@ def export_file(shape, fname): def export_dxf(shape, fname): print("EXPORTING TO {}".format(fname)) cq.exporters.export(w=shape, fname=fname + ".dxf", - exportType='DXF') \ No newline at end of file + exportType='DXF') diff --git a/src/helpers_solid.py b/src/helpers_solid.py index fcd9e7367..d9c5e9be5 100644 --- a/src/helpers_solid.py +++ b/src/helpers_solid.py @@ -2,10 +2,12 @@ debug_trace = False + def debugprint(info): if debug_trace: print(info) + def box(width, height, depth): return sl.cube([width, height, depth], center=True) @@ -85,6 +87,7 @@ def intersect(shape1, shape2): else: return shape1 + def hull_from_points(points): return sl.hull()(*points) @@ -111,7 +114,6 @@ def triangle_hulls(shapes): return union(hulls) - def bottom_hull(p, height=0.001): debugprint("bottom_hull()") shape = None @@ -126,6 +128,7 @@ def bottom_hull(p, height=0.001): shape = sl.hull()(p, shape, t_shape) return shape + def polyline(point_list): return sl.polygon(point_list) @@ -154,4 +157,4 @@ def export_file(shape, fname): def export_dxf(shape, fname): print("NO DXF EXPORT FOR SOLID".format(fname)) - pass \ No newline at end of file + pass diff --git a/src/model_builder.py b/src/model_builder.py index 7cca38790..f009489f3 100644 --- a/src/model_builder.py +++ b/src/model_builder.py @@ -8,7 +8,7 @@ config_options = [ { - 'name': '{}', 'vars': ['ball_side'], # set ball side to both, other half can come from other renders + 'name': '{}', 'vars': ['ball_side'], # set ball side to both, other half can come from other renders 'vals': ['both'], 'val_names': [''] }, @@ -56,13 +56,12 @@ def create_config(config_options): temp_opt = copy.deepcopy(opt) new_config = copy.deepcopy(config) if len(temp_opt['vars']) == 1: - vals=[vals] + vals = [vals] if 'val_names' in temp_opt: temp_opt['val_names'][i_vals] = [temp_opt['val_names'][i_vals]] for i_val, val in enumerate(vals): new_config[opt['vars'][i_val]] = val - if 'val_names' in temp_opt: n_input = temp_opt['val_names'][i_vals] else: @@ -78,19 +77,18 @@ def create_config(config_options): return configurations - def build_release(base, configurations, engines=('solid', 'cadquery')): init = True for config in configurations: shape_config = copy.deepcopy(base) for item in config: shape_config[item] = config[item] - + for engine in engines: shape_config['ENGINE'] = engine with open('run_config.json', mode='w') as fid: json.dump(shape_config, fid, indent=4) - + if init: import dactyl_manuform as dactyl_manuform dactyl_manuform.run() @@ -99,6 +97,7 @@ def build_release(base, configurations, engines=('solid', 'cadquery')): importlib.reload(dactyl_manuform) dactyl_manuform.run() + if __name__ == '__main__': configurations = create_config(config_options) From c8ad9d67a5c3b45420a75deddb4c055df2a45f45 Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 24 Oct 2022 19:41:49 +0000 Subject: [PATCH 03/11] Set up packages/data directories. --- src/dactyl_keyboard/__init__.py | 0 src/{ => dactyl_keyboard}/dactyl_manuform.py | 0 src/{ => dactyl_keyboard}/generate_configuration.py | 0 .../generate_configuration_mklasklasd.py | 0 .../generate_configuration_orbyl_test.py | 0 .../generate_configuration_test.py | 0 src/{ => dactyl_keyboard}/helpers_blender.py | 0 src/{ => dactyl_keyboard}/helpers_cadquery.py | 0 src/{ => dactyl_keyboard}/helpers_solid.py | 0 src/{ => dactyl_keyboard}/model_builder.py | 0 src/{ => dactyl_keyboard}/parts/hot_swap_plate.step | 0 src/{ => dactyl_keyboard}/parts/hot_swap_plate.stl | Bin src/{ => dactyl_keyboard}/parts/sensor_holder.step | 0 src/{ => dactyl_keyboard}/parts/sensor_holder.stl | Bin .../parts/trackball_fused_34mm.step | 0 .../parts/trackball_fused_34mm.stl | Bin .../parts/trackball_mount.step | 0 .../parts/trackball_sensor_cutter.step | 0 .../parts/trackball_sensor_cutter.stl | Bin .../parts/trackball_sensor_mount.step | 0 .../parts/trackball_sensor_mount.stl | Bin .../parts/trackball_socket_body_34mm.step | 0 .../parts/trackball_socket_body_34mm.stl | Bin .../parts/trackball_socket_cutter_34mm.step | 0 .../parts/trackball_socket_cutter_34mm.stl | Bin 25 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/dactyl_keyboard/__init__.py rename src/{ => dactyl_keyboard}/dactyl_manuform.py (100%) rename src/{ => dactyl_keyboard}/generate_configuration.py (100%) rename src/{ => dactyl_keyboard}/generate_configuration_mklasklasd.py (100%) rename src/{ => dactyl_keyboard}/generate_configuration_orbyl_test.py (100%) rename src/{ => dactyl_keyboard}/generate_configuration_test.py (100%) rename src/{ => dactyl_keyboard}/helpers_blender.py (100%) rename src/{ => dactyl_keyboard}/helpers_cadquery.py (100%) rename src/{ => dactyl_keyboard}/helpers_solid.py (100%) rename src/{ => dactyl_keyboard}/model_builder.py (100%) rename src/{ => dactyl_keyboard}/parts/hot_swap_plate.step (100%) rename src/{ => dactyl_keyboard}/parts/hot_swap_plate.stl (100%) rename src/{ => dactyl_keyboard}/parts/sensor_holder.step (100%) rename src/{ => dactyl_keyboard}/parts/sensor_holder.stl (100%) rename src/{ => dactyl_keyboard}/parts/trackball_fused_34mm.step (100%) rename src/{ => dactyl_keyboard}/parts/trackball_fused_34mm.stl (100%) rename src/{ => dactyl_keyboard}/parts/trackball_mount.step (100%) rename src/{ => dactyl_keyboard}/parts/trackball_sensor_cutter.step (100%) rename src/{ => dactyl_keyboard}/parts/trackball_sensor_cutter.stl (100%) rename src/{ => dactyl_keyboard}/parts/trackball_sensor_mount.step (100%) rename src/{ => dactyl_keyboard}/parts/trackball_sensor_mount.stl (100%) rename src/{ => dactyl_keyboard}/parts/trackball_socket_body_34mm.step (100%) rename src/{ => dactyl_keyboard}/parts/trackball_socket_body_34mm.stl (100%) rename src/{ => dactyl_keyboard}/parts/trackball_socket_cutter_34mm.step (100%) rename src/{ => dactyl_keyboard}/parts/trackball_socket_cutter_34mm.stl (100%) diff --git a/src/dactyl_keyboard/__init__.py b/src/dactyl_keyboard/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/dactyl_manuform.py b/src/dactyl_keyboard/dactyl_manuform.py similarity index 100% rename from src/dactyl_manuform.py rename to src/dactyl_keyboard/dactyl_manuform.py diff --git a/src/generate_configuration.py b/src/dactyl_keyboard/generate_configuration.py similarity index 100% rename from src/generate_configuration.py rename to src/dactyl_keyboard/generate_configuration.py diff --git a/src/generate_configuration_mklasklasd.py b/src/dactyl_keyboard/generate_configuration_mklasklasd.py similarity index 100% rename from src/generate_configuration_mklasklasd.py rename to src/dactyl_keyboard/generate_configuration_mklasklasd.py diff --git a/src/generate_configuration_orbyl_test.py b/src/dactyl_keyboard/generate_configuration_orbyl_test.py similarity index 100% rename from src/generate_configuration_orbyl_test.py rename to src/dactyl_keyboard/generate_configuration_orbyl_test.py diff --git a/src/generate_configuration_test.py b/src/dactyl_keyboard/generate_configuration_test.py similarity index 100% rename from src/generate_configuration_test.py rename to src/dactyl_keyboard/generate_configuration_test.py diff --git a/src/helpers_blender.py b/src/dactyl_keyboard/helpers_blender.py similarity index 100% rename from src/helpers_blender.py rename to src/dactyl_keyboard/helpers_blender.py diff --git a/src/helpers_cadquery.py b/src/dactyl_keyboard/helpers_cadquery.py similarity index 100% rename from src/helpers_cadquery.py rename to src/dactyl_keyboard/helpers_cadquery.py diff --git a/src/helpers_solid.py b/src/dactyl_keyboard/helpers_solid.py similarity index 100% rename from src/helpers_solid.py rename to src/dactyl_keyboard/helpers_solid.py diff --git a/src/model_builder.py b/src/dactyl_keyboard/model_builder.py similarity index 100% rename from src/model_builder.py rename to src/dactyl_keyboard/model_builder.py diff --git a/src/parts/hot_swap_plate.step b/src/dactyl_keyboard/parts/hot_swap_plate.step similarity index 100% rename from src/parts/hot_swap_plate.step rename to src/dactyl_keyboard/parts/hot_swap_plate.step diff --git a/src/parts/hot_swap_plate.stl b/src/dactyl_keyboard/parts/hot_swap_plate.stl similarity index 100% rename from src/parts/hot_swap_plate.stl rename to src/dactyl_keyboard/parts/hot_swap_plate.stl diff --git a/src/parts/sensor_holder.step b/src/dactyl_keyboard/parts/sensor_holder.step similarity index 100% rename from src/parts/sensor_holder.step rename to src/dactyl_keyboard/parts/sensor_holder.step diff --git a/src/parts/sensor_holder.stl b/src/dactyl_keyboard/parts/sensor_holder.stl similarity index 100% rename from src/parts/sensor_holder.stl rename to src/dactyl_keyboard/parts/sensor_holder.stl diff --git a/src/parts/trackball_fused_34mm.step b/src/dactyl_keyboard/parts/trackball_fused_34mm.step similarity index 100% rename from src/parts/trackball_fused_34mm.step rename to src/dactyl_keyboard/parts/trackball_fused_34mm.step diff --git a/src/parts/trackball_fused_34mm.stl b/src/dactyl_keyboard/parts/trackball_fused_34mm.stl similarity index 100% rename from src/parts/trackball_fused_34mm.stl rename to src/dactyl_keyboard/parts/trackball_fused_34mm.stl diff --git a/src/parts/trackball_mount.step b/src/dactyl_keyboard/parts/trackball_mount.step similarity index 100% rename from src/parts/trackball_mount.step rename to src/dactyl_keyboard/parts/trackball_mount.step diff --git a/src/parts/trackball_sensor_cutter.step b/src/dactyl_keyboard/parts/trackball_sensor_cutter.step similarity index 100% rename from src/parts/trackball_sensor_cutter.step rename to src/dactyl_keyboard/parts/trackball_sensor_cutter.step diff --git a/src/parts/trackball_sensor_cutter.stl b/src/dactyl_keyboard/parts/trackball_sensor_cutter.stl similarity index 100% rename from src/parts/trackball_sensor_cutter.stl rename to src/dactyl_keyboard/parts/trackball_sensor_cutter.stl diff --git a/src/parts/trackball_sensor_mount.step b/src/dactyl_keyboard/parts/trackball_sensor_mount.step similarity index 100% rename from src/parts/trackball_sensor_mount.step rename to src/dactyl_keyboard/parts/trackball_sensor_mount.step diff --git a/src/parts/trackball_sensor_mount.stl b/src/dactyl_keyboard/parts/trackball_sensor_mount.stl similarity index 100% rename from src/parts/trackball_sensor_mount.stl rename to src/dactyl_keyboard/parts/trackball_sensor_mount.stl diff --git a/src/parts/trackball_socket_body_34mm.step b/src/dactyl_keyboard/parts/trackball_socket_body_34mm.step similarity index 100% rename from src/parts/trackball_socket_body_34mm.step rename to src/dactyl_keyboard/parts/trackball_socket_body_34mm.step diff --git a/src/parts/trackball_socket_body_34mm.stl b/src/dactyl_keyboard/parts/trackball_socket_body_34mm.stl similarity index 100% rename from src/parts/trackball_socket_body_34mm.stl rename to src/dactyl_keyboard/parts/trackball_socket_body_34mm.stl diff --git a/src/parts/trackball_socket_cutter_34mm.step b/src/dactyl_keyboard/parts/trackball_socket_cutter_34mm.step similarity index 100% rename from src/parts/trackball_socket_cutter_34mm.step rename to src/dactyl_keyboard/parts/trackball_socket_cutter_34mm.step diff --git a/src/parts/trackball_socket_cutter_34mm.stl b/src/dactyl_keyboard/parts/trackball_socket_cutter_34mm.stl similarity index 100% rename from src/parts/trackball_socket_cutter_34mm.stl rename to src/dactyl_keyboard/parts/trackball_socket_cutter_34mm.stl From f741a8621a001345cd061f2c80ea8823de7522bb Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 24 Oct 2022 20:35:52 +0000 Subject: [PATCH 04/11] Add package directory --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e4fbe816b..f0c5d649d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,10 @@ dynamic = ["version"] cadquery = ["cadquery==2.2.0b2", "cadquery-ocp==7.6.3a0"] solid = ["solidpython"] - [project.urls] "Homepage" = "https://github.com/joshreve/dactyl-keyboard" "Bug Tracker" = "https://github.com/joshreve/dactyl-keyboard/issues" + +[tool.setuptools] +package-dir = { "" = "src" } +packages = ["dactyl_keyboard"] From ace9c84533b688effdeb160641b94599a8f81cec Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 24 Oct 2022 20:36:01 +0000 Subject: [PATCH 05/11] Add missing dependency. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f0c5d649d..3a74ab99c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ dependencies = [ dynamic = ["version"] [project.optional-dependencies] -cadquery = ["cadquery==2.2.0b2", "cadquery-ocp==7.6.3a0"] +cadquery = ["cadquery==2.2.0b2", "cadquery-ocp==7.6.3a0", "scipy"] solid = ["solidpython"] [project.urls] From ae390715ab4ad3118f2839afe5b4fb72eae41187 Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Tue, 25 Oct 2022 05:12:32 +0000 Subject: [PATCH 06/11] Switch to using in-package resources. Load config directly from config generator, instead of generated file. --- configs/.gitkeep | 0 configs/default.json | 384 ---------------- pyproject.toml | 4 + src/dactyl_keyboard/dactyl_manuform.py | 54 +-- src/dactyl_keyboard/helpers_cadquery.py | 13 +- src/dactyl_keyboard/helpers_solid.py | 11 +- src/run_config.json | 574 ------------------------ things/.gitkeep | 0 8 files changed, 46 insertions(+), 994 deletions(-) delete mode 100644 configs/.gitkeep delete mode 100644 configs/default.json delete mode 100644 src/run_config.json delete mode 100644 things/.gitkeep diff --git a/configs/.gitkeep b/configs/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/configs/default.json b/configs/default.json deleted file mode 100644 index 599202731..000000000 --- a/configs/default.json +++ /dev/null @@ -1,384 +0,0 @@ -{ - "ENGINE": "solid", - "save_dir": "default", - "config_name": "default", - "show_caps": true, - "show_pcbs": false, - "nrows": 5, - "ncols": 6, - "alpha": 0.26179916666666664, - "beta": 0.08726638888888888, - "centercol": 3, - "centerrow_offset": 3, - "tenting_angle": 0.26179916666666664, - "symmetry": "symmetric", - "column_style_gt5": "orthographic", - "column_style": "standard", - "thumb_offsets": [ - 6, - -3, - 7 - ], - "keyboard_z_offset": 11, - "thumb_style": "DEFAULT", - "default_1U_cluster": true, - "minidox_Usize": 1.6, - "thumb_plate_tr_rotation": 0.0, - "thumb_plate_tl_rotation": 0.0, - "thumb_plate_mr_rotation": 0.0, - "thumb_plate_ml_rotation": 0.0, - "thumb_plate_br_rotation": 0.0, - "thumb_plate_bl_rotation": 0.0, - "trackball_in_wall": false, - "tbiw_ball_center_row": 0.2, - "tbiw_translational_offset": [ - 0.0, - 0.0, - 0.0 - ], - "tbiw_rotation_offset": [ - 0.0, - 0.0, - 0.0 - ], - "tbiw_left_wall_x_offset_override": 50.0, - "tbiw_left_wall_z_offset_override": 0.0, - "tbiw_left_wall_lower_y_offset": 0.0, - "tbiw_left_wall_lower_z_offset": 0.0, - "tbiw_oled_center_row": 0.75, - "tbiw_oled_translation_offset": [ - -3.5, - 0, - 1.5 - ], - "tbiw_oled_rotation_offset": [ - 0, - 0, - 0 - ], - "other_thumb": "DEFAULT", - "tbjs_key_diameter": 70, - "tbjs_translation_offset": [ - 0, - 0, - 10 - ], - "tbjs_rotation_offset": [ - 0, - 0, - 0 - ], - "tbjs_key_translation_offsets": [ - [ - 0.0, - 0.0, - -8.0 - ], - [ - 0.0, - 0.0, - -8.0 - ], - [ - 0.0, - 0.0, - -8.0 - ], - [ - 0.0, - 0.0, - -8.0 - ] - ], - "tbjs_key_rotation_offsets": [ - [ - 0.0, - 0.0, - 0.0 - ], - [ - 0.0, - 0.0, - 0.0 - ], - [ - 0.0, - 0.0, - 0.0 - ], - [ - 0.0, - 0.0, - 0.0 - ] - ], - "tbcj_inner_diameter": 42, - "tbcj_thickness": 2, - "tbcj_outer_diameter": 53, - "trackball_modular": false, - "trackball_Usize": 1.5, - "ball_side": "right", - "ball_diameter": 34.0, - "ball_wall_thickness": 3, - "ball_gap": 1.0, - "trackball_hole_diameter": 36.5, - "trackball_hole_height": 40, - "trackball_plate_thickness": 2, - "trackball_plate_width": 2, - "tb_socket_translation_offset": [ - 0, - 0, - 2.0 - ], - "tb_socket_rotation_offset": [ - 0, - 0, - 0 - ], - "tb_sensor_translation_offset": [ - 0, - 0, - 0 - ], - "tb_sensor_rotation_offset": [ - 0, - 0, - 0 - ], - "pinky_1_5U": false, - "first_1_5U_row": 0, - "last_1_5U_row": 5, - "extra_width": 2.5, - "extra_height": 1.0, - "wall_z_offset": 15, - "wall_x_offset": 5, - "wall_y_offset": 6, - "left_wall_x_offset": 12, - "left_wall_z_offset": 3, - "left_wall_lower_y_offset": 0, - "left_wall_lower_z_offset": 0, - "wall_thickness": 4.5, - "wall_base_y_thickness": 4.5, - "wall_base_x_thickness": 4.5, - "wall_base_back_thickness": 4.5, - "fixed_angles": [ - 0.17453277777777776, - 0.17453277777777776, - 0, - 0, - 0, - -0.26179916666666664, - -0.26179916666666664 - ], - "fixed_x": [ - -41.5, - -22.5, - 0, - 20.3, - 41.4, - 65.5, - 89.6 - ], - "fixed_z": [ - 12.1, - 8.3, - 0, - 5, - 10.7, - 14.5, - 17.5 - ], - "fixed_tenting": 0.0, - "plate_style": "NOTCH", - "hole_keyswitch_height": 14.0, - "hole_keyswitch_width": 14.0, - "nub_keyswitch_height": 14.4, - "nub_keyswitch_width": 14.4, - "undercut_keyswitch_height": 14.0, - "undercut_keyswitch_width": 14.0, - "notch_width": 5.0, - "sa_profile_key_height": 12.7, - "sa_length": 18.5, - "sa_double_length": 37.5, - "plate_thickness": 5.1, - "plate_rim": 2.0, - "clip_thickness": 1.4, - "clip_undercut": 1.0, - "undercut_transition": 0.2, - "plate_file": null, - "plate_offset": 0.0, - "oled_mount_type": "CLIP", - "oled_center_row": 1.25, - "oled_translation_offset": [ - 0, - 0, - 4 - ], - "oled_rotation_offset": [ - 0, - 0, - 0 - ], - "oled_configurations": { - "UNDERCUT": { - "oled_mount_width": 15.0, - "oled_mount_height": 35.0, - "oled_mount_rim": 3.0, - "oled_mount_depth": 6.0, - "oled_mount_cut_depth": 20.0, - "oled_mount_location_xyz": [ - -80.0, - 20.0, - 45.0 - ], - "oled_mount_rotation_xyz": [ - 13.0, - 0.0, - -6.0 - ], - "oled_left_wall_x_offset_override": 28.0, - "oled_left_wall_z_offset_override": 0.0, - "oled_left_wall_lower_y_offset": 12.0, - "oled_left_wall_lower_z_offset": 5.0, - "oled_mount_undercut": 1.0, - "oled_mount_undercut_thickness": 2.0 - }, - "SLIDING": { - "oled_mount_width": 12.5, - "oled_mount_height": 25.0, - "oled_mount_rim": 2.5, - "oled_mount_depth": 8.0, - "oled_mount_cut_depth": 20.0, - "oled_mount_location_xyz": [ - -78.0, - 10.0, - 41.0 - ], - "oled_mount_rotation_xyz": [ - 6.0, - 0.0, - -3.0 - ], - "oled_left_wall_x_offset_override": 24.0, - "oled_left_wall_z_offset_override": 0.0, - "oled_left_wall_lower_y_offset": 12.0, - "oled_left_wall_lower_z_offset": 5.0, - "oled_thickness": 4.2, - "oled_edge_overlap_end": 6.5, - "oled_edge_overlap_connector": 5.5, - "oled_edge_overlap_thickness": 2.5, - "oled_edge_overlap_clearance": 2.5, - "oled_edge_chamfer": 2.0 - }, - "CLIP": { - "oled_mount_width": 12.5, - "oled_mount_height": 39.0, - "oled_mount_rim": 2.0, - "oled_mount_depth": 7.0, - "oled_mount_cut_depth": 20.0, - "oled_mount_location_xyz": [ - -78.0, - 20.0, - 42.0 - ], - "oled_mount_rotation_xyz": [ - 12.0, - 0.0, - -6.0 - ], - "oled_left_wall_x_offset_override": 24.0, - "oled_left_wall_z_offset_override": 0.0, - "oled_left_wall_lower_y_offset": 12.0, - "oled_left_wall_lower_z_offset": 5.0, - "oled_thickness": 4.2, - "oled_mount_bezel_thickness": 3.5, - "oled_mount_bezel_chamfer": 2.0, - "oled_mount_connector_hole": 6.0, - "oled_screen_start_from_conn_end": 6.5, - "oled_screen_length": 24.5, - "oled_screen_width": 10.5, - "oled_clip_thickness": 1.5, - "oled_clip_width": 6.0, - "oled_clip_overhang": 1.0, - "oled_clip_extension": 5.0, - "oled_clip_width_clearance": 0.5, - "oled_clip_undercut": 0.5, - "oled_clip_undercut_thickness": 2.5, - "oled_clip_y_gap": 0.2, - "oled_clip_z_gap": 0.2 - } - }, - "web_thickness": 4.0, - "post_size": 0.1, - "post_adj": 0, - "screws_offset": "INSIDE", - "screw_insert_height": 3.8, - "screw_insert_bottom_radius": 2.655, - "screw_insert_top_radius": 2.55, - "wire_post_height": 7, - "wire_post_overhang": 3.5, - "wire_post_diameter": 2.6, - "controller_mount_type": "EXTERNAL", - "external_holder_height": 12.5, - "external_holder_width": 28.75, - "external_holder_xoffset": -5.0, - "external_holder_yoffset": -4.5, - "screw_hole_diameter": 2, - "base_thickness": 3.0, - "base_offset": 3.0, - "base_rim_thickness": 5.0, - "screw_cbore_diameter": 4.0, - "screw_cbore_depth": 2.0, - "plate_holes": false, - "plate_holes_xy_offset": [ - 0.0, - 0.0 - ], - "plate_holes_width": 14.3, - "plate_holes_height": 14.3, - "plate_holes_diameter": 1.7, - "plate_holes_depth": 20.0, - "pcb_width": 18.0, - "pcb_height": 18.0, - "pcb_thickness": 1.5, - "pcb_hole_diameter": 2, - "pcb_hole_pattern_width": 14.3, - "pcb_hole_pattern_height": 14.3, - "column_offsets": [ - [ - 0, - 0, - 0 - ], - [ - 0, - 0, - 0 - ], - [ - 0, - 2.82, - -4.5 - ], - [ - 0, - 0, - 0 - ], - [ - 0, - -6, - 5 - ], - [ - 0, - -6, - 5 - ], - [ - 0, - -6, - 5 - ] - ] -} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 3a74ab99c..d4810ab71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ ] dependencies = [ "numpy", + "importlib-resources; python_version<'3.9'", ] dynamic = ["version"] @@ -34,6 +35,9 @@ solid = ["solidpython"] "Homepage" = "https://github.com/joshreve/dactyl-keyboard" "Bug Tracker" = "https://github.com/joshreve/dactyl-keyboard/issues" +[project.scripts] +"dactyl-keyboard" = "dactyl_keyboard.dactyl_manuform:run" + [tool.setuptools] package-dir = { "" = "src" } packages = ["dactyl_keyboard"] diff --git a/src/dactyl_keyboard/dactyl_manuform.py b/src/dactyl_keyboard/dactyl_manuform.py index e8d915ad0..2320a1349 100644 --- a/src/dactyl_keyboard/dactyl_manuform.py +++ b/src/dactyl_keyboard/dactyl_manuform.py @@ -1,5 +1,4 @@ import math -import generate_configuration as cfg import numpy as np from numpy import pi import os.path as path @@ -9,7 +8,12 @@ import os import copy -from scipy.spatial import ConvexHull as sphull +if sys.version_info[:2] > (3, 9): + import importlib.resources as resources +else: + import importlib_resources as resources + +from . generate_configuration import shape_config def deg2rad(degrees: float) -> float: @@ -25,24 +29,19 @@ def rad2deg(rad: float) -> float: ############################################### # IMPORT DEFAULT CONFIG IN CASE NEW PARAMETERS EXIST -for item in cfg.shape_config: - locals()[item] = cfg.shape_config[item] +for key, item in shape_config.items(): + locals()[key] = item if len(sys.argv) <= 1: - print("NO CONFIGURATION SPECIFIED, USING run_config.json") - with open(os.path.join(r".", 'run_config.json'), mode='r') as fid: - data = json.load(fid) - + print("NO CONFIGURATION SPECIFIED, USING DEFAULT CONFIGURATION") else: # CHECK FOR CONFIG FILE AND WRITE TO ANY VARIABLES IN FILE. opts, args = getopt.getopt(sys.argv[1:], "", ["config="]) for opt, arg in opts: if opt in ('--config'): - with open(os.path.join(r"..", "configs", arg + '.json'), mode='r') as fid: - data = json.load(fid) - -for item in data: - locals()[item] = data[item] + with open(arg, mode="rt", encoding="utf-8") as fid: + for key, item in json.load(fid).items(): + locals()[key] = item # Really rough setup. Check for ENGINE, set it not present from configuration. @@ -55,11 +54,11 @@ def rad2deg(rad: float) -> float: print('Setting Current Engine = {}'.format(ENGINE)) if save_dir in ['', None, '.']: - save_path = path.join(r"..", "things") - parts_path = path.join(r"..", "src", "parts") + save_path = path.join(r".", "things") else: - save_path = path.join(r"..", "things", save_dir) - parts_path = path.join(r"..", r"..", "src", "parts") + save_path = path.join(r".", "things", save_dir) + +parts_path = resources.files("dactyl_keyboard.parts") ############################################### # END EXTREMELY UGLY BOOTSTRAP @@ -70,9 +69,9 @@ def rad2deg(rad: float) -> float: #################################################### if ENGINE == 'cadquery': - from helpers_cadquery import * + from . helpers_cadquery import * else: - from helpers_solid import * + from . helpers_solid import * #################################################### # END HELPER FUNCTIONS @@ -118,7 +117,7 @@ def debugprint(info): if 'HS_' in plate_style: symmetry = "asymmetric" - plate_file = path.join(parts_path, r"hot_swap_plate") + plate_file = "hot_swap_plate" plate_offset = 0.0 if (trackball_in_wall or ('TRACKBALL' in thumb_style)) and not ball_side == 'both': @@ -241,7 +240,7 @@ def single_plate(cylinder_segments=100, side="right"): plate = difference(plate, [undercut]) if plate_file is not None: - socket = import_file(plate_file) + socket = import_file(parts_path, plate_file) socket = translate(socket, [0, 0, plate_thickness + plate_offset]) plate = union([plate, socket]) @@ -311,15 +310,10 @@ def trackball_socket(segments=100, side="right"): sensor = None else: - tb_file = path.join(parts_path, r"trackball_socket_body_34mm") - tbcut_file = path.join(parts_path, r"trackball_socket_cutter_34mm") - sens_file = path.join(parts_path, r"trackball_sensor_mount") - senscut_file = path.join(parts_path, r"trackball_sensor_cutter") - - shape = import_file(tb_file) - sensor = import_file(sens_file) - cutter = import_file(tbcut_file) - cutter = union([cutter, import_file(senscut_file)]) + shape = import_file(parts_path, "trackball_socket_body_34mm") + sensor = import_file(parts_path, "trackball_sensor_mount") + cutter = import_file(parts_path, "trackball_socket_cutter_34mm") + cutter = union([cutter, import_file(parts_path, "trackball_sensor_cutter")]) # return shape, cutter return shape, cutter, sensor diff --git a/src/dactyl_keyboard/helpers_cadquery.py b/src/dactyl_keyboard/helpers_cadquery.py index 1af247875..cc7a37ed8 100644 --- a/src/dactyl_keyboard/helpers_cadquery.py +++ b/src/dactyl_keyboard/helpers_cadquery.py @@ -1,3 +1,9 @@ +import sys +if sys.version_info[:2] > (3, 9): + import importlib.resources as resources +else: + import importlib_resources as resources + import cadquery as cq from scipy.spatial import ConvexHull as sphull import numpy as np @@ -219,11 +225,10 @@ def extrude_poly(outer_poly, inner_polys=None, height=1): # vector=(0,0,1)): cq.Solid.extrudeLinear(outerWire=outer_wires, innerWires=inner_wires, vecNormal=cq.Vector(0, 0, height))) -def import_file(fname, convexity=None): +def import_file(parts_path: resources.abc.Traversable, fname: str, convexity=None): print("IMPORTING FROM {}".format(fname)) - return cq.Workplane('XY').add(cq.importers.importShape( - cq.exporters.ExportTypes.STEP, - fname + ".step")) + with resources.as_file(parts_path.joinpath(fname + ".step")) as extracted: + return cq.Workplane('XY').add(cq.importers.importShape(cq.exporters.ExportTypes.STEP, extracted)) def export_file(shape, fname): diff --git a/src/dactyl_keyboard/helpers_solid.py b/src/dactyl_keyboard/helpers_solid.py index d9c5e9be5..5daaa87e6 100644 --- a/src/dactyl_keyboard/helpers_solid.py +++ b/src/dactyl_keyboard/helpers_solid.py @@ -1,3 +1,9 @@ +import sys +if sys.version_info[:2] > (3, 9): + import importlib.resources as resources +else: + import importlib_resources as resources + import solid as sl debug_trace = False @@ -145,9 +151,10 @@ def extrude_poly(outer_poly, inner_polys=None, height=1): return sl.linear_extrude(height=height, twist=0, convexity=0, center=True)(outer_poly) -def import_file(fname, convexity=2): +def import_file(parts_path: resources.abc.Traversable, fname: str, convexity=2): print("IMPORTING FROM {}".format(fname)) - return sl.import_stl(fname.replace("\\", "/") + ".stl", convexity=convexity) + with resources.as_file(parts_path.joinpath(fname + ".stl")) as extracted: + return sl.import_stl(extracted, convexity=convexity) def export_file(shape, fname): diff --git a/src/run_config.json b/src/run_config.json deleted file mode 100644 index 8337c8e9f..000000000 --- a/src/run_config.json +++ /dev/null @@ -1,574 +0,0 @@ -{ - "ENGINE": "solid", - "save_dir": ".", - "config_name": "DM", - "show_caps": "MX", - "show_pcbs": false, - "nrows": 5, - "ncols": 6, - "alpha": 0.26179916666666664, - "beta": 0.08726638888888888, - "centercol": 3, - "centerrow_offset": 3, - "tenting_angle": 0.26179916666666664, - "symmetry": "symmetric", - "column_style_gt5": "orthographic", - "column_style": "standard", - "reduced_inner_cols": 2, - "reduced_outer_cols": 0, - "thumb_offsets": [ - 6, - -3, - 7 - ], - "keyboard_z_offset": 11, - "extra_width": 2.5, - "extra_height": 1.0, - "web_thickness": 5.1, - "post_size": 0.1, - "post_adj": 0, - "thumb_style": "DEFAULT", - "default_1U_cluster": true, - "minidox_Usize": 1.6, - "mini_index_key": true, - "default_thumb_screw_xy_locations": [ - [ - -21, - -58 - ] - ], - "default_separable_thumb_screw_xy_locations": [ - [ - -21, - -58 - ] - ], - "mini_thumb_screw_xy_locations": [ - [ - -29, - -52 - ] - ], - "mini_separable_thumb_screw_xy_locations": [ - [ - -29, - -52 - ], - [ - -62, - 10 - ], - [ - 12, - -25 - ] - ], - "minidox_thumb_screw_xy_locations": [ - [ - -37, - -34 - ] - ], - "minidox_separable_thumb_screw_xy_locations": [ - [ - -37, - -34 - ], - [ - -62, - 12 - ], - [ - 10, - -25 - ] - ], - "carbonfet_thumb_screw_xy_locations": [ - [ - -48, - -37 - ] - ], - "carbonfet_separable_thumb_screw_xy_locations": [ - [ - -48, - -37 - ], - [ - -52, - 10 - ], - [ - 12, - -35 - ] - ], - "orbyl_thumb_screw_xy_locations": [ - [ - -53, - -68 - ] - ], - "orbyl_separable_thumb_screw_xy_locations": [ - [ - -53, - -68 - ], - [ - -66, - 8 - ], - [ - 10, - -40 - ] - ], - "tbcj_thumb_screw_xy_locations": [ - [ - -40, - -75 - ] - ], - "tbcj_separable_thumb_screw_xy_locations": [ - [ - -40, - -75 - ], - [ - -63, - 10 - ], - [ - 15, - -40 - ] - ], - "thumb_plate_tr_rotation": 0.0, - "thumb_plate_tl_rotation": 0.0, - "thumb_plate_mr_rotation": 0.0, - "thumb_plate_ml_rotation": 0.0, - "thumb_plate_br_rotation": 0.0, - "thumb_plate_bl_rotation": 0.0, - "separable_thumb": false, - "trackball_in_wall": false, - "tbiw_ball_center_row": 0.2, - "tbiw_translational_offset": [ - 0.0, - 0.0, - 0.0 - ], - "tbiw_rotation_offset": [ - 0.0, - 0.0, - 0.0 - ], - "tbiw_left_wall_x_offset_override": 50.0, - "tbiw_left_wall_z_offset_override": 0.0, - "tbiw_left_wall_lower_x_offset": 0.0, - "tbiw_left_wall_lower_y_offset": 0.0, - "tbiw_left_wall_lower_z_offset": 0.0, - "tbiw_oled_center_row": 0.75, - "tbiw_oled_translation_offset": [ - -3.5, - 0, - 1.5 - ], - "tbiw_oled_rotation_offset": [ - 0, - 0, - 0 - ], - "finger_trackball_in_wall": false, - "tbiw_ball_center_column": 0.2, - "tbiw_top_wall_y_offset_override": 50.0, - "tbiw_top_wall_z_offset_override": 0.0, - "tbiw_top_wall_extension_cols": 4, - "other_thumb": "DEFAULT", - "tbjs_key_diameter": 70, - "tbjs_Uwidth": 1.2, - "tbjs_Uheight": 1.2, - "tbjs_translation_offset": [ - 0, - 0, - 2 - ], - "tbjs_rotation_offset": [ - 0, - -8, - 0 - ], - "tbjs_key_translation_offsets": [ - [ - 0.0, - 0.0, - -8.0 - ], - [ - 0.0, - 0.0, - -8.0 - ], - [ - 0.0, - 0.0, - -8.0 - ], - [ - 0.0, - 0.0, - -8.0 - ] - ], - "tbjs_key_rotation_offsets": [ - [ - 0.0, - 0.0, - 0.0 - ], - [ - 0.0, - 0.0, - 0.0 - ], - [ - 0.0, - 0.0, - 0.0 - ], - [ - 0.0, - 0.0, - 0.0 - ] - ], - "tbcj_inner_diameter": 42, - "tbcj_thickness": 2, - "tbcj_outer_diameter": 53, - "trackball_modular": false, - "trackball_modular_lip_width": 3.0, - "trackball_modular_ball_height": 3.0, - "trackball_modular_ring_height": 10.0, - "trackball_modular_clearance": 0.5, - "ball_side": "both", - "ball_diameter": 34.0, - "ball_wall_thickness": 3, - "ball_gap": 1.0, - "trackball_hole_diameter": 36.5, - "trackball_hole_height": 40, - "trackball_plate_thickness": 2, - "trackball_plate_width": 2, - "tb_socket_translation_offset": [ - 0, - 0, - 2.0 - ], - "tb_socket_rotation_offset": [ - 0, - 0, - 0 - ], - "tb_sensor_translation_offset": [ - 0, - 0, - 0 - ], - "tb_sensor_rotation_offset": [ - 0, - 0, - 0 - ], - "pinky_1_5U": false, - "first_1_5U_row": 0, - "last_1_5U_row": 5, - "skeletal": false, - "wall_z_offset": 15, - "wall_x_offset": 5, - "wall_y_offset": 6, - "left_wall_x_offset": 12, - "left_wall_z_offset": 3, - "left_wall_lower_x_offset": 0, - "left_wall_lower_y_offset": 0, - "left_wall_lower_z_offset": 0, - "wall_thickness": 4.5, - "wall_base_y_thickness": 4.5, - "wall_base_x_thickness": 4.5, - "wall_base_back_thickness": 4.5, - "fixed_angles": [ - 0.17453277777777776, - 0.17453277777777776, - 0, - 0, - 0, - -0.26179916666666664, - -0.26179916666666664 - ], - "fixed_x": [ - -41.5, - -22.5, - 0, - 20.3, - 41.4, - 65.5, - 89.6 - ], - "fixed_z": [ - 12.1, - 8.3, - 0, - 5, - 10.7, - 14.5, - 17.5 - ], - "fixed_tenting": 0.0, - "plate_style": "NOTCH", - "hole_keyswitch_height": 14.0, - "hole_keyswitch_width": 14.0, - "nub_keyswitch_height": 14.4, - "nub_keyswitch_width": 14.4, - "undercut_keyswitch_height": 14.0, - "undercut_keyswitch_width": 14.0, - "notch_width": 6.0, - "sa_profile_key_height": 12.7, - "sa_length": 18.5, - "sa_double_length": 37.5, - "plate_thickness": 5.1, - "plate_rim": 2.0, - "clip_thickness": 1.1, - "clip_undercut": 1.0, - "undercut_transition": 0.2, - "plate_file": null, - "plate_offset": 0.0, - "oled_mount_type": "CLIP", - "oled_center_row": 1.25, - "oled_translation_offset": [ - 0, - 0, - 4 - ], - "oled_rotation_offset": [ - 0, - 0, - 0 - ], - "oled_configurations": { - "UNDERCUT": { - "oled_mount_width": 15.0, - "oled_mount_height": 35.0, - "oled_mount_rim": 3.0, - "oled_mount_depth": 6.0, - "oled_mount_cut_depth": 20.0, - "oled_mount_location_xyz": [ - -80.0, - 20.0, - 45.0 - ], - "oled_mount_rotation_xyz": [ - 13.0, - 0.0, - -6.0 - ], - "oled_left_wall_x_offset_override": 28.0, - "oled_left_wall_z_offset_override": 0.0, - "oled_left_wall_lower_y_offset": 12.0, - "oled_left_wall_lower_z_offset": 5.0, - "oled_mount_undercut": 1.0, - "oled_mount_undercut_thickness": 2.0 - }, - "SLIDING": { - "oled_mount_width": 12.5, - "oled_mount_height": 25.0, - "oled_mount_rim": 2.5, - "oled_mount_depth": 8.0, - "oled_mount_cut_depth": 20.0, - "oled_mount_location_xyz": [ - -78.0, - 10.0, - 41.0 - ], - "oled_mount_rotation_xyz": [ - 6.0, - 0.0, - -3.0 - ], - "oled_left_wall_x_offset_override": 24.0, - "oled_left_wall_z_offset_override": 0.0, - "oled_left_wall_lower_y_offset": 12.0, - "oled_left_wall_lower_z_offset": 5.0, - "oled_thickness": 4.2, - "oled_edge_overlap_end": 6.5, - "oled_edge_overlap_connector": 5.5, - "oled_edge_overlap_thickness": 2.5, - "oled_edge_overlap_clearance": 2.5, - "oled_edge_chamfer": 2.0 - }, - "CLIP": { - "oled_mount_width": 12.5, - "oled_mount_height": 39.0, - "oled_mount_rim": 2.0, - "oled_mount_depth": 7.0, - "oled_mount_cut_depth": 20.0, - "oled_mount_location_xyz": [ - -78.0, - 20.0, - 42.0 - ], - "oled_mount_rotation_xyz": [ - 12.0, - 0.0, - -6.0 - ], - "oled_left_wall_x_offset_override": 24.0, - "oled_left_wall_z_offset_override": 0.0, - "oled_left_wall_lower_y_offset": 12.0, - "oled_left_wall_lower_z_offset": 5.0, - "oled_thickness": 4.2, - "oled_mount_bezel_thickness": 3.5, - "oled_mount_bezel_chamfer": 2.0, - "oled_mount_connector_hole": 6.0, - "oled_screen_start_from_conn_end": 6.5, - "oled_screen_length": 24.5, - "oled_screen_width": 10.5, - "oled_clip_thickness": 1.5, - "oled_clip_width": 6.0, - "oled_clip_overhang": 1.0, - "oled_clip_extension": 5.0, - "oled_clip_width_clearance": 0.5, - "oled_clip_undercut": 0.5, - "oled_clip_undercut_thickness": 2.5, - "oled_clip_y_gap": 0.2, - "oled_clip_z_gap": 0.2 - } - }, - "screws_offset": "INSIDE", - "screw_insert_height": 3.8, - "screw_insert_bottom_radius": 1.25, - "screw_insert_top_radius": 1.25, - "screw_insert_outer_radius": 4.25, - "wire_post_height": 7, - "wire_post_overhang": 3.5, - "wire_post_diameter": 2.6, - "controller_mount_type": "EXTERNAL", - "external_holder_height": 12.5, - "external_holder_width": 28.75, - "external_holder_xoffset": -5.0, - "external_holder_yoffset": -4.5, - "pcb_mount_ref_offset": [ - 0, - -5, - 0 - ], - "pcb_holder_size": [ - 34.6, - 7, - 4 - ], - "pcb_holder_offset": [ - 8.9, - 0, - 0 - ], - "pcb_usb_hole_size": [ - 7.5, - 10.0, - 4 - ], - "pcb_usb_hole_offset": [ - 15, - 0, - 4.5 - ], - "wall_thinner_size": [ - 34, - 7, - 10 - ], - "trrs_hole_size": [ - 3, - 20 - ], - "trrs_offset": [ - 0, - 0, - 1.5 - ], - "pcb_screw_hole_size": [ - 0.5, - 10 - ], - "pcb_screw_x_offsets": [ - -5.5, - 7.75, - 22 - ], - "pcb_screw_y_offset": -2, - "screw_hole_diameter": 3, - "base_thickness": 3.0, - "base_offset": 3.0, - "base_rim_thickness": 5.0, - "screw_cbore_diameter": 6.0, - "screw_cbore_depth": 2.5, - "plate_holes": true, - "plate_holes_xy_offset": [ - 0.0, - 0.0 - ], - "plate_holes_width": 14.3, - "plate_holes_height": 14.3, - "plate_holes_diameter": 1.6, - "plate_holes_depth": 20.0, - "plate_pcb_clear": false, - "plate_pcb_size": [ - 18.5, - 18.5, - 5 - ], - "plate_pcb_offset": [ - 0, - 0, - 0 - ], - "pcb_width": 18.0, - "pcb_height": 18.0, - "pcb_thickness": 1.5, - "pcb_hole_diameter": 2, - "pcb_hole_pattern_width": 14.3, - "pcb_hole_pattern_height": 14.3, - "column_offsets": [ - [ - 0, - 0, - 0 - ], - [ - 0, - 0, - 0 - ], - [ - 0, - 2.82, - -4.5 - ], - [ - 0, - 0, - 0 - ], - [ - 0, - -6, - 5 - ], - [ - 0, - -6, - 5 - ], - [ - 0, - -6, - 5 - ] - ] -} \ No newline at end of file diff --git a/things/.gitkeep b/things/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From 5cd26c70c9a9b5019159449865045aafe80d8015 Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Tue, 25 Oct 2022 05:51:18 +0000 Subject: [PATCH 07/11] Remove use of custom angle conversion. Remove use of numpy values/functions that have math equivalents. --- src/dactyl_keyboard/dactyl_manuform.py | 61 ++++++++----------- src/dactyl_keyboard/generate_configuration.py | 15 ++--- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/src/dactyl_keyboard/dactyl_manuform.py b/src/dactyl_keyboard/dactyl_manuform.py index 2320a1349..16d7b8fdb 100644 --- a/src/dactyl_keyboard/dactyl_manuform.py +++ b/src/dactyl_keyboard/dactyl_manuform.py @@ -1,6 +1,4 @@ import math -import numpy as np -from numpy import pi import os.path as path import getopt import sys @@ -13,15 +11,9 @@ else: import importlib_resources as resources -from . generate_configuration import shape_config - - -def deg2rad(degrees: float) -> float: - return degrees * pi / 180 - +import numpy as np -def rad2deg(rad: float) -> float: - return rad * 180 / pi +from . generate_configuration import shape_config ############################################### @@ -143,11 +135,11 @@ def debugprint(info): cap_top_height = plate_thickness + sa_profile_key_height -row_radius = ((mount_height + extra_height) / 2) / (np.sin(alpha / 2)) + cap_top_height +row_radius = ((mount_height + extra_height) / 2) / (math.sin(alpha / 2)) + cap_top_height column_radius = ( - ((mount_width + extra_width) / 2) / (np.sin(beta / 2)) + ((mount_width + extra_width) / 2) / (math.sin(beta / 2)) ) + cap_top_height -column_x_delta = -1 - column_radius * np.sin(beta) +column_x_delta = -1 - column_radius * math.sin(beta) column_base_angle = beta * (centercol - 2) @@ -441,8 +433,8 @@ def rotate_around_x(position, angle): t_matrix = np.array( [ [1, 0, 0], - [0, np.cos(angle), -np.sin(angle)], - [0, np.sin(angle), np.cos(angle)], + [0, math.cos(angle), -math.sin(angle)], + [0, math.sin(angle), math.cos(angle)], ] ) return np.matmul(t_matrix, position) @@ -452,9 +444,9 @@ def rotate_around_y(position, angle): # debugprint('rotate_around_y()') t_matrix = np.array( [ - [np.cos(angle), 0, np.sin(angle)], + [math.cos(angle), 0, math.sin(angle)], [0, 1, 0], - [-np.sin(angle), 0, np.cos(angle)], + [-math.sin(angle), 0, math.cos(angle)], ] ) return np.matmul(t_matrix, position) @@ -475,7 +467,7 @@ def apply_key_geometry( column_angle = beta * (centercol - column) if column_style == "orthographic": - column_z_delta = column_radius * (1 - np.cos(column_angle)) + column_z_delta = column_radius * (1 - math.cos(column_angle)) shape = translate_fn(shape, [0, 0, -row_radius]) shape = rotate_x_fn(shape, alpha * (centerrow - row)) shape = translate_fn(shape, [0, 0, row_radius]) @@ -511,12 +503,12 @@ def apply_key_geometry( def x_rot(shape, angle): # debugprint('x_rot()') - return rotate(shape, [rad2deg(angle), 0, 0]) + return rotate(shape, [math.degrees(angle), 0, 0]) def y_rot(shape, angle): # debugprint('y_rot()') - return rotate(shape, [0, rad2deg(angle), 0]) + return rotate(shape, [0, math.degrees(angle), 0]) def key_place(shape, column, row): @@ -1245,7 +1237,7 @@ def mini_thumb_15x_layout(shape): def mini_thumbcaps(): t1 = mini_thumb_1x_layout(keycap(1)) - t15 = mini_thumb_15x_layout(rotate(keycap(1), [0, 0, rad2deg(pi / 2)])) + t15 = mini_thumb_15x_layout(rotate(keycap(1), [0, 0, 90])) return t1.add(t15) @@ -1431,7 +1423,6 @@ def minidox_thumb_fx_layout(shape): def minidox_thumbcaps(): t1 = minidox_thumb_1x_layout(keycap(1)) - # t1.add(minidox_thumb_15x_layout(rotate(keycap(1), [0, 0, rad2deg(pi / 2)]))) return t1 @@ -1606,7 +1597,7 @@ def carbonfet_thumb_15x_layout(shape, plate=True): def carbonfet_thumbcaps(): t1 = carbonfet_thumb_1x_layout(keycap(1)) - t15 = carbonfet_thumb_15x_layout(rotate(keycap(1.5), [0, 0, rad2deg(pi / 2)])) + t15 = carbonfet_thumb_15x_layout(rotate(keycap(1.5), [0, 0, 90])) return t1.add(t15) @@ -1874,8 +1865,6 @@ def trackball_layout(shape): def tbjs_thumbcaps(): t1 = tbjs_thumb_1x_layout(keycap(1)) - # t1 = tbjs_thumb_fx_layout(keycap(1)) - # t1.add(tbjs_thumb_15x_layout(rotate(keycap(1), [0, 0, rad2deg(pi / 2)]))) return t1 @@ -3397,10 +3386,10 @@ def pcb_screw_hole(): oled_mount_location_xyz = (np.array(base_pt1)+np.array(base_pt2))/2. + np.array(((-left_wall_x_offset/2), 0, 0)) + np.array(oled_translation_offset) oled_mount_location_xyz[2] = (oled_mount_location_xyz[2] + base_pt0[2])/2 - angle_x = np.arctan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) - angle_z = np.arctan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) + angle_x = math.atan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) + angle_z = math.atan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) - oled_mount_rotation_xyz = (rad2deg(angle_x), 0, -rad2deg(angle_z)) + np.array(oled_rotation_offset) + oled_mount_rotation_xyz = (math.degrees(angle_x), 0, -math.degrees(angle_z)) + np.array(oled_rotation_offset) def generate_trackball(pos, rot): @@ -3476,9 +3465,9 @@ def tbiw_position_rotation(): # tbiw_mount_location_xyz[2] = (oled_translation_offset[2] + base_pt0[2])/2 - angle_x = np.arctan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) - angle_z = np.arctan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) - tbiw_mount_rotation_xyz = (rad2deg(angle_x), 0, rad2deg(angle_z)) + np.array(tbiw_rotation_offset) + angle_x = math.atan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) + angle_z = math.atan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) + tbiw_mount_rotation_xyz = (math.degrees(angle_x), 0, math.degrees(angle_z)) + np.array(tbiw_rotation_offset) return tbiw_mount_location_xyz, tbiw_mount_rotation_xyz @@ -3519,14 +3508,12 @@ def oled_position_rotation(side='right'): oled_mount_location_xyz = (np.array(base_pt1)+np.array(base_pt2))/2. + np.array(((-_left_wall_x_offset/2), 0, 0)) + np.array(_oled_translation_offset) oled_mount_location_xyz[2] = (oled_mount_location_xyz[2] + base_pt0[2])/2 - angle_x = np.arctan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) - angle_z = np.arctan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) + angle_x = math.atan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) + angle_z = math.atan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) if trackball_in_wall and (side == ball_side or ball_side == 'both'): - # oled_mount_rotation_xyz = (0, rad2deg(angle_x), -rad2deg(angle_z)-90) + np.array(oled_rotation_offset) - # oled_mount_rotation_xyz = (rad2deg(angle_x)*.707, rad2deg(angle_x)*.707, -45) + np.array(oled_rotation_offset) - oled_mount_rotation_xyz = (0, rad2deg(angle_x), -90) + np.array(_oled_rotation_offset) + oled_mount_rotation_xyz = (0, math.degrees(angle_x), -90) + np.array(_oled_rotation_offset) else: - oled_mount_rotation_xyz = (rad2deg(angle_x), 0, -rad2deg(angle_z)) + np.array(_oled_rotation_offset) + oled_mount_rotation_xyz = (math.degrees(angle_x), 0, -math.degrees(angle_z)) + np.array(_oled_rotation_offset) return oled_mount_location_xyz, oled_mount_rotation_xyz diff --git a/src/dactyl_keyboard/generate_configuration.py b/src/dactyl_keyboard/generate_configuration.py index 084fe516a..fb6f10aa6 100644 --- a/src/dactyl_keyboard/generate_configuration.py +++ b/src/dactyl_keyboard/generate_configuration.py @@ -1,13 +1,10 @@ +import math import sys import getopt import os import json -pi = 3.14159 -d2r = pi / 180 -r2d = 180 / pi - shape_config = { 'ENGINE': 'solid', # 'solid' = solid python / OpenSCAD, 'cadquery' = cadquery / OpenCascade @@ -27,11 +24,11 @@ 'nrows': 5, # 5, # key rows 'ncols': 6, # 6, # key columns - 'alpha': pi / 12.0, # curvature of the columns - 'beta': pi / 36.0, # curvature of the rows + 'alpha': math.pi / 12.0, # curvature of the columns + 'beta': math.pi / 36.0, # curvature of the rows 'centercol': 3, # controls left_right tilt / tenting (higher number is more tenting) 'centerrow_offset': 3, # rows from max, controls front_back tilt - 'tenting_angle': pi / 12.0, # or, change this for more precise tenting control + 'tenting_angle': math.pi / 12.0, # or, change this for more precise tenting control # symmetry states if it is a symmetric or asymmetric bui. If asymmetric it doubles the generation time. 'symmetry': "symmetric", # "asymmetric" or "symmetric" @@ -216,10 +213,10 @@ # http://patentimages.storage.googleapis.com/EP0219944A2/imgf0002.png # fixed_z overrides the z portion of the column ofsets above. # NOTE: THIS DOESN'T WORK QUITE LIKE I'D HOPED. - 'fixed_angles': [d2r * 10, d2r * 10, 0, 0, 0, d2r * -15, d2r * -15], + 'fixed_angles': [math.radians(10), math.radians(10), 0, 0, 0, math.radians(-15), math.radians(-15)], 'fixed_x': [-41.5, -22.5, 0, 20.3, 41.4, 65.5, 89.6], # relative to the middle finger 'fixed_z': [12.1, 8.3, 0, 5, 10.7, 14.5, 17.5], - 'fixed_tenting': d2r * 0, + 'fixed_tenting': 0, ################# ## Switch Hole ## From 75350e1b1dd87bde58a8ea42acbae6e7b53d51e7 Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Wed, 26 Oct 2022 05:13:26 +0000 Subject: [PATCH 08/11] Provide option to generate configuration in script. --- src/dactyl_keyboard/dactyl_manuform.py | 31 ++++---- src/dactyl_keyboard/generate_configuration.py | 70 +++++++------------ 2 files changed, 44 insertions(+), 57 deletions(-) diff --git a/src/dactyl_keyboard/dactyl_manuform.py b/src/dactyl_keyboard/dactyl_manuform.py index 16d7b8fdb..e136f64c4 100644 --- a/src/dactyl_keyboard/dactyl_manuform.py +++ b/src/dactyl_keyboard/dactyl_manuform.py @@ -1,10 +1,12 @@ +import argparse +import copy +import json +import logging import math +import os import os.path as path -import getopt +import pathlib import sys -import json -import os -import copy if sys.version_info[:2] > (3, 9): import importlib.resources as resources @@ -13,7 +15,12 @@ import numpy as np -from . generate_configuration import shape_config +from . generate_configuration import GenerateConfigAction, shape_config + +parser = argparse.ArgumentParser(description="Generate a dactyl keyboard.") +parser.add_argument("--generate-config", action=GenerateConfigAction) +parser.add_argument("--config", default=argparse.SUPPRESS, type=pathlib.Path, help="A config file to control keyboard generation.") +args = parser.parse_args() ############################################### @@ -24,16 +31,12 @@ for key, item in shape_config.items(): locals()[key] = item -if len(sys.argv) <= 1: - print("NO CONFIGURATION SPECIFIED, USING DEFAULT CONFIGURATION") +if not "config" in args: + logging.info("NO CONFIGURATION SPECIFIED, USING DEFAULT CONFIGURATION") else: - # CHECK FOR CONFIG FILE AND WRITE TO ANY VARIABLES IN FILE. - opts, args = getopt.getopt(sys.argv[1:], "", ["config="]) - for opt, arg in opts: - if opt in ('--config'): - with open(arg, mode="rt", encoding="utf-8") as fid: - for key, item in json.load(fid).items(): - locals()[key] = item + with open(args.config, mode="rt", encoding="utf-8") as fid: + for key, item in json.load(fid).items(): + locals()[key] = item # Really rough setup. Check for ENGINE, set it not present from configuration. diff --git a/src/dactyl_keyboard/generate_configuration.py b/src/dactyl_keyboard/generate_configuration.py index fb6f10aa6..cb2d6336c 100644 --- a/src/dactyl_keyboard/generate_configuration.py +++ b/src/dactyl_keyboard/generate_configuration.py @@ -1,8 +1,9 @@ -import math -import sys -import getopt -import os +import argparse import json +import logging +import math +import pathlib +from typing import Optional shape_config = { @@ -466,42 +467,25 @@ } -#################################### -# END CONFIGURATION SECTION -#################################### - - -def save_config(): - # Check to see if the user has specified an alternate config - opts, args = getopt.getopt(sys.argv[1:], "", ["config=", "update="]) - got_opts = False - for opt, arg in opts: - if opt in ('--update'): - with open(os.path.join(r"..", "configs", arg + '.json'), mode='r') as fid: - data = json.load(fid) - shape_config.update(data) - got_opts = True - - for opt, arg in opts: - if opt in ('--config'): - # If a config file was specified, set the config_name and save_dir - shape_config['save_dir'] = arg - shape_config['config_name'] = arg - got_opts = True - - # Write the config to ./configs/.json - if got_opts: - with open(os.path.join(r"..", "configs", shape_config['config_name'] + '.json'), mode='w') as fid: - json.dump(shape_config, fid, indent=4) - - else: - with open(os.path.join(r".", 'run_config.json'), mode='w') as fid: - json.dump(shape_config, fid, indent=4) - - -if __name__ == '__main__': - save_config() - - # HERE FOR QUICK TESTING, SHOULD BE COMMENTED ON COMMIT - # from dactyl_manuform import * - # run() + +class GenerateConfigAction(argparse.Action): + """ + Generate a file with default configuration settings. + """ + + def __init__(self, option_strings, dest, **kwargs): + kwargs.update({ + 'nargs': "?", + 'const': pathlib.Path("default.json"), + 'default': argparse.SUPPRESS, + 'type': pathlib.Path, + 'required': False, + 'help': "Generate the default settings configuration file, and exit." + }) + super().__init__(option_strings, dest, **kwargs) + + def __call__(self, _parser: argparse.ArgumentParser, _namespace: argparse.Namespace, values: pathlib.Path, _option_string: Optional[str] = None): + with values.open(mode="wt", encoding="utf-8") as opened_file: + logging.info("Generating default configuration to %s", values) + json.dump(shape_config, opened_file, indent=4) + exit() From f09b3d4cb8a6b7d83ea43ec420575aa1f2b58227 Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Wed, 26 Oct 2022 05:34:04 +0000 Subject: [PATCH 09/11] Switch from manual debug printing to logging. --- src/dactyl_keyboard/dactyl_manuform.py | 232 +++++++++--------- src/dactyl_keyboard/generate_configuration.py | 2 +- src/dactyl_keyboard/helpers_cadquery.py | 32 +-- src/dactyl_keyboard/helpers_solid.py | 27 +- 4 files changed, 143 insertions(+), 150 deletions(-) diff --git a/src/dactyl_keyboard/dactyl_manuform.py b/src/dactyl_keyboard/dactyl_manuform.py index e136f64c4..57ea94dc5 100644 --- a/src/dactyl_keyboard/dactyl_manuform.py +++ b/src/dactyl_keyboard/dactyl_manuform.py @@ -7,6 +7,7 @@ import os.path as path import pathlib import sys +from typing import Optional if sys.version_info[:2] > (3, 9): import importlib.resources as resources @@ -17,11 +18,40 @@ from . generate_configuration import GenerateConfigAction, shape_config + +class LogLevelAction(argparse.Action): + """ + Set the log level + """ + + log_levels = { + 'DEBUG': logging.DEBUG, + 'INFO': logging.INFO, + 'WARNING': logging.WARNING, + 'ERROR': logging.ERROR, + 'CRITICAL': logging.CRITICAL, + } + + def __init__(self, option_strings, dest: str, **kwargs): + kwargs.update({ + 'default': "INFO", + 'type': str, + 'choices': self.log_levels.keys(), + 'help': "The log level to use." + }) + super().__init__(option_strings, dest, **kwargs) + + def __call__(self, _parser: argparse.ArgumentParser, namespace: argparse.Namespace, values: pathlib.Path, _option_string: Optional[str] = None): + setattr(namespace, self.dest, values) + + parser = argparse.ArgumentParser(description="Generate a dactyl keyboard.") parser.add_argument("--generate-config", action=GenerateConfigAction) parser.add_argument("--config", default=argparse.SUPPRESS, type=pathlib.Path, help="A config file to control keyboard generation.") +parser.add_argument("--log-level", action=LogLevelAction) args = parser.parse_args() +logging.basicConfig(level=args.log_level) ############################################### # EXTREMELY UGLY BUT FUNCTIONAL BOOTSTRAP @@ -38,15 +68,7 @@ for key, item in json.load(fid).items(): locals()[key] = item - -# Really rough setup. Check for ENGINE, set it not present from configuration. -try: - print('Found Current Engine in Config = {}'.format(ENGINE)) -except Exception: - print('Engine Not Found in Config') - ENGINE = 'solid' - # ENGINE = 'cadquery' - print('Setting Current Engine = {}'.format(ENGINE)) +logging.info("Using engine %s", ENGINE) if save_dir in ['', None, '.']: save_path = path.join(r".", "things") @@ -74,12 +96,6 @@ debug_exports = False -debug_trace = False - - -def debugprint(info): - if debug_trace: - print(info) if oled_mount_type is not None and oled_mount_type != "NONE": @@ -432,7 +448,6 @@ def key_pcb(): def rotate_around_x(position, angle): - # debugprint('rotate_around_x()') t_matrix = np.array( [ [1, 0, 0], @@ -444,7 +459,6 @@ def rotate_around_x(position, angle): def rotate_around_y(position, angle): - # debugprint('rotate_around_y()') t_matrix = np.array( [ [math.cos(angle), 0, math.sin(angle)], @@ -465,7 +479,7 @@ def apply_key_geometry( column_style=column_style, ): - debugprint('apply_key_geometry()') + logging.debug("apply_key_geometry()") column_angle = beta * (centercol - column) @@ -505,22 +519,20 @@ def apply_key_geometry( def x_rot(shape, angle): - # debugprint('x_rot()') return rotate(shape, [math.degrees(angle), 0, 0]) def y_rot(shape, angle): - # debugprint('y_rot()') return rotate(shape, [0, math.degrees(angle), 0]) def key_place(shape, column, row): - debugprint('key_place()') + logging.debug("key_place()") return apply_key_geometry(shape, translate, x_rot, y_rot, column, row) def add_translate(shape, xyz): - debugprint('add_translate()') + logging.debug("add_translate()") vals = [] for i in range(len(shape)): vals.append(shape[i] + xyz[i]) @@ -528,14 +540,14 @@ def add_translate(shape, xyz): def key_position(position, column, row): - debugprint('key_position()') + logging.debug("key_position()") return apply_key_geometry( position, add_translate, rotate_around_x, rotate_around_y, column, row ) def key_holes(side="right"): - debugprint('key_holes()') + logging.debug("key_holes()") # hole = single_plate() holes = [] for column in range(ncols): @@ -549,7 +561,7 @@ def key_holes(side="right"): def plate_pcb_cutouts(side="right"): - debugprint('plate_pcb_cutouts()') + logging.debug("plate_pcb_cutouts()") # hole = single_plate() cutouts = [] for column in range(ncols): @@ -582,7 +594,7 @@ def caps(cap_type="MX"): def web_post(): - debugprint('web_post()') + logging.debug("web_post()") post = box(post_size, post_size, web_thickness) post = translate(post, (0, 0, plate_thickness - (web_thickness / 2))) return post @@ -622,7 +634,7 @@ def web_post_br(wide=False): def connectors(): - debugprint('connectors()') + logging.debug("connectors()") hulls = [] for column in range(ncols - 1): if reduced_inner_cols <= column < (ncols - reduced_outer_cols-1): @@ -689,8 +701,6 @@ def connectors(): def thumborigin(): - # debugprint('thumborigin()') - corner = cornerrow if reduced_inner_cols > 0 else lastrow origin = key_position([mount_width / 2, -(mount_height / 2), 0], 1, corner) @@ -704,7 +714,7 @@ def thumborigin(): def default_thumb_tl_place(shape): - debugprint('thumb_tl_place()') + logging.debug("thumb_tl_place()") shape = rotate(shape, [7.5, -18, 10]) shape = translate(shape, thumborigin()) shape = translate(shape, [-32.5, -14.5, -2.5]) @@ -712,7 +722,7 @@ def default_thumb_tl_place(shape): def default_thumb_tr_place(shape): - debugprint('thumb_tr_place()') + logging.debug("thumb_tr_place()") shape = rotate(shape, [10, -15, 10]) shape = translate(shape, thumborigin()) shape = translate(shape, [-12, -16, 3]) @@ -720,7 +730,7 @@ def default_thumb_tr_place(shape): def default_thumb_mr_place(shape): - debugprint('thumb_mr_place()') + logging.debug("thumb_mr_place()") shape = rotate(shape, [-6, -34, 48]) shape = translate(shape, thumborigin()) shape = translate(shape, [-29, -40, -13]) @@ -728,7 +738,7 @@ def default_thumb_mr_place(shape): def default_thumb_ml_place(shape): - debugprint('thumb_ml_place()') + logging.debug("thumb_ml_place()") shape = rotate(shape, [6, -34, 40]) shape = translate(shape, thumborigin()) shape = translate(shape, [-51, -25, -12]) @@ -736,7 +746,7 @@ def default_thumb_ml_place(shape): def default_thumb_br_place(shape): - debugprint('thumb_br_place()') + logging.debug("thumb_br_place()") shape = rotate(shape, [-16, -33, 54]) shape = translate(shape, thumborigin()) shape = translate(shape, [-37.8, -55.3, -25.3]) @@ -744,7 +754,7 @@ def default_thumb_br_place(shape): def default_thumb_bl_place(shape): - debugprint('thumb_bl_place()') + logging.debug("thumb_bl_place()") shape = rotate(shape, [-4, -35, 52]) shape = translate(shape, thumborigin()) shape = translate(shape, [-56.3, -43.3, -23.5]) @@ -752,7 +762,7 @@ def default_thumb_bl_place(shape): def default_thumb_1x_layout(shape, cap=False): - debugprint('thumb_1x_layout()') + logging.debug("thumb_1x_layout()") if cap: shape_list = [ default_thumb_mr_place(rotate(shape, [0, 0, thumb_plate_mr_rotation])), @@ -787,7 +797,7 @@ def default_thumb_pcb_plate_cutouts(side="right"): def default_thumb_15x_layout(shape, cap=False, plate=True): - debugprint('thumb_15x_layout()') + logging.debug("thumb_15x_layout()") if plate: if cap: shape = rotate(shape, (0, 0, 90)) @@ -827,7 +837,7 @@ def usize_dimention(Usize=1.5): def adjustable_plate_half(Usize=1.5): - debugprint('double_plate()') + logging.debug("double_plate()") adjustable_plate_height = adjustable_plate_size(Usize) top_plate = box(mount_width, adjustable_plate_height, web_thickness) top_plate = translate(top_plate, @@ -837,7 +847,7 @@ def adjustable_plate_half(Usize=1.5): def adjustable_plate(Usize=1.5): - debugprint('double_plate()') + logging.debug("double_plate()") top_plate = adjustable_plate_half(Usize) return union((top_plate, mirror(top_plate, 'XZ'))) @@ -853,7 +863,7 @@ def adjustable_square_plate(Uwidth=1.5, Uheight=1.5): def double_plate_half(): - debugprint('double_plate()') + logging.debug("double_plate()") top_plate = box(mount_width, double_plate_height, web_thickness) top_plate = translate(top_plate, [0, (double_plate_height + mount_height) / 2, plate_thickness - (web_thickness / 2)] @@ -862,7 +872,7 @@ def double_plate_half(): def double_plate(): - debugprint('double_plate()') + logging.debug("double_plate()") top_plate = double_plate_half() return union((top_plate, mirror(top_plate, 'XZ'))) @@ -979,7 +989,7 @@ def default_thumbcaps(): def default_thumb(side="right"): - print('thumb()') + logging.debug("thumb()") shape = default_thumb_1x_layout(rotate(single_plate(side=side), (0, 0, -90))) shape = union([shape, default_thumb_15x_layout(rotate(single_plate(side=side), (0, 0, -90)))]) shape = union([shape, default_thumb_15x_layout(double_plate(), plate=False)]) @@ -991,35 +1001,35 @@ def default_thumb(side="right"): def thumb_post_tr(): - debugprint('thumb_post_tr()') + logging.debug("thumb_post_tr()") return translate(web_post(), [(mount_width / 2) - post_adj, ((mount_height/2) + double_plate_height) - post_adj, 0] ) def thumb_post_tl(): - debugprint('thumb_post_tl()') + logging.debug("thumb_post_tl()") return translate(web_post(), [-(mount_width / 2) + post_adj, ((mount_height/2) + double_plate_height) - post_adj, 0] ) def thumb_post_bl(): - debugprint('thumb_post_bl()') + logging.debug("thumb_post_bl()") return translate(web_post(), [-(mount_width / 2) + post_adj, -((mount_height/2) + double_plate_height) + post_adj, 0] ) def thumb_post_br(): - debugprint('thumb_post_br()') + logging.debug("thumb_post_br()") return translate(web_post(), [(mount_width / 2) - post_adj, -((mount_height/2) + double_plate_height) + post_adj, 0] ) def default_thumb_connectors(): - print('thumb_connectors()') + logging.debug('thumb_connectors()') hulls = [] # Top two @@ -1446,28 +1456,28 @@ def minidox_thumb_pcb_plate_cutouts(side="right"): def minidox_thumb_post_tr(): - debugprint('thumb_post_tr()') + logging.debug("thumb_post_tr()") return translate(web_post(), [(mount_width / 2) - post_adj, ((mount_height/2) + adjustable_plate_size(minidox_Usize)) - post_adj, 0] ) def minidox_thumb_post_tl(): - debugprint('thumb_post_tl()') + logging.debug("thumb_post_tl()") return translate(web_post(), [-(mount_width / 2) + post_adj, ((mount_height/2) + adjustable_plate_size(minidox_Usize)) - post_adj, 0] ) def minidox_thumb_post_bl(): - debugprint('thumb_post_bl()') + logging.debug("thumb_post_bl()") return translate(web_post(), [-(mount_width / 2) + post_adj, -((mount_height/2) + adjustable_plate_size(minidox_Usize)) + post_adj, 0] ) def minidox_thumb_post_br(): - debugprint('thumb_post_br()') + logging.debug("thumb_post_br()") return translate(web_post(), [(mount_width / 2) - post_adj, -((mount_height/2) + adjustable_plate_size(minidox_Usize)) + post_adj, 0] ) @@ -1787,7 +1797,7 @@ def tbjs_place(shape): def tbjs_thumb_tl_place(shape): - debugprint('thumb_tr_place()') + logging.debug("thumb_tr_place()") # Modifying to make a "ring" of keys shape = rotate(shape, [0, 0, 0]) t_off = tbjs_key_translation_offsets[0] @@ -1800,7 +1810,7 @@ def tbjs_thumb_tl_place(shape): def tbjs_thumb_mr_place(shape): - debugprint('thumb_mr_place()') + logging.debug("thumb_mr_place()") shape = rotate(shape, [0, 0, 0]) shape = rotate(shape, tbjs_key_rotation_offsets[1]) t_off = tbjs_key_translation_offsets[1] @@ -1812,7 +1822,7 @@ def tbjs_thumb_mr_place(shape): def tbjs_thumb_br_place(shape): - debugprint('thumb_br_place()') + logging.debug("thumb_br_place()") shape = rotate(shape, [0, 0, 180]) shape = rotate(shape, tbjs_key_rotation_offsets[2]) @@ -1825,7 +1835,7 @@ def tbjs_thumb_br_place(shape): def tbjs_thumb_bl_place(shape): - debugprint('thumb_bl_place()') + logging.debug("thumb_bl_place()") shape = rotate(shape, [0, 0, 180]) shape = rotate(shape, tbjs_key_rotation_offsets[3]) t_off = tbjs_key_translation_offsets[3] @@ -1884,35 +1894,35 @@ def tbjs_thumb(side="right"): def tbjs_thumb_post_tr(): - debugprint('thumb_post_tr()') + logging.debug("thumb_post_tr()") return translate(web_post(), [(mount_width / 2) + adjustable_plate_size(tbjs_Uwidth) - post_adj, ((mount_height/2) + adjustable_plate_size(tbjs_Uheight)) - post_adj, 0] ) def tbjs_thumb_post_tl(): - debugprint('thumb_post_tl()') + logging.debug("thumb_post_tl()") return translate(web_post(), [-(mount_width / 2) - adjustable_plate_size(tbjs_Uwidth) + post_adj, ((mount_height/2) + adjustable_plate_size(tbjs_Uheight)) - post_adj, 0] ) def tbjs_thumb_post_bl(): - debugprint('thumb_post_bl()') + logging.debug("thumb_post_bl()") return translate(web_post(), [-(mount_width / 2) - adjustable_plate_size(tbjs_Uwidth) + post_adj, -((mount_height/2) + adjustable_plate_size(tbjs_Uheight)) + post_adj, 0] ) def tbjs_thumb_post_br(): - debugprint('thumb_post_br()') + logging.debug("thumb_post_br()") return translate(web_post(), [(mount_width / 2) + adjustable_plate_size(tbjs_Uwidth) - post_adj, - ((mount_height/2) + adjustable_plate_size(tbjs_Uheight)) + post_adj, 0] ) def tbjs_post_r(): - debugprint('tbjs_post_r()') + logging.debug("tbjs_post_r()") radius = ball_diameter/2 + ball_wall_thickness + ball_gap return translate(web_post(), [1.0*(radius - post_adj), 0.0*(radius - post_adj), 0] @@ -1920,7 +1930,7 @@ def tbjs_post_r(): def tbjs_post_tr(): - debugprint('tbjs_post_tr()') + logging.debug("tbjs_post_tr()") radius = ball_diameter/2+ball_wall_thickness + ball_gap return translate(web_post(), [0.5*(radius - post_adj), 0.866*(radius - post_adj), 0] @@ -1928,7 +1938,7 @@ def tbjs_post_tr(): def tbjs_post_tl(): - debugprint('tbjs_post_tl()') + logging.debug("tbjs_post_tl()") radius = ball_diameter/2+ball_wall_thickness + ball_gap return translate(web_post(), [-0.5*(radius - post_adj), 0.866*(radius - post_adj), 0] @@ -1936,7 +1946,7 @@ def tbjs_post_tl(): def tbjs_post_l(): - debugprint('tbjs_post_l()') + logging.debug("tbjs_post_l()") radius = ball_diameter/2+ball_wall_thickness + ball_gap return translate(web_post(), [-1.0*(radius - post_adj), 0.0*(radius - post_adj), 0] @@ -1944,7 +1954,7 @@ def tbjs_post_l(): def tbjs_post_bl(): - debugprint('tbjs_post_bl()') + logging.debug("tbjs_post_bl()") radius = ball_diameter/2+ball_wall_thickness + ball_gap return translate(web_post(), [-0.5*(radius - post_adj), -0.866*(radius - post_adj), 0] @@ -1952,7 +1962,7 @@ def tbjs_post_bl(): def tbjs_post_br(): - debugprint('tbjs_post_br()') + logging.debug("tbjs_post_br()") radius = ball_diameter/2+ball_wall_thickness + ball_gap return translate(web_post(), [0.5*(radius - post_adj), -0.866*(radius - post_adj), 0] @@ -1960,7 +1970,7 @@ def tbjs_post_br(): def tbjs_thumb_connectors(): - print('thumb_connectors()') + logging.debug('thumb_connectors()') hulls = [] # bottom 2 to tb @@ -2302,7 +2312,7 @@ def tbcj_thumb_connectors(): ########## def left_key_position(row, direction, low_corner=False, side='right'): - debugprint("left_key_position()") + logging.debug("left_key_position()") pos = np.array( key_position([-mount_width * 0.5, direction * mount_height * 0.5, 0], 0, row) ) @@ -2336,23 +2346,23 @@ def left_key_position(row, direction, low_corner=False, side='right'): def left_key_place(shape, row, direction, low_corner=False, side='right'): - debugprint("left_key_place()") + logging.debug("left_key_place()") pos = left_key_position(row, direction, low_corner=low_corner, side=side) return translate(shape, pos) def wall_locate1(dx, dy): - debugprint("wall_locate1()") + logging.debug("wall_locate1()") return [dx * wall_thickness, dy * wall_thickness, -1] def wall_locate2(dx, dy): - debugprint("wall_locate2()") + logging.debug("wall_locate2()") return [dx * wall_x_offset, dy * wall_y_offset, -wall_z_offset] def wall_locate3(dx, dy, back=False): - debugprint("wall_locate3()") + logging.debug("wall_locate3()") if back: return [ dx * (wall_x_offset + wall_base_x_thickness), @@ -2368,7 +2378,7 @@ def wall_locate3(dx, dy, back=False): def wall_brace(place1, dx1, dy1, post1, place2, dx2, dy2, post2, back=False, skeleton=False, skel_bottom=False): - debugprint("wall_brace()") + logging.debug("wall_brace()") hulls = [] hulls.append(place1(post1)) @@ -2407,7 +2417,7 @@ def wall_brace(place1, dx1, dy1, post1, place2, dx2, dy2, post2, back=False, ske def key_wall_brace(x1, y1, dx1, dy1, post1, x2, y2, dx2, dy2, post2, back=False, skeleton=False, skel_bottom=False): - debugprint("key_wall_brace()") + logging.debug("key_wall_brace()") return wall_brace( (lambda shape: key_place(shape, x1, y1)), dx1, @@ -2424,7 +2434,7 @@ def key_wall_brace(x1, y1, dx1, dy1, post1, x2, y2, dx2, dy2, post2, back=False, def back_wall(skeleton=False): - print("back_wall()") + logging.debug("back_wall()") x = 0 shape = None shape = union([shape, key_wall_brace( @@ -2456,7 +2466,7 @@ def back_wall(skeleton=False): def right_wall(skeleton=False): - print("right_wall()") + logging.debug("right_wall()") y = 0 shape = None @@ -2493,7 +2503,7 @@ def right_wall(skeleton=False): def left_wall(side='right', skeleton=False): - print('left_wall()') + logging.debug("left_wall()") shape = union([wall_brace( (lambda sh: key_place(sh, 0, 0)), 0, 1, web_post_tl(), (lambda sh: left_key_place(sh, 0, 1, side=side)), 0, 1, web_post(), @@ -2549,7 +2559,7 @@ def left_wall(side='right', skeleton=False): def front_wall(skeleton=False): - print('front_wall()') + logging.debug("front_wall()") shape = None # shape = union([shape,key_wall_brace( @@ -2582,9 +2592,9 @@ def front_wall(skeleton=False): for i in range(ncols - 3): x = i + 3 - print("col {}".format(x)) + logging.debug("col {}", x) if x < (offset_col - 1): - print("pre-offset") + logging.debug("pre-offset") if x > 3: shape = union([shape, key_wall_brace( x-1, lastrow, 0, -1, web_post_br(), x, lastrow, 0, -1, web_post_bl() @@ -2593,7 +2603,7 @@ def front_wall(skeleton=False): x, lastrow, 0, -1, web_post_bl(), x, lastrow, 0, -1, web_post_br() )]) elif x < (offset_col): - print("offset setup") + logging.debug("offset setup") if x > 3: shape = union([shape, key_wall_brace( x-1, lastrow, 0, -1, web_post_br(), x, lastrow, 0, -1, web_post_bl() @@ -2603,7 +2613,7 @@ def front_wall(skeleton=False): )]) elif x == (offset_col): - print("offset") + logging.debug("offset") shape = union([shape, key_wall_brace( x - 1, lastrow, 0.5, -1, web_post_br(), x, cornerrow, .5, -1, web_post_bl() )]) @@ -2612,7 +2622,7 @@ def front_wall(skeleton=False): )]) elif x == (offset_col + 1): - print("offset completion") + logging.debug("offset completion") shape = union([shape, key_wall_brace( x, cornerrow, 0, -1, web_post_bl(), x - 1, cornerrow, 0, -1, web_post_br() )]) @@ -2621,7 +2631,7 @@ def front_wall(skeleton=False): )]) else: - print("post offset") + logging.debug("post offset") shape = union([shape, key_wall_brace( x, cornerrow, 0, -1, web_post_bl(), x - 1, corner, 0, -1, web_post_br() )]) @@ -2684,7 +2694,7 @@ def thumb_connection(side='right', style_override=None, skeleton=False): def default_thumb_walls(skeleton=False): - print('thumb_walls()') + logging.debug("thumb_walls()") # thumb, walls if default_1U_cluster: shape = union([wall_brace(default_thumb_mr_place, 0, -1, web_post_br(), default_thumb_tr_place, 0, -1, web_post_br())]) @@ -2712,7 +2722,7 @@ def default_thumb_walls(skeleton=False): def default_thumb_connection(side='right', skeleton=False): - print('thumb_connection()') + logging.debug("thumb_connection()") # clunky bit on the top left thumb connection (normal connectors don't work well) shape = None shape = union([shape, bottom_hull( @@ -2768,7 +2778,7 @@ def default_thumb_connection(side='right', skeleton=False): def tbjs_thumb_connection(side='right', skeleton=False): - print('thumb_connection()') + logging.debug("thumb_connection()") # clunky bit on the top left thumb connection (normal connectors don't work well) hulls = [] hulls.append( @@ -2811,7 +2821,7 @@ def tbjs_thumb_connection(side='right', skeleton=False): def tbjs_thumb_walls(skeleton=False): - print('thumb_walls()') + logging.debug("thumb_walls()") # thumb, walls shape = wall_brace( tbjs_thumb_mr_place, .5, 1, tbjs_thumb_post_tr(), @@ -3163,7 +3173,7 @@ def carbonfet_thumb_connection(side='right', skeleton=False): def case_walls(side='right', skeleton=False): - print('case_walls()') + logging.debug("case_walls()") return ( union([ back_wall(skeleton=skeleton), @@ -3191,19 +3201,19 @@ def case_walls(side='right', skeleton=False): def rj9_cube(): - debugprint('rj9_cube()') + logging.debug("rj9_cube()") shape = box(14.78, 13, 22.38) return shape def rj9_space(): - debugprint('rj9_space()') + logging.debug("rj9_space()") return translate(rj9_cube(), rj9_position) def rj9_holder(): - print('rj9_holder()') + logging.debug("rj9_holder()") shape = union([translate(box(10.78, 9, 18.38), (0, 2, 0)), translate(box(10.78, 13, 5), (0, 0, 5))]) shape = difference(rj9_cube(), [shape]) shape = translate(shape, rj9_position) @@ -3219,7 +3229,7 @@ def rj9_holder(): def usb_holder(): - print('usb_holder()') + logging.debug("usb_holder()") shape = box( usb_holder_size[0] + usb_holder_thickness, usb_holder_size[1], @@ -3236,7 +3246,7 @@ def usb_holder(): def usb_holder_hole(): - debugprint('usb_holder_hole()') + logging.debug("usb_holder_hole()") shape = box(*usb_holder_size) shape = translate(shape, ( @@ -3262,7 +3272,7 @@ def usb_holder_hole(): def external_mount_hole(): - print('external_mount_hole()') + logging.debug("external_mount_hole()") shape = box(external_holder_width, 20.0, external_holder_height+.1) undercut = box(external_holder_width+8, 10.0, external_holder_height+8+.1) shape = union([shape, translate(undercut, (0, -5, 0))]) @@ -3288,7 +3298,7 @@ def external_mount_hole(): def pcb_usb_hole(): - debugprint('pcb_holder()') + logging.debug("pcb_holder()") pcb_usb_position = copy.deepcopy(pcb_mount_ref_position) pcb_usb_position[0] = pcb_usb_position[0] + pcb_usb_hole_offset[0] pcb_usb_position[1] = pcb_usb_position[1] + pcb_usb_hole_offset[1] @@ -3313,7 +3323,7 @@ def pcb_usb_hole(): def pcb_holder(): - debugprint('pcb_holder()') + logging.debug("pcb_holder()") shape = box(*pcb_holder_size) shape = translate(shape, ( @@ -3326,7 +3336,7 @@ def pcb_holder(): def wall_thinner(): - debugprint('wall_thinner()') + logging.debug("wall_thinner()") shape = box(*wall_thinner_size) shape = translate(shape, ( @@ -3339,7 +3349,7 @@ def wall_thinner(): def trrs_hole(): - debugprint('trrs_hole()') + logging.debug("trrs_hole()") trrs_position = copy.deepcopy(pcb_mount_ref_position) trrs_position[0] = trrs_position[0] + trrs_offset[0] trrs_position[1] = trrs_position[1] + trrs_offset[1] @@ -3364,7 +3374,7 @@ def trrs_hole(): def pcb_screw_hole(): - debugprint('pcb_screw_hole()') + logging.debug("pcb_screw_hole()") holes = [] hole = cylinder(*pcb_screw_hole_size) hole = translate(hole, pcb_screw_position) @@ -3779,7 +3789,7 @@ def oled_undercut_mount_frame(side='right'): def teensy_holder(): - print('teensy_holder()') + logging.debug("teensy_holder()") teensy_top_xy = key_position(wall_locate3(-1, 0), 0, centerrow - 1) teensy_bot_xy = key_position(wall_locate3(-1, 0), 0, centerrow + 1) teensy_holder_length = teensy_top_xy[1] - teensy_bot_xy[1] @@ -3824,7 +3834,7 @@ def teensy_holder(): def screw_insert_shape(bottom_radius, top_radius, height): - debugprint('screw_insert_shape()') + logging.debug("screw_insert_shape()") if bottom_radius == top_radius: base = cylinder(radius=bottom_radius, height=height) else: @@ -3838,28 +3848,28 @@ def screw_insert_shape(bottom_radius, top_radius, height): def screw_insert(column, row, bottom_radius, top_radius, height, side='right'): - debugprint('screw_insert()') + logging.debug("screw_insert()") shift_right = column == lastcol shift_left = column == 0 shift_up = (not (shift_right or shift_left)) and (row == 0) shift_down = (not (shift_right or shift_left)) and (row >= lastrow) if screws_offset == 'INSIDE': - # debugprint('Shift Inside') + # logging.debug("Shift Inside") shift_left_adjust = wall_base_x_thickness shift_right_adjust = -wall_base_x_thickness/2 shift_down_adjust = -wall_base_y_thickness/2 shift_up_adjust = -wall_base_y_thickness/3 elif screws_offset == 'OUTSIDE': - debugprint('Shift Outside') + logging.debug("Shift Outside") shift_left_adjust = 0 shift_right_adjust = wall_base_x_thickness/2 shift_down_adjust = wall_base_y_thickness*2/3 shift_up_adjust = wall_base_y_thickness*2/3 else: - # debugprint('Shift Origin') + # logging.debug("Shift Origin") shift_left_adjust = 0 shift_right_adjust = 0 shift_down_adjust = 0 @@ -3953,7 +3963,7 @@ def thumb_screw_insert(bottom_radius, top_radius, height, offset=None, side='rig def screw_insert_all_shapes(bottom_radius, top_radius, height, offset=0, side='right'): - print('screw_insert_all_shapes()') + logging.debug("screw_insert_all_shapes()") shape = ( translate(screw_insert(0, 0, bottom_radius, top_radius, height, side=side), (0, 0, offset)), translate(screw_insert(0, cornerrow, bottom_radius, top_radius, height, side=side), (0, left_wall_lower_y_offset, offset)), @@ -4002,7 +4012,7 @@ def screw_insert_screw_holes(side='right'): def wire_post(direction, offset): - debugprint('wire_post()') + logging.debug("wire_post()") s1 = box( wire_post_diameter, wire_post_diameter, wire_post_height ) @@ -4024,7 +4034,7 @@ def wire_post(direction, offset): def wire_posts(): - debugprint('wire_posts()') + logging.debug("wire_posts()") shape = default_thumb_ml_place(wire_post(1, 0).translate([-5, 0, -2])) shape = union([shape, default_thumb_ml_place(wire_post(-1, 6).translate([0, 0, -2.5]))]) shape = union([shape, default_thumb_ml_place(wire_post(1, 0).translate([5, 0, -2]))]) @@ -4041,7 +4051,7 @@ def wire_posts(): def model_side(side="right"): - print('model_right()') + logging.debug("model_right()") #shape = add([key_holes(side=side)]) shape = union([key_holes(side=side)]) if debug_exports: @@ -4143,7 +4153,7 @@ def model_side(side="right"): has_trackball = False if ('TRACKBALL' in thumb_style) and (side == ball_side or ball_side == 'both'): - print("Has Trackball") + logging.debug("Has Trackball") tbprecut, tb, tbcutout, sensor, ball = generate_trackball_in_cluster() has_trackball = True thumb_section = difference(thumb_section, [tbprecut]) @@ -4265,7 +4275,7 @@ def baseplate(wedge_angle=None, side='right'): if sizes[-1] > max_val: inner_index = i_wire max_val = sizes[-1] - debugprint(sizes) + logging.debug(sizes) inner_wire = base_wires[inner_index] # inner_plate = cq.Workplane('XY').add(cq.Face.makeFromWires(inner_wire)) diff --git a/src/dactyl_keyboard/generate_configuration.py b/src/dactyl_keyboard/generate_configuration.py index cb2d6336c..1fb8324a9 100644 --- a/src/dactyl_keyboard/generate_configuration.py +++ b/src/dactyl_keyboard/generate_configuration.py @@ -473,7 +473,7 @@ class GenerateConfigAction(argparse.Action): Generate a file with default configuration settings. """ - def __init__(self, option_strings, dest, **kwargs): + def __init__(self, option_strings, dest: str, **kwargs): kwargs.update({ 'nargs': "?", 'const': pathlib.Path("default.json"), diff --git a/src/dactyl_keyboard/helpers_cadquery.py b/src/dactyl_keyboard/helpers_cadquery.py index cc7a37ed8..1db459a83 100644 --- a/src/dactyl_keyboard/helpers_cadquery.py +++ b/src/dactyl_keyboard/helpers_cadquery.py @@ -1,3 +1,4 @@ +import logging import sys if sys.version_info[:2] > (3, 9): import importlib.resources as resources @@ -9,14 +10,6 @@ import numpy as np -debug_trace = False - - -def debugprint(info): - if debug_trace: - print(info) - - def box(width, height, depth): return cq.Workplane("XY").box(width, height, depth) @@ -53,12 +46,12 @@ def translate(shape, vector): def mirror(shape, plane=None): - debugprint('mirror()') + logging.debug("mirror()") return shape.mirror(mirrorPlane=plane) def union(shapes): - debugprint('union()') + logging.debug("union()") shape = None for item in shapes: if item is not None: @@ -70,7 +63,7 @@ def union(shapes): def add(shapes): - debugprint('union()') + logging.debug("union()") shape = None for item in shapes: if item is not None: @@ -82,7 +75,7 @@ def add(shapes): def difference(shape, shapes): - debugprint('difference()') + logging.debug("difference()") for item in shapes: if item is not None: shape = shape.cut(item) @@ -97,7 +90,7 @@ def intersect(shape1, shape2): def face_from_points(points): - # debugprint('face_from_points()') + # logging.debug("face_from_points()") edges = [] num_pnts = len(points) for i in range(len(points)): @@ -116,7 +109,6 @@ def face_from_points(points): def hull_from_points(points): - # debugprint('hull_from_points()') hull_calc = sphull(points) n_faces = len(hull_calc.simplices) @@ -134,7 +126,6 @@ def hull_from_points(points): def hull_from_shapes(shapes, points=None): - # debugprint('hull_from_shapes()') vertices = [] for shape in shapes: verts = shape.vertices() @@ -149,7 +140,6 @@ def hull_from_shapes(shapes, points=None): def tess_hull(shapes, sl_tol=.5, sl_angTol=1): - # debugprint('hull_from_shapes()') vertices = [] solids = [] for wp in shapes: @@ -166,7 +156,7 @@ def tess_hull(shapes, sl_tol=.5, sl_angTol=1): def triangle_hulls(shapes): - debugprint('triangle_hulls()') + logging.debug("triangle_hulls()") hulls = [cq.Workplane('XY')] for i in range(len(shapes) - 2): hulls.append(hull_from_shapes(shapes[i: (i + 3)])) @@ -175,7 +165,7 @@ def triangle_hulls(shapes): def bottom_hull(p, height=0.001): - debugprint("bottom_hull()") + logging.debug("bottom_hull()") shape = None for item in p: vertices = [] @@ -226,18 +216,18 @@ def extrude_poly(outer_poly, inner_polys=None, height=1): # vector=(0,0,1)): def import_file(parts_path: resources.abc.Traversable, fname: str, convexity=None): - print("IMPORTING FROM {}".format(fname)) + logging.info("IMPORTING FROM %s", fname) with resources.as_file(parts_path.joinpath(fname + ".step")) as extracted: return cq.Workplane('XY').add(cq.importers.importShape(cq.exporters.ExportTypes.STEP, extracted)) def export_file(shape, fname): - print("EXPORTING TO {}".format(fname)) + logging.info("EXPORTING TO %s", fname) cq.exporters.export(w=shape, fname=fname + ".step", exportType='STEP') def export_dxf(shape, fname): - print("EXPORTING TO {}".format(fname)) + logging.info("EXPORTING TO %s", fname) cq.exporters.export(w=shape, fname=fname + ".dxf", exportType='DXF') diff --git a/src/dactyl_keyboard/helpers_solid.py b/src/dactyl_keyboard/helpers_solid.py index 5daaa87e6..b82398346 100644 --- a/src/dactyl_keyboard/helpers_solid.py +++ b/src/dactyl_keyboard/helpers_solid.py @@ -1,3 +1,4 @@ +import logging import sys if sys.version_info[:2] > (3, 9): import importlib.resources as resources @@ -6,13 +7,6 @@ import solid as sl -debug_trace = False - - -def debugprint(info): - if debug_trace: - print(info) - def box(width, height, depth): return sl.cube([width, height, depth], center=True) @@ -43,7 +37,7 @@ def translate(shape, vector): def mirror(shape, plane=None): - debugprint('mirror()') + logging.debug("mirror()") planes = { 'XY': [0, 0, 1], 'YX': [0, 0, -1], @@ -56,7 +50,7 @@ def mirror(shape, plane=None): def union(shapes): - debugprint('union()') + logging.debug("union()") shape = None for item in shapes: if item is not None: @@ -68,7 +62,7 @@ def union(shapes): def add(shapes): - debugprint('union()') + logging.debug("union()") shape = None for item in shapes: if item is not None: @@ -80,7 +74,7 @@ def add(shapes): def difference(shape, shapes): - debugprint('difference()') + logging.debug("difference()") for item in shapes: if item is not None: shape -= item @@ -112,7 +106,7 @@ def tess_hull(shapes, sl_tol=.5, sl_angTol=1): def triangle_hulls(shapes): - debugprint('triangle_hulls()') + logging.debug("triangle_hulls()") hulls = [] for i in range(len(shapes) - 2): hulls.append(hull_from_shapes(shapes[i: (i + 3)])) @@ -121,7 +115,7 @@ def triangle_hulls(shapes): def bottom_hull(p, height=0.001): - debugprint("bottom_hull()") + logging.debug("bottom_hull()") shape = None for item in p: proj = sl.projection()(p) @@ -152,16 +146,15 @@ def extrude_poly(outer_poly, inner_polys=None, height=1): def import_file(parts_path: resources.abc.Traversable, fname: str, convexity=2): - print("IMPORTING FROM {}".format(fname)) + logging.info("IMPORTING FROM %s", fname) with resources.as_file(parts_path.joinpath(fname + ".stl")) as extracted: return sl.import_stl(extracted, convexity=convexity) def export_file(shape, fname): - print("EXPORTING TO {}".format(fname)) + logging.info("EXPORTING TO %s", fname) sl.scad_render_to_file(shape, fname + ".scad") def export_dxf(shape, fname): - print("NO DXF EXPORT FOR SOLID".format(fname)) - pass + logging.warn("NO DXF EXPORT FOR SOLID %s", fname) From 4b2a5d685ca664dc98893cdc0b313eab235ca9eb Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 31 Oct 2022 03:02:33 +0000 Subject: [PATCH 10/11] Change install instructions to as python package. --- .github/workflows/release.yaml | 28 -- Makefile | 61 ---- README.md | 193 ++++------ build_docker.bat | 5 - conda.sh | 76 ---- dactyl.sh | 647 --------------------------------- docker/Dockerfile | 21 -- docker/environment.yml | 13 - run.sh | 125 ------- shell.nix | 8 - 10 files changed, 69 insertions(+), 1108 deletions(-) delete mode 100644 .github/workflows/release.yaml delete mode 100644 Makefile delete mode 100644 build_docker.bat delete mode 100755 conda.sh delete mode 100755 dactyl.sh delete mode 100644 docker/Dockerfile delete mode 100644 docker/environment.yml delete mode 100755 run.sh delete mode 100644 shell.nix diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index 2b7e6e8ad..000000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: "Dactyl keyboard" - -on: - push: - branches: - - master - -jobs: - build: - runs-on: ubuntu-latest - timeout-minutes: 180 - name: "Build artifacts and publish Release" - steps: - - name: Checkout - uses: actions/checkout@v2 - - uses: satackey/action-docker-layer-caching@v0.0.11 - continue-on-error: true - - name: Build - run: make build - - name: Release - uses: softprops/action-gh-release@v1 - with: - draft: false - files: things/** - tag_name: v${{ github.run_number }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile deleted file mode 100644 index 453ed5bf5..000000000 --- a/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -#SHELL := /bin/sh - -mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) -current_dir := $(dir $(mkfile_path)) - -source_dir := ${current_dir}"src" -artifact_dir := ${current_dir}"things" -config_dir := ${current_dir}"configs" - -DOCKER_CMD := "docker" -.DEFAULT_GOAL := help - -help: ## Will print this help. - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) -.PHONY: help - -.DELETE_ON_ERROR: - -build: build-container config build-models ## Build everything. Executes the complete pipeline. - @echo "\nAll done" -.PHONY: build - -check-requirements: # private - @if ! command -v ${DOCKER_CMD} %> /dev/null; then \ - echo "Docker executable not found (\`${DOCKER_CMD}\`)." && \ - exit 1; \ - fi -.PHONY: check-requirements - -build-container: check-requirements ## Build docker container. - @echo "\nBuilding container..\n" && \ - ${DOCKER_CMD} build -t dactyl-keyboard -f docker/Dockerfile . && \ - echo "Done" -.PHONY: build-container - -config: check-requirements ## Generate configuration. - @echo "\nGenerate configuration..\n" && \ - ${DOCKER_CMD} run --rm --name DM-config -v ${source_dir}:/app/src -v ${artifact_dir}:/app/things -v ${config_dir}:/app/configs dactyl-keyboard python3 -i generate_configuration.py && \ - echo "Done" -.PHONY: config - -build-models: check-requirements ## Build models. - @echo "\nGenerate configured model..\n" && \ - cd ${current_dir} && \ - ${DOCKER_CMD} run --rm --name DM-run -v ${source_dir}:/app/src -v ${artifact_dir}:/app/things -v ${config_dir}:/app/configs dactyl-keyboard python3 -i dactyl_manuform.py && \ - echo "Done" -.PHONY: config - -build-models: check-requirements ## Build models. - @echo "\nGenerate release models..\n" && \ - cd ${current_dir} && \ - ${DOCKER_CMD} run --rm --name DM-release-build -v ${source_dir}:/app/src -v ${artifact_dir}:/app/things -v ${config_dir}:/app/configs dactyl-keyboard python3 -i model_builder.py && \ - echo "Done" -.PHONY: config - - -shell: check-requirements ## Open an interactive shell inside a container. - @${DOCKER_CMD} run --rm -it --name DM-shell -v ${source_dir}:/app/src -v ${artifact_dir}:/app/things -v ${config_dir}:/app/configs dactyl-keyboard bash && \ - echo "\nBye!" -.PHONY: shell - diff --git a/README.md b/README.md index f554b6aad..d984ec369 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # The Dactyl-ManuForm Keyboard - Python 3 - Cadquery This is a fork of [Dactyl-Manuform](https://github.com/tshort/dactyl-keyboard) by Tom Short, which itself is a fork of [Dactyl](https://github.com/adereth/dactyl-keyboard) by Matthew Adereth, a parameterized, split-hand, concave, columnar, ergonomic keyboard. -While the code structure remains comparable to the original, Clojure and OpenSCAD have been replaced by Python and cadquery/OpenCASCADE. The predecessors were exceptional contributions to the ergo keyboard community by the authors but used a rather esoteric programming language, Clojure, and a relatively inconsistent geometry engine, OpenSCAD. My hope is that by converting the code the community will have an easier time modifying and evolving this design. +While the code structure remains comparable to the original, Clojure and OpenSCAD have been replaced by Python and cadquery/OpenCASCADE. The predecessors were exceptional contributions to the ergo keyboard community by the authors but used a rather esoteric programming language, Clojure, and a relatively inconsistent geometry engine, OpenSCAD. My hope is that by converting the code the community will have an easier time modifying and evolving this design. ## Collaborations and Donations I decided to start accepting donations to help offset some of the prototyping costs and development time. There are 2 ways to contribute to this project: ### Purchase a kit or keyboard from https://www.ergohaven.xyz/ -I am also supported by [ergohaven](https://www.ergohaven.xyz/). The Dactyl-Manuforms are generated from this repository. After working with the owner on additions to support new features we decided to collaborate to evolve the designs they can offer and to support my work. +I am also supported by [ergohaven](https://www.ergohaven.xyz/). The Dactyl-Manuforms are generated from this repository. After working with the owner on additions to support new features we decided to collaborate to evolve the designs they can offer and to support my work. ### Donate directly I opened Liberapay and Ko-fi accounts to accept donations. It is obviously not necessary, but is appreciated. If you do donate and have something specific you really want to see, please let me know. I want to be very open that I can't promise to complete all requests as there are many reasons like engine capabilities and generator construction that can make certain features unfeasible, but I will do my best to improve this repo for you and the ergo keyboard community. @@ -22,47 +22,30 @@ I opened Liberapay and Ko-fi accounts to accept donations. It is obviously not At this point there has been tons of feedback form the community and I greatly appreciate it. While I can only work on this in my free time, I do my best to respond to anyone who posts a comment or question. Feedback on issues or just possible new features is always welcome. ## Updated Geometry Engine, generating STEP files -As part of the effort to create a new engine I converted the code to cadquery/OpenCASCADE. While OpenSCAD has provided an open source 3D engine that is extremely popular, it frankly creates barely passable STLs when you have complex geometry. After being extremely frustrated trying to fix the mesh I realized it is just not a stable engine to create high quality files. OpenCASCADE is extremely powerful but requires extensive detail to operate. cadquery provided an excellent platform to run a stable geometry engine with a simplified API. +As part of the effort to create a new engine I converted the code to cadquery/OpenCASCADE. While OpenSCAD has provided an open source 3D engine that is extremely popular, it frankly creates barely passable STLs when you have complex geometry. After being extremely frustrated trying to fix the mesh I realized it is just not a stable engine to create high quality files. OpenCASCADE is extremely powerful but requires extensive detail to operate. cadquery provided an excellent platform to run a stable geometry engine with a simplified API. ![STEP File in FreeCAD](./resources/FreeCAD_STEP_screen.png) ## Added Features -### Docker Autobuild -![Docker Support!](./resources/docker_containers.png) - -At the excellent suggestion of [martint17r](https://github.com/joshreve/dactyl-keyboard/issues?q=is%3Apr+author%3Amartint17r) -I have added docker configurations with a Windows batch file to assist with getting setup. -If you have -[docker desktop](https://www.docker.com/products/docker-desktop) installed, the batch file will create the -dactyl-keyboard image and 4 containers: - -- DM-run: runs `dactyl_manuform.py`, -- DM-config: runs `generate_configuration.py` -- DM-shell: starts an interactive session to manually run from shell - - tip: run bash after entering to get a better shell environment -- DM-release-build: runs `model_builder.py` to generate a number of keyboard variants - -All apps bindmount the `src` and `things` directory to allow editing in the host and running in the -container. While not exactly hard drive space efficient, this hopefully helps those having issues getting -cadquery running and prevents local Python conflicts. It works well on my computer, but I don't use -docker often, so please let me know if you find any issues with the approach. +### Python package +This project is now a python package, and installs as one. +See below for instructions ### Refactored -Your settings are now created by `generate_configuration.py` or by direct modification of the `run_config.json` file. -This allows you to save `run_config.json` to share your configuration. +Running `dactyl-keyboard --generate-config ` generates a settings file with the default configuration, which can be modified and then used to control the build with `dactyl-keyboard --config `. +This file can of course be shared with others -Additionally, the OpenSCAD/solid python and OpenCASCADE/cadquery versions are merged with separate helper functions +Additionally, the OpenSCAD/solid python and OpenCASCADE/cadquery versions are merged with separate helper functions to decouple the generator from the target library. This also lets me stay sane by only modifying one file for most updates. -Running `dactyl_manuform.py` will automatically load the `run_config.json` file. ### Everyone gets a thumb cluster! Added support of for the thumb clusters in the [carbonfet Dactyl library](https://github.com/carbonfet/dactyl-manuform). These are the "mini" and "carbonfet" thumb clusters. Additional trackball cluster added as well more info to be added after additional build and debug time. -Feel free to try them out with by setting `'thumb_style'` to +Feel free to try them out with by setting `'thumb_style'` to `'DEFAULT'`, `'MINI'`, `'CARBONFET'`, `'MINIDOX'`, `'TRACKBALL_ORBYL'`, and `'TRACKBALL_CJ'`. Trackball features accommodate a [Perixx PERIPRO-303](https://smile.amazon.com/gp/product/B08DD6GQRV/). Others may fit, but this was the target ball diameter for the design. It is a little smaller than a Ploopy to try to fit better in the cluster. @@ -71,21 +54,21 @@ Rendered and actual images to be added in future commits. ### Clippable switch mounting -Tired of hot glue and constraining the socket with "nubs"? I've added an adjustable undercut for using the clips on -the sockets. May require some tweaking and little filing, but I have my DM built without any glue and you can too. +Tired of hot glue and constraining the socket with "nubs"? I've added an adjustable undercut for using the clips on +the sockets. May require some tweaking and little filing, but I have my DM built without any glue and you can too. Just use `plate_style = 'UNDERCUT'`. I've also added an improved local undercut using `plate_style = 'NOTCH'`. ### Kailh Hotswap Added a new switch for hot swap and a way to include any additional geometry in the key plate by use of an imported file. -For hot swap just use `plate_style = 'HS_NOTCH'`, `plate_style = 'HS_HOLE'`, or `plate_style = 'HS_NUB'`. -To import an arbitrary geometry set the `plate_file = None` and `plate_offset = 0.0`. -The file must be .step for OpenCascade / cadquery and .stl for openSCAD / solid python. -The zero reference should be the key center (XY), and the top of the plate (Z). -Plate offset is a Z-axis translation for minor adjustments without modifying the geometry file. +For hot swap just use `plate_style = 'HS_NOTCH'`, `plate_style = 'HS_HOLE'`, or `plate_style = 'HS_NUB'`. +To import an arbitrary geometry set the `plate_file = None` and `plate_offset = 0.0`. +The file must be .step for OpenCascade / cadquery and .stl for openSCAD / solid python. +The zero reference should be the key center (XY), and the top of the plate (Z). +Plate offset is a Z-axis translation for minor adjustments without modifying the geometry file. -**DISCLAIMER: I have not built the hot swap version and cannot speak to the geometry. I found it running around in various places and don't know the origin. At least one user has claimed it works.** +**DISCLAIMER: I have not built the hot swap version and cannot speak to the geometry. I found it running around in various places and don't know the origin. At least one user has claimed it works.** -If you know the origin I would like to credit the originator. If you test it I'd love to know how well it works or if you come up with a better geometry I'm happy to add it. +If you know the origin I would like to credit the originator. If you test it I'd love to know how well it works or if you come up with a better geometry I'm happy to add it. Message me on Reddit u/j_oshreve if you are really stuck. I don't have much time to help, but can answer the occasional question. Also feel free to put in a pull request if you come up with something crafty and want to give others access to it. @@ -114,104 +97,66 @@ Added 3 OLED mounts. Have printed them stand alone with success. I suggest cli ![OLED Clip Mounting](./resources/clip_OLED_mounting.png) ![OLED Clip Plate](./resources/OLED_clip_plate.png) -`oled_mount_type = 'CLIP'` creates an opening to set the OLED with a clip on face plate to hold it down. This is the preferred mounting, but needs the OLED to have a removable connection. +`oled_mount_type = 'CLIP'` creates an opening to set the OLED with a clip on face plate to hold it down. This is the preferred mounting, but needs the OLED to have a removable connection. `oled_mount_type = 'SLIDING'` creates an opening such that you can slide the screen up through the back and into place. Needs a piece of foam or a bit of glue to lock in place. `oled_mount_type = 'UNDERCUT'` creates an opening with an undercut to create whatever custom holder you want. Will not work without additional part creation from the user. -This is a new feature so any feedback is appreciated. If you have issues, message me on Reddit and I will try to help correct them. +This is a new feature so any feedback is appreciated. If you have issues, message me on Reddit and I will try to help correct them. ### Screw Post Locations -You can now have slightly better control of screw mounts. Set to `'screws_offset':'INSIDE'`, `'screws_offset':'OUTSIDE'` or `'screws_offset': 'ORIGINAL'` to control screw locations relative to the wall. +You can now have slightly better control of screw mounts. Set to `'screws_offset':'INSIDE'`, `'screws_offset':'OUTSIDE'` or `'screws_offset': 'ORIGINAL'` to control screw locations relative to the wall. ![Inside Screws](./resources/inside_screw_posts.png) I am planning to deprecate outside and original at some point. I don't see the need to carry all of them and the hidden look the best. If you disagree feel free to let me know and I may keep a second form. ## Status / Future -This is now a bit of a monster of many minds and yet continues to bear fruit. +This is now a bit of a monster of many minds and yet continues to bear fruit. I plan to continue to use this code to try new geometries and features to share for the foreseeable future. ## Installation -There are three different environments in which you can run this application. Depending on which you choose, the installation process will vary. - -- [Docker Environment](#docker-environment-installation) -- [Conda Environment](#conda-environment-installation) -- [Python Environment](#python-environment-installation) - -### Docker Environment Installation - -Running the application with Docker is the most convenient way to do so. In addition to a straightforward installation, this also allows you to generate models in the background without having to keep a shell open. - -*Note:* If you are using Windows, see [Docker Autobuild](#docker-autobuild). - -Before you proceed, ensure you have installed [Docker](https://www.docker.com/) and the `docker` command is available from your terminal. - -There are two tools you can use to help manage the Docker containers associated with this project. - -#### Make - -If you prefer, you can use `make` to manage the containers. Type `make help` to see the available commands. - -#### Bash Script - -The `dactyl.sh` bash script provides a CLI to manage the containers. Type `./dactyl.sh --help` to see all CLI options. - -In addition to the CLI you can run `./dactyl.sh` without any arguments to use an interactive menu. - -Upon running the script, you will be prompted to build the dactyl-keyboard Docker image. - -Once the image is built, you can choose which containers to run on an as-needed basis. In general, you can start, stop, rebuild, inspect, and remove the containers via the CLI/Menu. - -You can also remove all of the Docker artifacts by running the included uninstaller. - -*Tip:* Run `./dactyl.sh shell --session` to jump into a bash session inside of the shell container. - -### Conda Environment Installation - -After the Docker installation, Anaconda is the next best option. Before you begin, ensure you have installed [Anaconda](https://docs.anaconda.com/anaconda/install/index.html) and the `conda` command is available from your terminal. - -You can install all of the dependencies by hand, but you can automate the install by running the bash script `./conda.sh`. This will create a python 3.7 environment named `dactyl-keyboard` and install all of the required dependencies. - -If you would like to install into a conda environment manually, check the bash script to see all of the required commands. - -If you would like to remove the conda artifacts, run `./conda.sh --uninstall`. +This project is now a python package, and installs as one: +``` +pip install "dactyl-keyboard @ git+https://github.com/joshreve/dactyl-keyboard" +``` +(see the official [pip support for version control systems](https://pip.pypa.io/en/stable/topics/vcs-support/) for more options) -### Python Environment Installation +The engines required to create output files are optional dependencies: + - cadquery: `"pip install "dactyl-keyboard[cadquery] @ git+https://github.com/joshreve/dactyl-keyboard"` + - solid/openSCAD: `"pip install "dactyl-keyboard[solid] @ git+https://github.com/joshreve/dactyl-keyboard"` -You can install the application in a regular python environment, but it is not recommended. You will not be able to take advantage of the updated geometry generated by the CadQuery engine, as this is only available via the Docker/Anaconda installation. + Specifying multiple options requires separating them with a comma: `pip install "dactyl-keyboard[cadquery, solid] @ ..."` -**Setting up the Python environment - NEW** -* [Install Python 3.X](https://www.python.org/downloads/release/python-385/) or use your [favorite distro / platform (Anaconda)](https://www.anaconda.com/products/individual) -* It is advisable, but not necessary, to setup a virtual environment to prevent package/library incompatibility -* [Install Numpy](https://pypi.org/project/numpy/), easiest method is `pip install numpy` or `pip3 install numpy` on linux. -* [Install dataclasses_json](https://pypi.org/project/dataclasses_json/), easiest method is `pip install dataclasses-json` or `pip3 install dataclasses-json` on linux. +To install you will need either [python](https://www.python.org/downloads/)+[pip](https://pip.pypa.io/en/stable/installation/) or a [conda environment](https://docs.anaconda.com/anaconda/install/index.html) -**cadquery install** -* [Install scipy](https://pypi.org/project/scipy/), easiest method is `pip install scipy` or `pip3 install scipy` on linux. -* [Install cadquery](https://github.com/CadQuery/cadquery), many options (see link), but easiest method is `conda install -c conda-forge -c cadquery cadquery=2`. Props to the creators/maintainers, this has the power of Open CASCADE with nearing the simplicity of OpenSCAD. +For python+pip it is recommended you follow standard practice and use a [virtual environment](https://packaging.python.org/en/latest/tutorials/installing-packages/#creating-and-using-virtual-environments). -**OpenSCAD install** -* [Install SolidPython](https://pypi.org/project/solidpython/), easiest method is `pip install solidpython` or `pip3 install solidpython` on linux. -* [Install OpenSCAD](http://www.openscad.org/) +For conda, besides installing with pip you can also add the required entries to an `environment.yml` file, as so: +```yaml +name: ... +channels: +dependencies: + - python>=3.8 + - pip: + - "dactyl-keyboard @ git+https://github.com/joshreve/dactyl-keyboard" +``` ## Generating the design **Generating the design - UPDATED** -* ~~Run `python dactyl_manuform_cadquery.py` or `python3 dactyl_manuform_cadquery.py`~~ -* ~~Run `python dactyl_manuform.py` or `python3 dactyl_manuform.py`~~ -* Run `generate_configuration.py` or directly edit `run_config.json` to configure the design -* Run `dactyl_manuform.py` to create the geometry (ENGINE variable in run determines method) -* This will regenerate the `things/` files (or in subdirectory if defined in config) +* If desired, run `dactyl-keyboard --generate-config ` and directly edit the file to configure the design. +* Run `dactyl-keyboard` (or `dactyl-keyboard --config `) to create the geometry (ENGINE variable in run determines method) +* This will regenerate a `things/` directory with files (or in subdirectory if defined in config) * `*left.*` * `*right.*` * `*plate.*` * `*oled_clip.*` (if applicable) * `*oled_clip_test.*` (if applicable) -* Use OpenSCAD to open a `.scad` file -* Use FreeCAD or other application to open a `.step` file +* Use [OpenSCAD](https://openscad.org/) to open a `.scad` file +* Use [FreeCAD](https://www.freecad.org/) or other application to open a `.step` file * Make changes to design, repeat run step * When done, use OpenSCAD or FreeCAD to export STL files @@ -220,9 +165,9 @@ You can install the application in a regular python environment, but it is not r ## Origin ![Imgur](http://i.imgur.com/LdjEhrR.jpg) -The main change is that the thumb cluster was adapted from the [ManuForm keyboard](https://github.com/jeffgran/ManuForm) ([geekhack](https://geekhack.org/index.php?topic=46015.0)). The walls were changed to just drop to the floor. The keyboard is paramaterized to allow adjusting the following: +The main change is that the thumb cluster was adapted from the [ManuForm keyboard](https://github.com/jeffgran/ManuForm) ([geekhack](https://geekhack.org/index.php?topic=46015.0)). The walls were changed to just drop to the floor. The keyboard is paramaterized to allow adjusting the following: -* Rows: 4 - 6 +* Rows: 4 - 6 * Columns: 5 and up * Row curvature * Column curvature @@ -251,33 +196,33 @@ Here are materials tshort used for wiring. * [1N4148 diodes](https://www.amazon.com/gp/product/B00LQPY0Y0) * [Female RJ-9 connectors](https://www.amazon.com/gp/product/B01HU7BVDU/) -I wired one half using the traditional approach of using the legs of a diode to form the row connections. +I wired one half using the traditional approach of using the legs of a diode to form the row connections. (I'm not great at soldering, so this was challenging for me.) -For this side, I used magnet wire to wire columns. That worked okay. +For this side, I used magnet wire to wire columns. That worked okay. The magnet wire is small enough, it wants to move around, and it's hard to tell if you have a good connection. ![Imgur](http://i.imgur.com/7kPvSgg.jpg) -For another half, I used stripboard for the row connections. -This allowed me to presolder all of the diodes. -Then, I hot-glued this in place and finished the soldering of the other diode ends. -I like this approach quite a lot. -Connections for the diodes were much easier with one end fixed down. -On this half, I also used copper tape to connect columns. -This worked a bit better than the magnet wire for me. -For a future version, I may try just bare tinned copper wire for columns (something like #20). +For another half, I used stripboard for the row connections. +This allowed me to presolder all of the diodes. +Then, I hot-glued this in place and finished the soldering of the other diode ends. +I like this approach quite a lot. +Connections for the diodes were much easier with one end fixed down. +On this half, I also used copper tape to connect columns. +This worked a bit better than the magnet wire for me. +For a future version, I may try just bare tinned copper wire for columns (something like #20). With the stripboard, it's pretty easy keeping row and column connections separate. ![Imgur](http://i.imgur.com/JOm5ElP.jpg) Note that a telephone handset cable has leads that are reversed, so take this into account when connecting these leads to the controller. -The 3D printed part is the main keyboard. -You can attach a bottom plate with screws. -The case has holes for heat-set inserts designed to hold 3- to 6-mm long M3 screws. -Then, I used wafer-head screws to connect a bottom plate. -If wires aren't dangling, a bottom plate may not be needed. -You need something on the bottom to keep the keyboard from sliding around. +The 3D printed part is the main keyboard. +You can attach a bottom plate with screws. +The case has holes for heat-set inserts designed to hold 3- to 6-mm long M3 screws. +Then, I used wafer-head screws to connect a bottom plate. +If wires aren't dangling, a bottom plate may not be needed. +You need something on the bottom to keep the keyboard from sliding around. Without a plate, you could use a rubber pad, or you could dip the bottom of the keyboard in PlastiDip. For more photos of the first complete wiring of v0.4, see [Imgur](http://imgur.com/a/v9eIO). @@ -297,9 +242,9 @@ NOTE: you also make sure the firmware is set up correctly (ex: change row pins w ### Firmware -Firmware goes hand in hand with how you wire the circuit. -I adapted the QMK firmware [here](https://github.com/tshort/qmk_firmware/tree/master/keyboards/dactyl-manuform). -This allows each side to work separately or together. +Firmware goes hand in hand with how you wire the circuit. +I adapted the QMK firmware [here](https://github.com/tshort/qmk_firmware/tree/master/keyboards/dactyl-manuform). +This allows each side to work separately or together. This site also shows connections for the Arduino Pro Micro controllers. ## License diff --git a/build_docker.bat b/build_docker.bat deleted file mode 100644 index 6df8be653..000000000 --- a/build_docker.bat +++ /dev/null @@ -1,5 +0,0 @@ -docker build -t dactyl-keyboard -f docker/Dockerfile . -docker run --name DM-run -d -v "%cd%/:/app" dactyl-keyboard python3 -i dactyl_manuform.py -docker run --name DM-config -d -v "%cd%/:/app" dactyl-keyboard python3 -i generate_configuration.py -docker run --name DM-release-build -d -v "%cd%/:/app" dactyl-keyboard python3 -i model_builder.py -docker run --name DM-shell -d -ti -v "%cd%/:/app" dactyl-keyboard diff --git a/conda.sh b/conda.sh deleted file mode 100755 index 16b3f58ce..000000000 --- a/conda.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -# exit on any errors -set -e - -function inform() { echo -e "\n[INFO] $@\n"; } -function warn() { echo -e "\n[WARN] $@\n"; } -function error() { echo -e "\n[ERROR] $@\n"; } - -# exit unless user responds with yes -function confirmContinue() { - while true; do - read -p "$@ [y/n]" yn - case $yn in - [Yy]* ) break;; - [Nn]* ) exit 0;; - * ) error "Please answer yes or no.";; - esac - done -} - -if ! which conda &> /dev/null; then - error "Conda not found.\n\nVisit https://docs.anaconda.com/anaconda/install/index.html for more info." - exit 1 -fi - -# Enable "conda activate" and "conda deactivate" -eval "$(conda shell.bash hook)" - -envName=dactyl-keyboard - -if [ "$1" = "--uninstall" ]; then - confirmContinue "Would you like to remove the conda environment $envName?" - conda deactivate - conda env remove -n $envName - inform "Conda environment removed!\n\n\tRun \"conda deactivate\" to ensure the environment has been properly deactivated." - - exit -fi - -if conda info --envs | grep $envName &> /dev/null; then - warn "Conda env \"$envName\" already exists." - confirmContinue "Do you want to overwrite it?" -fi - -inform "Creating conda environment: $envName..." - -conda create --name=$envName python=3.7 -y - -conda activate $envName - -inform "Installing CadQuery..." - -conda install -c conda-forge -c cadquery cadquery=2 -y - -inform "Installing dataclasses-json..." - -pip install dataclasses-json - -inform "Installing numpy..." - -pip install numpy - -inform "Installing scipy..." - -pip install scipy - -inform "Installing solidpython..." - -pip install solidpython - -inform "Updating conda dependencies..." - -conda update --all -y - -inform "Success!\n\n\tRun \"conda activate $envName\" to activate the environment." diff --git a/dactyl.sh b/dactyl.sh deleted file mode 100755 index 43bb553be..000000000 --- a/dactyl.sh +++ /dev/null @@ -1,647 +0,0 @@ -#!/bin/bash - -# ******************* # -# ******************* setup ******************* # -# ******************* # - -# exit if any errors are thrown -set -e - -container="" -# bad practice: - # container variable names MUST match - # the positional name {positional}Container -shellContainer=DM-shell -runContainer=DM-run -configContainer=DM-config -releaseBuildContainer=DM-release-build -containers=("$shellContainer" "$configContainer" "$runContainer" "$releaseBuildContainer") - -imageName=dactyl-keyboard -srcBind="$(pwd)/src:/app/src" -thingsBind="$(pwd)/things:/app/things" - -# force exit on interrupt in case we are in a menu -function catch_interrupt() { exit 1; } -trap catch_interrupt SIGINT -trap catch_interrupt SIGTSTP - -# ******************* # -# ******************* functions ******************* # -# ******************* # - -################################ -# General Helpers -################################ - -function inform() { - echo -e "\n[INFO] $@\n" -} - -function warn() { - echo -e "\n[WARN] $@\n" -} - -function error() { - echo -e "\n[ERROR] $@\n" -} - -function exitUnexpectedPositionalArgs() { - error "Unexpected positionnal argument.\n\n\tAlready had: $positional\n\n\tAnd then got: $1" - exit 1 -} - -function exitUnexpectedFlags() { - error "One or more flags are invalid:\n\n\tPositional: $positional\n\n\tFlags: $flags" - exit 1 -} - -################################ -# Interactive Menu -################################ - -# https://unix.stackexchange.com/questions/146570/arrow-key-enter-menu -# Arguments: -# array of options -# -# Return value: -# selected index (0 for opt1, 1 for opt2 ...) - -function menu { - local header="\n[Dactyl Manuform]" - if [ $container ]; then - header+=" -- $container" - fi - header+="\n\nPlease choose an option:\n\n" - printf "$header" - options=("$@") - - # helpers for terminal print control and key input - ESC=$(printf "\033") - cursor_blink_on() { printf "$ESC[?25h"; } - cursor_blink_off() { printf "$ESC[?25l"; } - cursor_to() { printf "$ESC[$1;${2:-1}H"; } - print_option() { printf "\t $1 "; } - print_selected() { printf "\t${COLOR_GREEN} $ESC[7m $1 $ESC[27m${NC}"; } - get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } - key_input() { - local key - # read 3 characters, 1 at a time - for (( i=0; i < 3; ++i)); do - read -s -n1 input 2>/dev/null >&2 - # concatenate chars together - key+="$input" - # if a number is encountered, echo it back - if [[ $input =~ ^[1-9]$ ]]; then - echo $input; return; - # if enter, early return - elif [[ $input = "" ]]; then - echo enter; return; - # if we encounter something other than [1-9] or "" or the escape sequence - # then consider it an invalid input and exit without echoing back - elif [[ ! $input = $ESC && i -eq 0 ]]; then - return - fi - done - - if [[ $key = $ESC[A ]]; then echo up; fi; - if [[ $key = $ESC[B ]]; then echo down; fi; - } - function cursorUp() { printf "$ESC[A"; } - function clearRow() { printf "$ESC[2K\r"; } - function eraseMenu() { - cursor_to $lastrow - clearRow - numHeaderRows=$(printf "$header" | wc -l) - numOptions=${#options[@]} - numRows=$(($numHeaderRows + $numOptions)) - for ((i=0; i<$numRows; ++i)); do - cursorUp; clearRow; - done - } - - # initially print empty new lines (scroll down if at bottom of screen) - for opt in "${options[@]}"; do printf "\n"; done - - # determine current screen position for overwriting the options - local lastrow=`get_cursor_row` - local startrow=$(($lastrow - $#)) - local selected=0 - - # ensure cursor and input echoing back on upon a ctrl+c during read -s - trap "cursor_blink_on; stty echo; printf '\n'; exit" 2 - cursor_blink_off - - while true; do - # print options by overwriting the last lines - local idx=0 - for opt in "${options[@]}"; do - cursor_to $(($startrow + $idx)) - # add an index to the option - local label="$(($idx + 1)). $opt" - if [ $idx -eq $selected ]; then - print_selected "$label" - else - print_option "$label" - fi - ((idx++)) - done - - # user key control - input=$(key_input) - - case $input in - enter) break;; - [1-9]) - # If a digit is encountered, consider it a selection (if within range) - if [ $input -lt $(($# + 1)) ]; then - selected=$(($input - 1)) - break - fi - ;; - up) ((selected--)); - if [ $selected -lt 0 ]; then selected=$(($# - 1)); fi;; - down) ((selected++)); - if [ $selected -ge $# ]; then selected=0; fi;; - esac - done - - eraseMenu - cursor_blink_on - - return $selected -} - - -################################ -# Setup helpers -################################ - -function showHelpAndExit() { -cat << _end_of_text -[Dactyl Manuform] - -A bash CLI to manage Docker artifacts for the Dactyl Keyboard project. - -Run the script without any flags to use the interactive menu. - -Usage: - ./dactyl.sh - ./dactyl.sh [-h | --help | --uninstall] - ./dactyl.sh image [--build | --inspect | --remove] - ./dactyl.sh (config|run|releaseBuild) [--build | --inspect | --start | --stop | --remove] - ./dactyl.sh shell [--build | --inspect | --session | --start | --stop | --remove] - -Options: - positional Target the image or a particular container (shell | config | run | releaseBuild) - -h --help Show this screen. - --uninstall Remove all Docker artifacts. - --build Build (or rebuild) and run the target container. - --inspect Show "docker inspect" results for the target container. - --start Start or restart the target container. - --stop Stop the target container. - --remove Remove the target container. - --session Start a shell session in the shell container. -_end_of_text -exit -} - -# error on any unexpected flags or more than one positional argument -function processArgs() { - while [[ $# -gt 0 ]] - do - key="$1" - - case $key in - --build|--remove|--inspect|--session|--start|--stop) - if [[ $flags ]]; then - flags+=" $key" - else - flags=$key - fi - shift;; - -h|--help) showHelpAndExit;; - --uninstall) handleUninstall;; - *) - # all valid flags should have already been captured above - if [[ $key == -* ]]; then - error "Unknwon flag: $key" - exit 1 - # if we already have a positional argument we shouldn't get another - elif [[ "$positional" ]]; then - exitUnexpectedPositionalArgs $key - exit 1 - # the totality of accepted positional arguments - elif [[ "$key" =~ ^(image|shell|config|run|releaseBuild)$ ]]; then - positional="$key" - if [[ ! $key = image ]]; then - key+="Container" - container=$(echo "${!key}") - fi - shift - else - error "Unknown positional arg: \"$key\"" - exit 1 - fi - ;; - esac - done -} - -# installing docker is out of scope -# so if it isn't found, inform user and exit -function checkDocker() { - if ! which docker &> /dev/null; then - error "Docker is not installed.\n\n\tPlease visit https://www.docker.com/products/docker-desktop for more information." - exit 1 - fi - - if ! docker image list &> /dev/null; then - error "Docker is not running. Please start docker and try again." - exit 1; - fi -} - -# exit unless user responds with yes -function confirmContinue() { - while true; do - read -p "$@ [y/n]" yn - case $yn in - [Yy]* ) break;; - [Nn]* ) exit 0;; - * ) error "Please answer yes or no.";; - esac - done -} - -################################ -# Image Logic -################################ - -function imageExists() { - docker image list | grep "$imageName" &> /dev/null -} - -function buildImage() { - inform "Building docker image: $imageName..." - docker build -t dactyl-keyboard -f docker/Dockerfile . -} - -function promptBuildImageIfNotExists() { - if ! imageExists; then - inform "Docker image not found: $imageName" - confirmContinue "Would you like to build it now?" - buildImage - fi -} - -# image will always exist if we are here -function handleRebuildImage() { - warn "Docker image already exists: $imageName" - confirmContinue "Would you like to overwrite it?" - buildImage -} - -function removeImage() { - inform "Removing docker image: $imageName..." - docker image rm $imageName -} - -function handleRemoveImage() { - warn "This will remove docker image: $imageName" - confirmContinue "Would you like to continue?" - removeImage -} - -function handleInspectImage() { - inform "Checking status of image: $imageName" - docker image inspect $imageName -} - -function handleImageMenu() { - local check="Check Image Status" - local build="Rebuild Image" - local remove="Remove Image" - local mainMenu="Main Menu" - local end="Exit" - options=("$check" "$build" "$remove" "$mainMenu" "$end") - # execute in subshell so exit code doesn't exit the script - (menu "${options[@]}") && true - result="${options[$?]}" - - case $result in - $check) handleInspectImage;; - $build) handleRebuildImage;; - $remove) handleRemoveImage;; - $mainMenu) handleMainMenu;; - *) exit;; - esac -} - -# if we made it this far, image is confirmed to exist -function handleImageCLI() { - if [[ ! "$flags" ]]; then - handleImageMenu - elif [[ "$flags" =~ ^.*(--inspect).*$ ]]; then - handleInspectImage - elif [[ "$flags" =~ ^.*(--build).*$ ]]; then - handleRebuildImage - elif [[ "$flags" =~ ^.*(--remove).*$ ]]; then - handleRemoveImage - else - exitUnexpectedFlags - fi -} - -################################ -# Container Helpers -################################ - -function containerExists() { - docker container list -a | grep "$container" &> /dev/null -} - -function containerIsRunning() { - if ! containerExists "$container"; then - return 1 - fi - - docker container inspect $container | grep '"Status": "running",' &> /dev/null -} - -function isShell() { - test $container = $shellContainer -} - -function promptIfShell() { - if isShell; then - promptStartShellSession - fi -} - -function buildContainerAndExecutePythonScript() { - docker run --name $container -d -v "$srcBind" -v "$thingsBind" $imageName python3 -i $1 -} - -function buildContainer() { - inform "Building docker container: $container..." - case $container in - $shellContainer) - docker run --name $shellContainer -d -it -v "$srcBind" -v "$thingsBind" $imageName - ;; - $runContainer) - buildContainerAndExecutePythonScript dactyl_manuform.py - ;; - $configContainer) - buildContainerAndExecutePythonScript generate_configuration.py - ;; - $releaseBuildContainer) - buildContainerAndExecutePythonScript model_builder.py - ;; - *) - error "Unexpected exception. Containier: $container" - exit 1;; - esac - echo -} - -function buildContainerIfNotExists() { - if ! containerExists; then - warn "Container not found: $container" - confirmContinue "Would you like to build it now?" - buildContainer - fi -} - -function startContainer() { - docker container start $container &> /dev/null -} - -function promptStartContainerIfNotRunning() { - buildContainerIfNotExists - if ! containerIsRunning; then - warn "Container is not running: $container" - confirmContinue "Would you like to start it now?" - startContainer - fi -} - -function startContainerIfNotRunning() { - buildContainerIfNotExists - if ! containerIsRunning; then - inform "Starting docker container: $container" - startContainer - fi -} - -function startContainerOrAlert() { - if containerIsRunning; then - inform "Container is already running: $shellContainer" - else - startContainerIfNotRunning - fi - - if isShell; then - promptStartShellSession - fi -} - -function stopContainer() { - if containerIsRunning; then - inform "Stopping docker container: $container..." - docker container stop $container &> /dev/null - docker container wait $container &> /dev/null - fi -} - -function handleStopContainer() { - if ! containerExists; then - warn "Docker container does not exist: $container" - elif ! containerIsRunning; then - inform "Container is already stopped: $container" - else - stopContainer - fi -} - -function removeContainer() { - if containerExists; then - stopContainer - inform "Removing docker container: $container..." - docker container rm $container &> /dev/null - fi -} - -function inspectContainer() { - if ! containerExists; then - inform "Container \"$container\" does not exist." - confirmContinue "Would you like to build it?" - buildContainer - fi - - docker container inspect $container -} - -function handleBuildContainer() { - if containerExists; then - warn "Container already exists: $container" - confirmContinue "Would you like to overwrite it?" - removeContainer - fi - - buildContainer - promptIfShell -} - -function handleContainerMenu() { - local build="Rebuild $container Container" - local start="Start $container Container" - local stop="Stop $container Container" - local remove="Remove $container Container" - local inspect="Inspect $container Container" - local session="Start $container Session" - local main="Main Menu" - local end="Exit" - - if ! containerExists; then - build="Build and run $container Container" - options=("$build" "$main" "$end") - elif containerIsRunning; then - options=("$session" "$inspect" "$build" "$stop" "$remove" "$main" "$end") - if ! isShell; then - unset options[0] - fi - else - options=("$inspect" "$build" "$start" "$remove" "$main" "$end") - fi - - # execute in subshell so exit code doesn't exit the script - (menu "${options[@]}") && true - result="${options[$?]}" - - case $result in - $build) handleBuildContainer;; - $start) startContainerOrAlert;; - $stop) handleStopContainer;; - $remove) removeContainer;; - $inspect) inspectContainer;; - $main) handleMainMenu;; - *) - if isShell && [[ $session = $result ]]; then - startShellSession - fi - exit - ;; - esac -} - -function handleContainerCLI() { - if [[ ! "$flags" ]]; then - handleContainerMenu - elif [[ "$flags" =~ ^.*(--inspect).*$ ]]; then - inspectContainer - elif [[ "$flags" =~ ^.*(--build).*$ ]]; then - handleBuildContainer - elif [[ "$flags" =~ ^.*(--session).*$ ]] && isShell; then - startShellSession - elif [[ "$flags" =~ ^.*(--start).*$ ]]; then - startContainerOrAlert - elif [[ "$flags" =~ ^.*(--stop).*$ ]]; then - handleStopContainer - elif [[ "$flags" =~ ^.*(--remove).*$ ]]; then - removeContainer - else - exitUnexpectedFlags - fi -} - -################################ -# Shell Specific Logic -################################ - -function startShellSession() { - promptStartContainerIfNotRunning - inform "Starting session in container: $shellContainer\n\n\tType \"exit\" to terminate the session." - docker exec -it $shellContainer /bin/bash -} - -function promptStartShellSession() { - confirmContinue "Would you like to start a shell session?" - startShellSession -} - -################################ -# Uninstaller -################################ - -function handleUninstall() { - warn "This will remove all containers and images." - confirmContinue "Are you sure you want to continue?" - for currentContainer in "${containers[@]}"; do - container="$currentContainer" - removeContainer - done - - removeImage - exit -} - -################################ -# Main Menu Logic -################################ - -function handleMainMenu() { - container="" - - local imageOpt="Manage Docker Image" - local shellOpt="$shellContainer Container" - local configOpt="$configContainer Container" - local releaseOpt="$releaseBuildContainer Container" - local runOpt="$runContainer Container" - local uninstallOpt="Uninstall" - local help="Show Help" - local end="Exit" - - options=("$imageOpt" "$shellOpt" "$configOpt" "$runOpt" "$releaseOpt" "$help" "$uninstallOpt" "$end") - - # execute in subshell so exit code doesn't exit the script - (menu "${options[@]}") && true - result="${options[$?]}" - - case $result in - $help) showHelpAndExit;; - $imageOpt) handleImageMenu;; - $uninstallOpt) handleUninstall;; - $shellOpt|$configOpt|$runOpt|$releaseOpt) - # remove " Container" and set as currentn container - container=$(echo "${result/ Container/}") - handleContainerMenu - ;; - * ) exit;; - esac -} - -# ******************* # -# ******************* main ******************* # -# ******************* # - -# figure out why we're running the script -processArgs $@ - -# exit if `docker` command not available -checkDocker - -# make sure the base image has been built -promptBuildImageIfNotExists - -# main switchboard to act depending on which positionl arg was passed - -if [[ "$positional" ]]; then - case $positional in - image) handleImageCLI;; - shell|config|run|releaseBuild) handleContainerCLI;; - *) exitUnexpectedPositionalArgs;; - esac -else - handleMainMenu -fi diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index ab7d85bba..000000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM continuumio/miniconda3 - -RUN apt-get update && \ - apt-get install -y libgl1-mesa-glx gcc bash && \ - rm -rf /var/lib/apt/lists/* - - -COPY ./docker/environment.yml . - -RUN conda env create -f environment.yml - -RUN conda init bash - -SHELL ["bash", "-lc"] - -RUN conda activate myenv - -RUN echo "source activate myenv" >> ~/.bashrc -ENV PATH /opt/conda/envs/myenv/bin:$PATH - -WORKDIR /app/src diff --git a/docker/environment.yml b/docker/environment.yml deleted file mode 100644 index 864fa555b..000000000 --- a/docker/environment.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: myenv -channels: - - cadquery - - conda-forge - - defaults -dependencies: - - python>=3.6 - - cadquery=2 - - pip - - numpy - - scipy - - pip: - - solidpython diff --git a/run.sh b/run.sh deleted file mode 100755 index ad6a9227d..000000000 --- a/run.sh +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/bash - -cd "${0%/*}" || exit 1 - - - -# set the default Docker image tag to dactyl-keyboard -IMAGE_TAG="dactyl-keyboard" - -# by default, don't rebuild the image -REBUILD=false; - -# leave config empty to use default values -CONFIG="" - - -# check for command line flags -while test $# -gt 0; do - case "$1" in - -r|--rebuild) - REBUILD=true - shift - ;; - -t|--tag) - if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then - IMAGE_TAG=$2 - shift 2 - else - echo "Error: Argument for $1 is missing" >&2 - exit 1 - fi - ;; - -c|--config) - CONFIG=$2 - shift 2 - ;; - -*|--*) - echo "Error: Unknown flag $1" >&2 - exit 1 - ;; - *) - COMMAND=$1 - shift; - ;; - esac -done - - - -case $COMMAND in - help) - echo "Dactyl-Manuform Keyboard Generator" - echo "" - echo "Use this tool to configure and generate files for building a keyboard. All" - echo "commands will be run in a Docker contianer, which will be built if it does" - echo "not already exist." - echo "" - echo "" - echo "Usage:" - echo " run [-r] [-i ] [-c ] " - echo "" - echo "Available Commands:" - echo " help Show this help" - echo " build Rebuild the docker image" - echo " release Run model_builder.py" - echo " generate Output the keyboard files to the './things' directory" - echo " configure Generate a configuration file with default values. The config" - echo " file will be saved to configs/.json. If the" - echo " -c flag is not set, the defailt config_name will be used." - echo "" - echo "Flags:" - echo " -c Set the configuration file to use. This should be the name of the file" - echo " only, without a file extension, and it is relative to the './configs'" - echo " directory. For example, '-c my-custom-dm' will refer to a file located" - echo " at './configs/my-custom-dm.json'" - echo " -r Rebuild the docker image" - echo " -t The tag that should be applied to the docker image" - exit 0 - ;; - build) - docker build -t ${IMAGE_TAG} -f docker/Dockerfile . - exit 0 - ;; - generate) - SCRIPT=dactyl_manuform.py - ;; - configure) - SCRIPT=generate_configuration.py - ;; - release) - SCRIPT=model_builder.py - ;; - *) - echo "Invalid command. Try 'run help'" - exit 1 -esac - - -# get the image ID, and save the return code so we'll know if the image exists -IMAGE_ID=$(docker inspect --type=image --format={{.Id}} ${IMAGE_TAG}) -INSPECT_RETURN_CODE=$? - -# if we were specifically told to rebuild, or if the image doesn't exists, then build the docker image -if $REBUILD || [ $INSPECT_RETURN_CODE -ne 0 ]; then - docker build -t ${IMAGE_TAG} -f docker/Dockerfile . -fi - - -# if a config file was specified, set the command line argument for the python script -if [[ ! -z $CONFIG ]]; then - CONFIG_OPTION="--config=${CONFIG}" -fi - -# run the command in a temporary container -docker run --name dm-run -d --rm -v "`pwd`/src:/app/src" -v "`pwd`/things:/app/things" -v "`pwd`/configs:/app/configs" ${IMAGE_TAG} python3 $SCRIPT $CONFIG_OPTION > /dev/null 2>&1 - -# show progress indicator while until dm-run container completes -while $(docker inspect --format={{.Id}} dm-run > /dev/null 2>&1); do - echo -n "." - sleep 1.5 -done - -echo "" -echo "Dactyl-Manuform '${COMMAND}' is complete!" -echo "" \ No newline at end of file diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 6548e72ae..000000000 --- a/shell.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ pkgs ? import {} }: - -pkgs.mkShell { - buildInputs = [ - pkgs.cmake - pkgs.cq-editor - ]; -} From 9fb9ad54e57b9986166f94bb84bba94e4e2e73c7 Mon Sep 17 00:00:00 2001 From: "Stephen A. Imhoff" Date: Mon, 31 Oct 2022 04:36:17 +0000 Subject: [PATCH 11/11] Re-enable custom plates. --- src/dactyl_keyboard/dactyl_manuform.py | 6 +++++- src/dactyl_keyboard/helpers_cadquery.py | 10 ++++++++-- src/dactyl_keyboard/helpers_solid.py | 10 ++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/dactyl_keyboard/dactyl_manuform.py b/src/dactyl_keyboard/dactyl_manuform.py index 57ea94dc5..9d4003c83 100644 --- a/src/dactyl_keyboard/dactyl_manuform.py +++ b/src/dactyl_keyboard/dactyl_manuform.py @@ -251,7 +251,11 @@ def single_plate(cylinder_segments=100, side="right"): plate = difference(plate, [undercut]) if plate_file is not None: - socket = import_file(parts_path, plate_file) + plate_path = pathlib.Path(plate_file) + if plate_path.exists(): + socket = import_file(plate_path) + else: + socket = import_resource(parts_path, plate_file) socket = translate(socket, [0, 0, plate_thickness + plate_offset]) plate = union([plate, socket]) diff --git a/src/dactyl_keyboard/helpers_cadquery.py b/src/dactyl_keyboard/helpers_cadquery.py index 1db459a83..03b3c4131 100644 --- a/src/dactyl_keyboard/helpers_cadquery.py +++ b/src/dactyl_keyboard/helpers_cadquery.py @@ -1,4 +1,5 @@ import logging +import pathlib import sys if sys.version_info[:2] > (3, 9): import importlib.resources as resources @@ -215,10 +216,15 @@ def extrude_poly(outer_poly, inner_polys=None, height=1): # vector=(0,0,1)): cq.Solid.extrudeLinear(outerWire=outer_wires, innerWires=inner_wires, vecNormal=cq.Vector(0, 0, height))) -def import_file(parts_path: resources.abc.Traversable, fname: str, convexity=None): +def import_resource(parts_path: resources.abc.Traversable, fname: str, convexity=None): logging.info("IMPORTING FROM %s", fname) with resources.as_file(parts_path.joinpath(fname + ".step")) as extracted: - return cq.Workplane('XY').add(cq.importers.importShape(cq.exporters.ExportTypes.STEP, extracted)) + return cq.Workplane('XY').add(cq.importers.importShape(cq.exporters.ExportTypes.STEP, str(extracted))) + + +def import_file(fname: pathlib.Path, convexity=None): + logging.info("IMPORTING FROM %s", fname) + return cq.Workplane('XY').add(cq.importers.importShape(cq.exporters.ExportTypes.STEP, str(fname))) def export_file(shape, fname): diff --git a/src/dactyl_keyboard/helpers_solid.py b/src/dactyl_keyboard/helpers_solid.py index b82398346..0a0327173 100644 --- a/src/dactyl_keyboard/helpers_solid.py +++ b/src/dactyl_keyboard/helpers_solid.py @@ -1,4 +1,5 @@ import logging +import pathlib import sys if sys.version_info[:2] > (3, 9): import importlib.resources as resources @@ -145,10 +146,15 @@ def extrude_poly(outer_poly, inner_polys=None, height=1): return sl.linear_extrude(height=height, twist=0, convexity=0, center=True)(outer_poly) -def import_file(parts_path: resources.abc.Traversable, fname: str, convexity=2): +def import_resource(parts_path: resources.abc.Traversable, fname: str, convexity=2): logging.info("IMPORTING FROM %s", fname) with resources.as_file(parts_path.joinpath(fname + ".stl")) as extracted: - return sl.import_stl(extracted, convexity=convexity) + return sl.import_stl(str(extracted), convexity=convexity) + + +def import_file(fname: pathlib.Path, convexity=2): + logging.info("IMPORTING FROM %s", fname) + return sl.import_stl(str(fname), convexity=convexity) def export_file(shape, fname):