1813 lines
59 KiB
Plaintext
1813 lines
59 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "11191589-d59e-453c-9473-98f7a5200e89",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Overwriting auto display for cadquery Workplane and Shape\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import timeit\n",
|
|
"tic = timeit.default_timer()\n",
|
|
"\n",
|
|
"import cadquery as cq\n",
|
|
"\n",
|
|
"\n",
|
|
"from jupyter_cadquery import (\n",
|
|
" versions,\n",
|
|
" show, PartGroup, Part, \n",
|
|
" get_viewer, close_viewer, get_viewers, close_viewers, open_viewer, set_defaults, get_defaults, open_viewer,\n",
|
|
" get_pick,\n",
|
|
")\n",
|
|
"from jupyter_cadquery.ocp_utils import webcol_to_cq\n",
|
|
"\n",
|
|
"from jupyter_cadquery.replay import replay, enable_replay, disable_replay\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "0bf54acd-c9dd-4d79-87a3-93245059765f",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n",
|
|
"Versions:\n",
|
|
"- jupyter_cadquery 3.5.2\n",
|
|
"- cad_viewer_widget 1.4.1\n",
|
|
"- open cascade 7.6.3\n",
|
|
"\n",
|
|
"Plugins loaded:\n",
|
|
"- build123d\n",
|
|
"- cadquery-massembly\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"close_viewers()\n",
|
|
"versions()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "ba2360de-f361-44ec-83a8-fa516edf320d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"cv = open_viewer(\"smue2\",\n",
|
|
" anchor=\"right\", \n",
|
|
" glass=True, \n",
|
|
" theme=\"dark\",\n",
|
|
" tools=True) # sets default viewer\n",
|
|
"\n",
|
|
"\n",
|
|
"#cv.grid = [not g for g in cv.widget.grid]\n",
|
|
"\n",
|
|
"#cv.axes = not cv.axes\n",
|
|
"#cv.axes0 = not cv.axes0\n",
|
|
"#cv.transparent = not cv.transparent\n",
|
|
"#cv.black_edges = not cv.black_edges\n",
|
|
"\n",
|
|
"set_defaults(\n",
|
|
" cad_width=640, \n",
|
|
" height=480, \n",
|
|
" viewer=\"smue2\"\n",
|
|
")\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "6c0bf0b7-4559-487a-a059-95896c3ce3d0",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from math import asin,pi\n",
|
|
"\n",
|
|
"def arcd(y):\n",
|
|
" return 2*asin(y*0.5)\n",
|
|
"\n",
|
|
"def row_phi(size, radius):\n",
|
|
" return arcd(size/radius)\n",
|
|
"\n",
|
|
"tol = 0.5\n",
|
|
"\n",
|
|
"column_width = 19.3\n",
|
|
"plate_thickness = 4.0\n",
|
|
"\n",
|
|
"#column_yoff = 20.2\n",
|
|
"column_yoff = 18.0\n",
|
|
"switch_height = 15.4\n",
|
|
"switch_travel = 3.9\n",
|
|
"pad = 1\n",
|
|
"buttonhole_size = 14.0\n",
|
|
"cap_size = 18.0\n",
|
|
"cap_height = 11.5\n",
|
|
"\n",
|
|
"y0 = 0#-column_width*0.5\n",
|
|
"z0 =30\n",
|
|
"x0=-55\n",
|
|
"\n",
|
|
"endz = 65\n",
|
|
"endx = 110\n",
|
|
"endy = 6*column_width+5*pad\n",
|
|
"\n",
|
|
"radii = [60,60,68,64,44,44]\n",
|
|
"#radii = [47,47,48,48,44,44]\n",
|
|
"# global angle to rotate everything around after generation\n",
|
|
"radius = max(radii) + switch_height\n",
|
|
"angle_y = row_phi(column_yoff, radius)/(pi)*180 * 2\n",
|
|
"\n",
|
|
"radmodp= lambda r : r+switch_height#-switch_travel+plate_thickness\n",
|
|
"radmoda = lambda r : r+switch_height- cap_height\n",
|
|
"\n",
|
|
"def column(radius, full=False, n_buttons=4, r=None, tol=0.0, overwidth=0.0):\n",
|
|
" \n",
|
|
" angle_button = row_phi(column_yoff, radmoda(radius))/(pi)*180\n",
|
|
" radius = radmodp(radius)\n",
|
|
" angle_rev = angle_button*n_buttons\n",
|
|
" if r:\n",
|
|
" angle_rev = r\n",
|
|
" \n",
|
|
" l = radius+plate_thickness+tol if full else plate_thickness\n",
|
|
" y0 = -tol if full else 0\n",
|
|
"\n",
|
|
" #radius = radius+tol if full else radius\n",
|
|
" \n",
|
|
" base = (cq.Workplane(\"YZ\")\n",
|
|
" .move(-tol, -plate_thickness+y0)\n",
|
|
" .rect(column_width+tol+overwidth, l, False)\n",
|
|
" .revolve(angle_rev,(-50,radius),(50,radius), False)\n",
|
|
" )\n",
|
|
" return base\n",
|
|
"\n",
|
|
"\n",
|
|
"def buttonhole(i, j,r):\n",
|
|
" \n",
|
|
" angle = row_phi(column_yoff, radmoda(r))/(pi)*180*(0.5+j)\n",
|
|
" r = radmodp(r)\n",
|
|
" # r = r+switch_height-switch_travel + plate_thickness\n",
|
|
" # h = 4\n",
|
|
" return (cq.Workplane(\"XY\")\n",
|
|
" .workplane(offset=switch_height/2)\n",
|
|
" .box(cap_size, cap_size ,switch_height)\n",
|
|
" .faces(\"<Z\")\n",
|
|
" .workplane()\n",
|
|
" .rect(buttonhole_size, buttonhole_size)\n",
|
|
" .extrude(7)\n",
|
|
" #.translate([0,0,h])\n",
|
|
" .rotate((0,-50,r),(0,50,r),angle)\n",
|
|
" .translate([0,(i+0.5)*(column_width)+i*pad, 0])\n",
|
|
" )\n",
|
|
"\n",
|
|
"def buttonholes(radii, n_buttons=4):\n",
|
|
" result = None\n",
|
|
" for i, r in enumerate(radii):\n",
|
|
" for j in range(n_buttons):\n",
|
|
" if not result:\n",
|
|
" result = buttonhole(i, j, r)\n",
|
|
" result += buttonhole(i, j, r)\n",
|
|
" return result\n",
|
|
"\n",
|
|
"def build_buttonplate(radii,full=False, phi=None):\n",
|
|
" radius = max(radii)\n",
|
|
" result=None\n",
|
|
" fingers = []\n",
|
|
" for i,r in enumerate(radii):\n",
|
|
" finger = column(r, full, 4, phi).translate([0,(column_width+pad)*i,0])\n",
|
|
" fingers.append(finger)\n",
|
|
" bridges = []\n",
|
|
" for i in range(len(fingers)-1):\n",
|
|
" left_finger_right_face = fingers[i].faces(\">Y\").val().outerWire()\n",
|
|
" right_finger_left_face = fingers[i+1].faces(\"<Y\").val().outerWire()\n",
|
|
" bridge = cq.Solid.makeLoft([left_finger_right_face, right_finger_left_face]) \n",
|
|
" bridges.append(bridge)\n",
|
|
" result = fingers[0]\n",
|
|
" for i in range(len(fingers)-1):\n",
|
|
" result += cq.Workplane().add(bridges[i]) + fingers[i+1]\n",
|
|
" return result\n",
|
|
"\n",
|
|
"def build_base_pcb_cutouts(radii):\n",
|
|
" cutouts = []\n",
|
|
" d = 1.5 # padding\n",
|
|
" h = 5 # pcb cutout height\n",
|
|
" for i, r in enumerate(radii):\n",
|
|
" phi = row_phi(column_yoff-(d*0.5), radmoda(r))/(pi)*180*4\n",
|
|
" r = radmodp(r)\n",
|
|
" cutout = (cq.Workplane(\"YZ\")\n",
|
|
" .move(d, -plate_thickness-h)\n",
|
|
" .rect(column_width-4, h+1, False)\n",
|
|
" .revolve(phi,(-50,r),(50,r), False)\n",
|
|
" .translate([0,(column_width+pad)*i,0])\n",
|
|
" #.faces(\"<Y or >Y\")#.edges(\">Z\")#.fillet(1)\n",
|
|
" \n",
|
|
" )\n",
|
|
" cutout = rotate_keyplate(cutout).faces(\"<Y or >Y\").edges(\"<Z\").fillet(2)\n",
|
|
" cutouts.append(cutout)\n",
|
|
" \n",
|
|
" result = cutouts[0]\n",
|
|
" for c in cutouts[1:]:\n",
|
|
" result += c\n",
|
|
" return result\n",
|
|
"\n",
|
|
"\n",
|
|
"def rotate_keyplate(part):\n",
|
|
" return part.rotate((0,-50,radius),(0,50,radius), -angle_y)\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "0bb6d95c-eaf9-4915-b898-c1159ca0886a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "7a364cc4-dfd2-4a34-8a88-2a32408d1c7c",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_screwholes(pos):\n",
|
|
" d = 10\n",
|
|
" hole= (cq.Workplane().cylinder(10,3/2))\n",
|
|
" countersunk = (cq.Workplane(\"XZ\")\n",
|
|
"\n",
|
|
" .polyline([(0,0),(0,d),(d,d),(0,0)])\n",
|
|
" .wire()\n",
|
|
" .revolve()\n",
|
|
" .translate([0,0,-2])\n",
|
|
" )\n",
|
|
" hole = (hole+countersunk).translate(pos)\n",
|
|
" stem = (cq.Workplane()\n",
|
|
" .workplane(offset=-10)\n",
|
|
" .cylinder(12, d+4)\n",
|
|
" .translate(pos)\n",
|
|
" )\n",
|
|
" return hole, stem\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "eb07d1a1-7512-464c-920d-0afd13fe092a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_handrest_cuttout(buttonplate):\n",
|
|
" h = plate_thickness\n",
|
|
" h1 = 50\n",
|
|
" dz=10\n",
|
|
" l = 0.7\n",
|
|
" sg = 0.04\n",
|
|
" y0=-30\n",
|
|
" pnts = [(y0, 5+z0),\n",
|
|
" ((1-l-sg)*(endy-y0)+y0,dz+z0),\n",
|
|
" ((l+sg)*(endy-y0)+y0, dz+z0),\n",
|
|
" (endy,5+z0)]\n",
|
|
" backpnts = [(y,z-h) for y,z in pnts][-1::-1]\n",
|
|
" backpnts_cutout = [(y,z+40) for y,z in pnts][-1::-1]\n",
|
|
"\n",
|
|
" top = (buttonplate.faces(\">X\")\n",
|
|
" .workplane(centerOption='CenterOfMass')\n",
|
|
" .moveTo(-endy/2+y0, switch_height)#plate_thickness*0.5)\n",
|
|
" .line(endy-y0,0)\n",
|
|
" .line(0,h1)\n",
|
|
" .line(-endy+y0,0)\n",
|
|
" .close()\n",
|
|
" .val()\n",
|
|
" )\n",
|
|
"\n",
|
|
" middle = (cq.Workplane(\"YZ\")\n",
|
|
" .workplane(offset=80)\n",
|
|
" .moveTo(-h, z0)\n",
|
|
" .spline(pnts, includeCurrent=False)\n",
|
|
" .line(0,30)\n",
|
|
" .line(-endy, 0)\n",
|
|
" .close()\n",
|
|
" .val()\n",
|
|
" )\n",
|
|
"\n",
|
|
" end = (cq.Workplane(\"YZ\")\n",
|
|
" .workplane(offset=endx)\n",
|
|
" .moveTo(y0,30-h)\n",
|
|
" .line(endy-y0,0)\n",
|
|
" .line(0,h1)\n",
|
|
" .line(-endy+y0,0)\n",
|
|
" .close()\n",
|
|
" .val()\n",
|
|
" )\n",
|
|
" \n",
|
|
" ans = cq.Solid.makeLoft([top, middle, end])\n",
|
|
" return ans\n",
|
|
"\n",
|
|
"#handrest_cutout = build_handrest_cuttout(raw_buttonplate)\n",
|
|
"#testrender()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "8c526fc5-55a3-453d-afa5-878726a5c480",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_xy_contour():\n",
|
|
" return (cq.Workplane(\"XY\")\n",
|
|
" .workplane(offset=-20)\n",
|
|
" .moveTo(x0,y0)\n",
|
|
" .line(0,endy)\n",
|
|
" .line(endx-x0,0)\n",
|
|
" .line(0,-endy) \n",
|
|
" .close()\n",
|
|
" .extrude(endz)\n",
|
|
" \n",
|
|
" )\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "314eae90-2aef-410a-9e46-97fa6b4f7d61",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_electronics_cutout():\n",
|
|
" return (cq.Workplane(\"XY\")\n",
|
|
" .workplane(offset=-15)\n",
|
|
" .rect(50, 50)\n",
|
|
" .workplane(offset=30)\n",
|
|
" .rect(55,55)\n",
|
|
" .loft()\n",
|
|
" .fillet(5)\n",
|
|
" .translate([0, 56,0])\n",
|
|
" )\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "bc87c49c-9b74-4da6-9059-e86d44453b24",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_keyplate_overhang_cutout(radii):\n",
|
|
" \n",
|
|
" def column(radius, n_buttons=4, r=None):\n",
|
|
" angle_button = row_phi(column_yoff, radmoda(radius))/(pi)*180\n",
|
|
" radius = radmodp(radius)\n",
|
|
" angle_rev = angle_button*(n_buttons)\n",
|
|
"\n",
|
|
"\n",
|
|
" base = (cq.Workplane(\"YZ\")\n",
|
|
" .move(0, -plate_thickness*5)\n",
|
|
" .rect(column_width, 5*plate_thickness, False)\n",
|
|
" .revolve(angle_rev,(-50,radius),(50,radius), False)\n",
|
|
" )\n",
|
|
" return base\n",
|
|
" \n",
|
|
" def plate(add=True):\n",
|
|
" n = 6 if add else 4\n",
|
|
" radius = max(radii)\n",
|
|
" \n",
|
|
" fingers = []\n",
|
|
" for i,r in enumerate(radii):\n",
|
|
"\n",
|
|
" finger = (column(r, n)\n",
|
|
" .translate([0,(column_width+pad)*i,0])\n",
|
|
" )\n",
|
|
" fingers.append(finger)\n",
|
|
" bridges = []\n",
|
|
" for i in range(len(fingers)-1):\n",
|
|
" left_finger_right_face = fingers[i].faces(\">Y\").val().outerWire()\n",
|
|
" right_finger_left_face = fingers[i+1].faces(\"<Y\").val().outerWire()\n",
|
|
" bridge = cq.Solid.makeLoft([left_finger_right_face, right_finger_left_face]) \n",
|
|
" bridges.append(bridge)\n",
|
|
" result = fingers[0]\n",
|
|
" for i in range(len(fingers)-1):\n",
|
|
" result += cq.Workplane().add(bridges[i]) + fingers[i+1]\n",
|
|
" #result += fingers[i+1]#cq.Workplane().add(bridges[i])# + fingers[i+1]\n",
|
|
" return result\n",
|
|
" \n",
|
|
" return plate(True)- plate(False)\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "387e92c7-5e92-4bdb-88d8-cbdc84e264ac",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_bottom_cutout():\n",
|
|
" w = 100\n",
|
|
" h0 = 10\n",
|
|
" h = 30\n",
|
|
" x0 = 30\n",
|
|
" z0 = -30\n",
|
|
" d=0.3\n",
|
|
" pnts = [(x0, z0+h0),\n",
|
|
" (x0+0.3*w,h+z0),\n",
|
|
" (x0+0.5*w,15+h+z0),\n",
|
|
" (x0+0.9*w,15+h+z0)][-1::-1]\n",
|
|
" \n",
|
|
" \n",
|
|
" path = (cq.Workplane(\"YZ\")\n",
|
|
" .workplane(offset=x0+w*0.5)\n",
|
|
" .line(endx,0))\n",
|
|
" \n",
|
|
" straightpts = [(x0+0.75*w, z0+h0), (x0,z0+h0)]\n",
|
|
" return (cq.Workplane(\"XZ\")\n",
|
|
" .workplane(offset=-20)\n",
|
|
" .moveTo(x0,z0)\n",
|
|
" .line(w,0)\n",
|
|
" .line(0,h0)\n",
|
|
" .spline(straightpts, includeCurrent=True)\n",
|
|
" .close()\n",
|
|
" .workplane(offset=-30)\n",
|
|
" .moveTo(x0,z0)\n",
|
|
" .line(w,0)\n",
|
|
" .line(0, h+15)\n",
|
|
" .spline(pnts, includeCurrent=True)\n",
|
|
" .close()\n",
|
|
" .workplane(offset=-45)\n",
|
|
" .moveTo(x0,z0)\n",
|
|
" .line(w,0)\n",
|
|
" .line(0,h0)\n",
|
|
" .spline(straightpts, includeCurrent=True)\n",
|
|
" .close()\n",
|
|
" .loft()\n",
|
|
" )\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "bfbd1413-e793-4d44-a9a6-10f4790c9e96",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_thumb_handrest_cuttout():\n",
|
|
" h1 = 50\n",
|
|
" base = (cq.Workplane(\"YZ\")\n",
|
|
" .transformed(rotate=[0,-15,0])\n",
|
|
" .transformed(offset=[endx+30,40, -38])\n",
|
|
" #.transformed(rotate=[-10,-15,-25])\n",
|
|
" \n",
|
|
" )\n",
|
|
" x1 = 0\n",
|
|
" ans = (base\n",
|
|
" .moveTo(x1,0)\n",
|
|
" .ellipse(22,22)\n",
|
|
" #.circle(10)\n",
|
|
" .workplane(offset=150)\n",
|
|
" .moveTo(x1,0)\n",
|
|
" .ellipse(37,22)\n",
|
|
" .loft(combine=True)\n",
|
|
" )\n",
|
|
" \n",
|
|
" return ans\n",
|
|
"#thumb_handrest_cutout = build_thumb_handrest_cuttout()\n",
|
|
"#based = contour - thumb_cutout - handrest_cutout - thumb_handrest_cutout\n",
|
|
"#testrender()\n",
|
|
"#based"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "139b0d8e-5e91-4664-9732-add85497d00d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_wire_tunnels():\n",
|
|
" d = 15\n",
|
|
" tunnel = cq.Workplane(\"XY\").workplane(offset=-8).move(0,20).rect(d,20).extrude(28).edges().fillet(3)\n",
|
|
" t1 = rotate_keyplate(tunnel).rotate((0,-50,radius),(0,50,radius), 10)\n",
|
|
" \n",
|
|
" r = radii[-1]+switch_height\n",
|
|
" t2 = rotate_keyplate(tunnel.rotate((0,-50,r),(0,50,r), 40)).translate([0,column_yoff*3.5,0])\n",
|
|
" t3 = rotate_keyplate(tunnel.rotate((0,-50,r),(0,50,r), 40)).translate([0,column_yoff*4.5,0])\n",
|
|
"\n",
|
|
" return t1 +t2 +t3\n",
|
|
"#wire_tunnels = build_wire_tunnels()\n",
|
|
"#testrender()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "dc9c2857-ad6c-4ab8-b72a-d24368469a1b",
|
|
"metadata": {},
|
|
"source": [
|
|
"# add thumb to base contour"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "2dc6984c-bdf0-48fb-8c5f-849a57834ced",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def position_thumbplate(plate, r=44):\n",
|
|
" \n",
|
|
" phi = row_phi(column_yoff, radmoda(r))/(pi)*180\n",
|
|
" r = radmodp(r)\n",
|
|
" thumbplate = plate.translate([0,0,plate_thickness/2])\n",
|
|
" thumbplate = thumbplate.rotate((0,-r,r),(0,r,r), -phi)\n",
|
|
" thumbplate = thumbplate.rotate((0,0,0),(0,0,1), -60)\n",
|
|
" thumbplate = thumbplate.translate([35,-27,0])\n",
|
|
" return thumbplate\n",
|
|
"\n",
|
|
"\n",
|
|
"def position_second_col_thumbplate(plate, r):\n",
|
|
" phi = row_phi(column_yoff, radmoda(r))/(pi)*180\n",
|
|
" r = radmodp(r)\n",
|
|
" return (plate.rotate((0,-r,r),(0,r,r), phi)\n",
|
|
" .translate([0, column_width, -plate_thickness/2]))\n",
|
|
"\n",
|
|
"\n",
|
|
"def build_thumbplate(r=44):\n",
|
|
" c = column(r, full=False, n_buttons=2) \n",
|
|
" #r += switch_height\n",
|
|
" c1 = position_second_col_thumbplate(c, r)\n",
|
|
" f = c.faces(\">Y\").wires().val()\n",
|
|
" f1 = c1.faces(\"<Y\").wires().val()\n",
|
|
" #l = cq.Solid.makeLoft([f,f1])\n",
|
|
" thumbplate = c + c1 \n",
|
|
" thumbplate = position_thumbplate(thumbplate, r)\n",
|
|
" thumbplate = thumbplate.edges(\">>Y[0]\").fillet(5)\n",
|
|
" return thumbplate\n",
|
|
"\n",
|
|
"def build_thumbplate_holes(r=44):\n",
|
|
" #r += switch_height \n",
|
|
" h = buttonholes([r], n_buttons=2)\n",
|
|
" h1 = position_second_col_thumbplate(h, r)\n",
|
|
" holes = h + h1\n",
|
|
" holes = position_thumbplate(holes, r)\n",
|
|
" return holes\n",
|
|
"\n",
|
|
"def build_thumbplate_cutspace(r=44, phi=None, yoff=0, width=22): \n",
|
|
" phipad = row_phi(tol, radmoda(r))/(pi)*180\n",
|
|
" angle_button = row_phi(column_yoff, radmoda(r))/(pi)*180\n",
|
|
" angle_rev = angle_button*2+(phipad*2)\n",
|
|
" angle_2nd = 20\n",
|
|
" #r = radmodp(r)\n",
|
|
" dr = 30\n",
|
|
" r0 = r\n",
|
|
" c0 = (cq\n",
|
|
" .Workplane(\"YZ\")\n",
|
|
" .workplane(offset=0)#-tol)\n",
|
|
" .move(-column_width, -plate_thickness+y0-50)\n",
|
|
" .rect(column_width*5, 200, False)\n",
|
|
" .extrude(30))\n",
|
|
" #r = radmodp(r)\n",
|
|
" c = column(r, full=True, n_buttons=2, r=angle_rev, tol=3*tol)\n",
|
|
" \n",
|
|
" #.translate([0,yoff,0])\n",
|
|
" c = c.rotate((0,-r,r),(0,r,r), -phipad)\n",
|
|
" c1 = position_second_col_thumbplate(c, r0)#c.translate([0, width+tol, 0])\n",
|
|
" \n",
|
|
" \n",
|
|
" c = column(r, full=True, n_buttons=4, tol=tol).translate([0,yoff,0])\n",
|
|
" c = c.rotate((0,-r,r),(0,r,r), -phipad)\n",
|
|
" \n",
|
|
" f = c.faces(\">Y\").wires().val()\n",
|
|
" f1 = c1.faces(\"<Y\").wires().val()\n",
|
|
" # l = cq.Solid.makeLoft([f,f1])\n",
|
|
" cutspace = c.translate([0,-10,0])+ c0+c + c1 + c1.translate([0,-15,0])\n",
|
|
" #cutspace = cutspace.rotate((0,-r,r),(0,r,r), 20)\n",
|
|
" cutspace = position_thumbplate(cutspace, r0)\n",
|
|
" return cutspace\n",
|
|
"\n",
|
|
"\n",
|
|
"def build_thumbcontour():\n",
|
|
" # The points that the spline will pass through\n",
|
|
" s = cq.Workplane(\"XY\")\n",
|
|
" x0 = 40\n",
|
|
" y0 = -45\n",
|
|
" sPnts = [\n",
|
|
" (x0-33, y0+55),\n",
|
|
" (x0, y0-8),\n",
|
|
" (x0+24, y0+6),\n",
|
|
" (x0+40, y0+27),\n",
|
|
" (x0+70, y0+45),\n",
|
|
" ]\n",
|
|
" r = (s.polyline(sPnts)#.lineTo(x0, y0)\n",
|
|
" .close()\n",
|
|
" .extrude(endz)\n",
|
|
" .translate([0,0,-20])\n",
|
|
" #.faces(\">>X[2]\")\n",
|
|
" #.edges(\"|Z and >>X[2]\").fillet(10)\n",
|
|
" .edges(\"|Z and >>Y[2]\").fillet(30)\n",
|
|
" .edges(\"|Z and <<Y[4]\").fillet(50)\n",
|
|
" )\n",
|
|
" plate_aligned_cutout = position_thumbplate( \n",
|
|
" cq\n",
|
|
" .Workplane(\"YZ\")\n",
|
|
" .workplane(offset=-100)\n",
|
|
" .move(-column_width, -plate_thickness+y0)\n",
|
|
" .rect(column_width, 200, False)\n",
|
|
" .extrude(200))\n",
|
|
" \n",
|
|
" return r -plate_aligned_cutout\n",
|
|
"\n",
|
|
"\n",
|
|
"def build_thumb_cutout(r=44):\n",
|
|
" r0 = r+switch_travel \n",
|
|
" r = radmodp(r)\n",
|
|
" off = -3*column_yoff\n",
|
|
" return position_thumbplate(\n",
|
|
" #return (\n",
|
|
" #build_thumbplate_cutspace(40,360, yoff=-10, width=32)\n",
|
|
" cq.Workplane(\"XZ\")\n",
|
|
" .workplane(offset=off)\n",
|
|
" .move(-r, switch_travel)\n",
|
|
" #.move(-r,-switch_travel)#-r+switch_height)\n",
|
|
" #.cylinder(-off+30,r-switch_height+switch_travel, centered=False)\n",
|
|
" .cylinder(-3*off, r-switch_travel, centered=False)\n",
|
|
" .faces(\">Y\")\n",
|
|
" .workplane(centerOption='CenterOfMass')\n",
|
|
" #.wires().toPending()\n",
|
|
" #.move(0, -switch_height+switch_travel)\n",
|
|
" .circle(r-switch_travel)\n",
|
|
" .workplane(offset=150, centerOption='CenterOfMass')\n",
|
|
" .move(10,0)\n",
|
|
" .circle(20)\n",
|
|
" .loft()#.clean()\n",
|
|
" .edges(\">>Y[2]\").fillet(290)\n",
|
|
" .rotate((0,-50,r),(0,50,r), 75)\n",
|
|
" .translate([0,2*column_yoff,0])\n",
|
|
" )\n",
|
|
"\n",
|
|
"def build_thumb_overhang_cutout(radii):\n",
|
|
" \n",
|
|
" def column(radius, n_buttons=2, r=None):\n",
|
|
" #radius+=switch_height\n",
|
|
" angle_button = row_phi(column_yoff, radius)/(pi)*180\n",
|
|
" angle_rev = angle_button*(n_buttons)\n",
|
|
" s = 5\n",
|
|
"\n",
|
|
" base = (cq.Workplane(\"YZ\")\n",
|
|
" .move(-32, 0)#-plate_thickness*s)\n",
|
|
" .rect(column_width+28, s*plate_thickness, False)\n",
|
|
" .revolve(angle_rev,(-50,radius),(50,radius), False)\n",
|
|
" )\n",
|
|
" return base\n",
|
|
" \n",
|
|
" def plate(add=True):\n",
|
|
" n = 4 if add else 2\n",
|
|
" fingers = []\n",
|
|
" for i,r in enumerate(radii):\n",
|
|
"\n",
|
|
" finger = (column(r, n)\n",
|
|
" #.translate([0,(column_width+pad)*i,0])\n",
|
|
" )\n",
|
|
" finger = position_second_col_thumbplate(finger,r) if i == 1 else finger\n",
|
|
" fingers.append(finger)\n",
|
|
" bridges = []\n",
|
|
" for i in range(len(fingers)-1):\n",
|
|
" left_finger_right_face = fingers[i].faces(\">Y\").val().outerWire()\n",
|
|
" right_finger_left_face = fingers[i+1].faces(\"<Y\").val().outerWire()\n",
|
|
" bridge = cq.Solid.makeLoft([left_finger_right_face, right_finger_left_face]) \n",
|
|
" bridges.append(bridge)\n",
|
|
" result = fingers[0]\n",
|
|
" for i in range(len(fingers)-1):\n",
|
|
" result += cq.Workplane().add(bridges[i]) + fingers[i+1]\n",
|
|
" #result += fingers[i+1]#cq.Workplane().add(bridges[i])# + fingers[i+1]\n",
|
|
" return result\n",
|
|
" \n",
|
|
" return position_thumbplate(plate(True)- plate(False))\n",
|
|
" #return (build_thumbplate_cutspace(70))\n",
|
|
" \n",
|
|
"def build_thumb_pcb_cutouts(radii=[44,44]):\n",
|
|
" cutouts = []\n",
|
|
" d = 1.5 # padding\n",
|
|
" h = 5 # pcb cutout height\n",
|
|
" for i, r in enumerate(radii):\n",
|
|
" \n",
|
|
" phi = row_phi(column_yoff-d \\\n",
|
|
" #+(d*0.5) \\\n",
|
|
" ,radmoda( r))/(pi)*180*2\n",
|
|
" r = r+switch_height\n",
|
|
" phi = phi + 20 if i == 0 else phi\n",
|
|
" cutout = (cq.Workplane(\"YZ\")\n",
|
|
" .move(d, -plate_thickness-h)\n",
|
|
" .rect(column_width-2*d, h, False)\n",
|
|
" .revolve(phi,(-50,r),(50,r), False) \n",
|
|
" )\n",
|
|
" if i == 1:\n",
|
|
" cutout = (cq.Workplane(\"YZ\")\n",
|
|
" .move(-2*d, -plate_thickness-h)\n",
|
|
" .rect(column_width+d, h, False)\n",
|
|
" .revolve(phi,(-50,r),(50,r), False))\n",
|
|
" cutout = position_second_col_thumbplate(cutout, r-switch_height)\n",
|
|
" cutout = cutout.faces(\"<Y or >Y\").edges(\"<<Z[2]\").fillet(2)\n",
|
|
" cutout = cutout.rotate((0,-50,r),(0,50,r), 2.5)\n",
|
|
" cutout = position_thumbplate(cutout, r-switch_height) \n",
|
|
" #if i== 1:\n",
|
|
" cutouts.append(cutout)\n",
|
|
" \n",
|
|
" result = cutouts[0]\n",
|
|
" for c in cutouts[1:]:\n",
|
|
" result += c\n",
|
|
" return result\n",
|
|
"\n",
|
|
"#thumbplate_cutspace = build_thumbplate_cutspace()\n",
|
|
"#thumb_pcb_cutout = build_thumb_pcb_cutouts()\n",
|
|
"#thumbcontour = build_thumbcontour()\n",
|
|
"#thumb_cutout = build_thumb_cutout()\n",
|
|
"#thumb_switches = place_thumb_switches(mx_switch)\n",
|
|
"#thumbplate_cutspace = build_thumbplate_cutspace()\n",
|
|
"#thumb_caps = place_thumb_switches(xda_cap)\n",
|
|
"#thumbplate = build_thumbplate()\n",
|
|
"#thumb_pcb_cutout = build_thumb_pcb_cutouts()\n",
|
|
"#thumbplate_cutspace = build_thumbplate_cutspace()\n",
|
|
"#thumb_handrest_cutout = build_thumb_handrest_cuttout()\n",
|
|
"#thumb_overhang_cutout = build_thumb_overhang_cutout([44+switch_height-switch_travel])\n",
|
|
"#testrender()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "348213f4-1705-454e-b921-014cf6e03f6e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"#prt = column(44, 0, 1) - buttonhole(0,0,44)\n",
|
|
"#cq.exporters.export(prt, basepath+\"/singlebtnframe.step\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8e83077d-cabd-4740-9eb5-36896c3df032",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4ce08cb1-2239-4ca9-a11c-882aebeaaac7",
|
|
"metadata": {},
|
|
"source": [
|
|
"# create bridge between buttonplate and thumb_buttonplate"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"id": "181c0e74-d6d6-4967-8cea-2fa959b1078a",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_buttonplate_bridge():\n",
|
|
" buttonplate_bridge_a = build_buttonplate([radii[0]],False, angle_y).translate([0,10,0])\n",
|
|
" buttonplate_bridge_a = rotate_keyplate(buttonplate_bridge_a)\n",
|
|
" f1 = buttonplate_bridge_a.faces(\"<Y\").val().outerWire()\n",
|
|
" buttonplate_bridge_b = position_thumbplate(column(44, full=False, n_buttons=2))\n",
|
|
" f2 = buttonplate_bridge_b.faces(\">Y\").val().outerWire()\n",
|
|
" buttonplate_bridge = cq.Solid.makeLoft([f2, f1])\n",
|
|
" return buttonplate_bridge\n",
|
|
" #return buttonplate_bridge_b\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c14ffb97-a514-4af9-ab58-a4434f9591f1",
|
|
"metadata": {},
|
|
"source": [
|
|
"# create slot"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"id": "5792be7b-db30-4b0f-93ca-581c8991d5ea",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_slot():\n",
|
|
" box =( cq.Workplane(\"YZ\").workplane(offset=x0)\n",
|
|
" .moveTo(2.5*column_yoff,-10)\n",
|
|
" .sketch()\n",
|
|
" .rect(20,20)\n",
|
|
" .finalize()\n",
|
|
" .extrude(50)\n",
|
|
" .edges(\"<X\").edges(\"<Z\").fillet(10))\n",
|
|
" \n",
|
|
" slot = (cq.Workplane(\"YZ\").workplane(offset=x0)\n",
|
|
" .moveTo(2.5*column_yoff,-11)\n",
|
|
" .sketch()\n",
|
|
" .slot(12,8)\n",
|
|
" .finalize()\n",
|
|
" .extrude(10))\n",
|
|
" usb = (cq.Workplane(\"YZ\").workplane(offset=x0)\n",
|
|
" .moveTo(2.5*column_yoff,-11)\n",
|
|
" .sketch()\n",
|
|
" .slot(9,3.2)\n",
|
|
" .finalize()\n",
|
|
" .extrude(10))\n",
|
|
" \n",
|
|
" cutslot = (cq.Workplane(\"YZ\").workplane(offset=x0)\n",
|
|
" .moveTo(2.5*column_yoff,-11)\n",
|
|
" .sketch()\n",
|
|
" .slot(12,8)\n",
|
|
" .finalize()\n",
|
|
" .extrude(50))\n",
|
|
" return cutslot, (slot & box)-usb\n",
|
|
"#slot, usbsocket = build_slot()\n",
|
|
"#usbsocket"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "dc985ea6-6982-4edc-9f43-39c85c7f3084",
|
|
"metadata": {},
|
|
"source": [
|
|
"# create instances of all components"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "e7a0ab16-5095-4dfc-bff3-f418940d25e8",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"raw_buttonplate = rotate_keyplate(build_buttonplate(radii)).faces(\"<Y or >Y\").edges(\"%LINE\").edges(\">>X[1] or >>X[0]\").fillet(8)\n",
|
|
"holes = rotate_keyplate(buttonholes(radii))\n",
|
|
"\n",
|
|
"buttonplate_cutspace = build_buttonplate(radii,True, angle_y*4).rotate((0,-50,radius),(0,50,radius), -angle_y-0.4)\n",
|
|
"buttonplate_cutspace1 = (build_buttonplate([radii[0]],True, angle_y*4)\n",
|
|
" .rotate((0,-50,radius),(0,50,radius), -angle_y-0.4)\n",
|
|
" #.rotate((0,-50,radii[0]),(0,50,radii[0]), angle_y*0.2)\n",
|
|
" .translate([0,-column_yoff*0.8,0]) )\n",
|
|
"#holes\n",
|
|
"hole1, stem1 = build_screwholes([0.,column_width+pad/2])\n",
|
|
"hole2, stem2 = build_screwholes([20.,5*(column_width+pad)-0.5,2.5])\n",
|
|
"slot, usbsocket = build_slot()\n",
|
|
"\n",
|
|
"xy_contour = build_xy_contour()\n",
|
|
"\n",
|
|
"handrest_cutout = build_handrest_cuttout(raw_buttonplate)\n",
|
|
"thumb_handrest_cutout = build_thumb_handrest_cuttout()\n",
|
|
"electronics_cutout = build_electronics_cutout()\n",
|
|
"overhang_cutout = rotate_keyplate(build_keyplate_overhang_cutout(radii))\n",
|
|
"bottom_cutout = build_bottom_cutout()\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"pcb_cutouts = build_base_pcb_cutouts(radii)\n",
|
|
"wire_tunnels = build_wire_tunnels()\n",
|
|
"thumbplate = build_thumbplate()\n",
|
|
"thumbholes = build_thumbplate_holes()\n",
|
|
"thumbplate_cutspace = build_thumbplate_cutspace()\n",
|
|
"thumb_cutout = build_thumb_cutout()\n",
|
|
"thumbcontour = build_thumbcontour()\n",
|
|
"thumb_overhang_cutout = build_thumb_overhang_cutout([40])\n",
|
|
"#thumb_overhang_cutout -= thumb_overhang_cutout & buttonplate_cutspace\n",
|
|
"\n",
|
|
"thumb_pcb_cutout = build_thumb_pcb_cutouts()\n",
|
|
"\n",
|
|
"buttonplate_bridge = build_buttonplate_bridge()\n",
|
|
"\n",
|
|
"#raw_buttonplate += buttonplate_bridge\n",
|
|
"buttonplate = ((raw_buttonplate + buttonplate_bridge)- thumbholes - holes-hole1-hole2) \n",
|
|
"thumbplate = thumbplate - thumbholes - holes\n",
|
|
"buttonplate += thumbplate\n",
|
|
"\n",
|
|
"#testrender()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d8dbe4f9-6e2d-42aa-98e0-890c67faa7f1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"id": "54dc0c80-cb21-4ed3-beb8-85192e7a52bf",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_contour():\n",
|
|
"# fuse both contours together and make seam smooth\n",
|
|
" r1 = 60\n",
|
|
" r2 = r1\n",
|
|
" contour = xy_contour + thumbcontour\n",
|
|
" contour = (contour.faces(\"-Y\").edges(\"|Z and >X\").fillet(r1)\n",
|
|
".edges(\"|Z\").edges(\"<<X[0]\").fillet(r2)\n",
|
|
" \n",
|
|
" )\n",
|
|
" return contour\n",
|
|
"contour = build_contour()\n",
|
|
"#contour"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "7a0ff9b5-69e4-4efb-8932-7969ecbf1ec1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0a46d47e-d823-4191-85c0-af8ec6888369",
|
|
"metadata": {},
|
|
"source": [
|
|
"# build base"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"id": "0c5aa503-6e41-4c3e-894e-87b571cf6fc5",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def build_base():\n",
|
|
" base = contour - thumb_cutout- handrest_cutout- thumb_handrest_cutout\n",
|
|
" #return base\n",
|
|
" base = (base \n",
|
|
" - buttonplate_cutspace \n",
|
|
" - buttonplate_cutspace1\n",
|
|
" - overhang_cutout\n",
|
|
" #-thumb_overhang_cutout\n",
|
|
" )\n",
|
|
" #return base\n",
|
|
" base = base - pcb_cutouts - electronics_cutout - wire_tunnels\n",
|
|
" #return base\n",
|
|
" base = (base\n",
|
|
" .edges(\"<X\").edges(\"not <Z\")\n",
|
|
" #.edges(\"not |Z\")\n",
|
|
" .edges(\"|Y\")\n",
|
|
" .fillet(8) # front top edges\n",
|
|
" .edges(\"<X and |Z\").fillet(8) # front side edges\n",
|
|
")\n",
|
|
" \n",
|
|
" base = base-hole1-hole2\n",
|
|
" \n",
|
|
" # smooth handrest\n",
|
|
" #return base\n",
|
|
" r1 = 20\n",
|
|
" base = (base.edges(\"<<Z[0]\").fillet(r1)\n",
|
|
" .edges(\"<<Z[1]\").fillet(r1)\n",
|
|
" .edges(\"<<X[0]\").edges(\">Z\").fillet(12)\n",
|
|
" .edges(\"|Z and >>Y[0]\").fillet(5)\n",
|
|
" .faces(\"<Z\").fillet(10)\n",
|
|
")\n",
|
|
" \n",
|
|
" #return base\n",
|
|
" # add slot for cable\n",
|
|
" base = base - slot\n",
|
|
" base = base - thumbplate_cutspace \n",
|
|
" #base = (base.faces(\"<Z\").fillet(10)) # bottom edge\n",
|
|
" base = base -thumb_pcb_cutout\n",
|
|
" \n",
|
|
" #base = base \n",
|
|
" #base = base.edges(\">>Y[0]\").fillet(3)\n",
|
|
" base = base - thumbholes\n",
|
|
" return base\n",
|
|
"\n",
|
|
"base = build_base()\n",
|
|
"#testrender()\n",
|
|
"base\n",
|
|
"#keyboard = show_product()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "81768916-1d16-4d20-b337-9d1a59a42341",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1af586cd-f2dc-4cd4-8daf-09957973b3c3",
|
|
"metadata": {},
|
|
"source": [
|
|
"# add ridge to base"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"id": "c47df18b-fb87-4dc9-b4be-50347b26ffeb",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from build123d import *"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"id": "dbd66d5c-ccc0-4921-914b-64a2ecab6f39",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"def add_ridge(contour, base):\n",
|
|
" path = contour.faces(\"<Z\").edges(\"<<X[2]\").translate([0,0,18.5]).val()\n",
|
|
" pathw = path.wrapped\n",
|
|
" path = Edge()\n",
|
|
" path.wrapped = pathw\n",
|
|
" with BuildPart() as signal:\n",
|
|
" with BuildLine(Plane.XY) as path_builder:\n",
|
|
" #path_builder.mode=Mode.PRIVATE\n",
|
|
" #Spline(path@0, ())\n",
|
|
" p1 = path@0\n",
|
|
" p1.Y = p1.Y+8.5\n",
|
|
" j0 = JernArc(start=p1, tangent=-(path % 0), radius=10, arc_size=-90)\n",
|
|
" j1 = JernArc(start=p1, tangent=path%0, radius=60, arc_size=-90)\n",
|
|
" #add(path)\n",
|
|
" #j1 = Spline(p1, path@1, tangents=[-(j0%0), path%1])\n",
|
|
" j2=JernArc(start=j1 @ 1, tangent=j1 % 1, radius=170, arc_size=90)\n",
|
|
"\n",
|
|
" with BuildSketch(Plane(j2 @ 0, z_dir=j2 % 0)) as x_section:\n",
|
|
" Circle(8)\n",
|
|
" sweep()\n",
|
|
" #sweep(sections=x_section, path=path_builder, transition=Transition.ROUND)\n",
|
|
" signal.label=\"decor\"\n",
|
|
" # convert base to build123d\n",
|
|
" base_b = Solid()\n",
|
|
" base_b.wrapped = base.val().wrapped\n",
|
|
"\n",
|
|
" with BuildPart() as pb:\n",
|
|
" add(base_b)\n",
|
|
" with Locations((0,0,0)):\n",
|
|
" add(signal.part, mode=Mode.SUBTRACT)\n",
|
|
" cut_selection = pb.edges(Select.LAST).filter_by(GeomType.CIRCLE, reverse=True).filter_by(GeomType.LINE, reverse=True).filter_by(GeomType.LINE, reverse=True).sort_by(Axis.Z)[1:]\n",
|
|
" cut_selection = cut_selection[:-3]+cut_selection[-2:]\n",
|
|
" fillet(cut_selection, radius=3)\n",
|
|
" # convert base back to cadquery \n",
|
|
" bases = cq.Solid.makeBox(1,1,1)\n",
|
|
" bases.wrapped = pb.part.solid().wrapped\n",
|
|
" return bases\n",
|
|
" \n",
|
|
"\n",
|
|
"#base = add_ridge(contour, base)bases\n",
|
|
"\n",
|
|
"#show(base, axes=True, axes0=True\n",
|
|
"# , ambient_intensity=1, theme=\"dark\", reset_camera=False\n",
|
|
"# ,tools=True, render_normals=False)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "520092cc-c728-4fa7-89ec-6cfdd14355c8",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c52f5db1-9205-4dc3-86a9-8def844d89eb",
|
|
"metadata": {},
|
|
"source": [
|
|
"# add switches and keycaps"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"id": "6c14a05b-612e-415d-97a4-eab445b680ca",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"mx_switch = (cq.importers.importStep(\"switch.step\")\n",
|
|
" .rotate([0,0,0],[1,0,0], 90)\n",
|
|
" .rotate([0,0,0],[0,0,1], 90)\n",
|
|
" )\n",
|
|
"\n",
|
|
"xda_cap = (cq.importers.importStep(\"xdacap.step\")\n",
|
|
" .translate([67, 0, 6])\n",
|
|
" .val().scale(18.0/17.7)\n",
|
|
" #.rotate([0,0,0],[0,0,1], 90)\n",
|
|
" )\n",
|
|
"\n",
|
|
"#xda_cap + mx_switch"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"id": "71e06b37-3747-4ad8-a777-1a289b329022",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def place_switch(switch, i, j,r):\n",
|
|
" angle = row_phi(column_yoff, radmoda(r))/(pi)*180*(0.5+j)\n",
|
|
" r =radmodp(r)\n",
|
|
" return (cq.Workplane(\"XY\")\n",
|
|
" .workplane(offset=-plate_thickness*0.5)\n",
|
|
" .add(switch)\n",
|
|
" #.translate([0,0,0])\n",
|
|
" .translate([1,(i+0.5)*(column_width)+i*pad, 0])\n",
|
|
" .rotate((0,-50,r),(0,50,r),angle)\n",
|
|
" \n",
|
|
" )\n",
|
|
"\n",
|
|
"def build_switches(model):\n",
|
|
" switches = None\n",
|
|
" for i, r in enumerate(radii):\n",
|
|
" for j in range(4):\n",
|
|
" switch = place_switch(model, i, j, r)\n",
|
|
" switches = switches+switch if switches else switch\n",
|
|
" return switches\n",
|
|
"\n",
|
|
"\n",
|
|
"def place_thumb_switches(switch, r=44):\n",
|
|
" c1 = place_switch(switch, 0, 0,r)+place_switch(switch, 0, 1,r)\n",
|
|
" c2 = position_second_col_thumbplate(c1, r)\n",
|
|
" switches = c1 + c2\n",
|
|
" return position_thumbplate(switches, r)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"id": "467a4986-63f0-4bd3-928a-1095f0619cf5",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"switches = rotate_keyplate(build_switches(mx_switch))\n",
|
|
"caps = rotate_keyplate(build_switches(xda_cap))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"id": "189465d7-ba99-46d3-9642-6991935baa09",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"thumb_switches = place_thumb_switches(mx_switch)\n",
|
|
"thumb_caps = place_thumb_switches(xda_cap)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"id": "68cd5bd3-3f2b-4efd-b8cf-461863ece5ba",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"100% ⋮————————————————————————————————————————————————————————————⋮ (2/2) 0.22s\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<cad_viewer_widget.widget.CadViewer at 0x736c913cc910>"
|
|
]
|
|
},
|
|
"execution_count": 26,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"def testrender():\n",
|
|
" return show(cq.Assembly()\n",
|
|
" #.add(xy_contour, color=webcol_to_cq(\"#11abdda4\"))\n",
|
|
" #.add(thumbcontour, color=webcol_to_cq(\"#ddab11a4\"))\n",
|
|
" #.add(contour, color=webcol_to_cq(\"#33ff6622\"))\n",
|
|
" .add(base, color=webcol_to_cq(\"#33ff66aa\"))\n",
|
|
" #.add(wire_tunnels, color=webcol_to_cq(\"#aa44ff99\"))\n",
|
|
" #.add(thumbplate, color=webcol_to_cq(\"#aa44ff99\"))\n",
|
|
" #.add(buttonplate_cutspace1, color=webcol_to_cq(\"#33abdd4a\"))\n",
|
|
" #.add(thumbplate_cutspace, color=webcol_to_cq(\"#1166ff33\")) \n",
|
|
" #.add(pcb_cutouts, color=webcol_to_cq(\"#aa44ff99\")) \n",
|
|
" #.add(thumb_cutout, color=webcol_to_cq(\"#ff66ff33\"))\n",
|
|
" #.add(handrest_cutout, color=webcol_to_cq(\"#aa110022\")) \n",
|
|
" .add(thumb_handrest_cutout, color=webcol_to_cq(\"#aa440022\"))\n",
|
|
" #.add(thumb_overhang_cutout, color=webcol_to_cq(\"#aa44ff99\"))\n",
|
|
" #.add(thumb_pcb_cutout, color=webcol_to_cq(\"#aa44ff99\"))\n",
|
|
" #.add(buttonplate, color=webcol_to_cq(\"#aa44ff99\"))\n",
|
|
" #.add(raw_buttonplate, color=webcol_to_cq(\"#aa44ff99\"))\n",
|
|
" #.add(hole1, color=webcol_to_cq(\"#ffa22aa44\"))\n",
|
|
" #.add(hole2, color=webcol_to_cq(\"#ffa22aa44\"))\n",
|
|
" #.add(holes, color=webcol_to_cq(\"#ffa22aa44\"))\n",
|
|
" #.add(thumbholes, color=webcol_to_cq(\"#ffa22aa44\"))\n",
|
|
" #.add(thumb_switches, color=webcol_to_cq(\"#00000055\"))\n",
|
|
" #.add(thumb_caps, color=webcol_to_cq(\"#efefef55\"))\n",
|
|
" #.add(buttonplate_bridge, color=webcol_to_cq(\"#ffaa4499\"))\n",
|
|
" #.add(overhang_cutout, color=webcol_to_cq(\"#aa44ff22\"))\n",
|
|
" , axes=True, axes0=True\n",
|
|
" , ambient_intensity=1, theme=\"dark\", reset_camera=False\n",
|
|
" ,tools=True, render_normals=False)\n",
|
|
"\n",
|
|
"testrender()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"id": "3db7cb62-4476-48d9-a12c-b3efb73d6095",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"#base = build_base()\n",
|
|
"#handrest_top = (base.faces(\"<Z\")\n",
|
|
"# .workplane(offset=-26)\n",
|
|
"# .move(0, -40)\n",
|
|
"# .rect(120, endx)\n",
|
|
"# .wires()\n",
|
|
"## .split(keepBottom=True)\n",
|
|
"# .solids(\">X\")\n",
|
|
"# )\n",
|
|
"\n",
|
|
"#dowel = (handrest_top.faces(\"<Z\")\n",
|
|
"# .workplane()\n",
|
|
"# .moveTo(endx-10,0)\n",
|
|
"# .circle(3)\n",
|
|
"# .extrude(40))\n",
|
|
"\n",
|
|
"#bottom_base = base - handrest_top\n",
|
|
"\n",
|
|
"\n",
|
|
"#show(base, handrest_top)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b02cf303-b55b-490d-97c3-1de1a6c88cbe",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Assembly of product"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 28,
|
|
"id": "85894ad4-1f53-4b29-a312-acca8c33e4d0",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"def show_product():\n",
|
|
" product = (\n",
|
|
" cq.Assembly(name=\"keyboard\")\n",
|
|
" #.add(bottom_base, name=\"base\", color=webcol_to_cq(\"#777744ff\")) # transparent alpha = 0x80/0xFF\n",
|
|
" #.add(handrest_top, name=\"blue box\", color=webcol_to_cq(\"#888844ff\")) # transparent, alpha = 0.3\n",
|
|
" .add(base, name=\"base\", color=webcol_to_cq(\"#777744ff\")) # transparent alpha = 0x80/0xFF\n",
|
|
" .add(buttonplate, name=\"plate\", color=webcol_to_cq(\"#121212\"))\n",
|
|
" .add(thumbplate, name=\"tplate\", color=webcol_to_cq(\"#121212\"))\n",
|
|
" .add(switches, name=\"switches\", color=webcol_to_cq(\"#000000ff\"))\n",
|
|
" .add(thumb_switches, name=\"thumbswitches\", color=webcol_to_cq(\"#000000ff\"))\n",
|
|
" .add(caps, name=\"caps\", color=webcol_to_cq(\"#bbbb99ff\"))\n",
|
|
" .add(thumb_caps, name=\"thumbcaps\", color=webcol_to_cq(\"#bbbb99ff\"))\n",
|
|
" .add(usbsocket, name=\"slot\", color=webcol_to_cq(\"#221111ff\"))\n",
|
|
" \n",
|
|
" )\n",
|
|
"\n",
|
|
" cv = show(product, axes=True, grid=[True, False, False], ortho=True, axes0=True, collapse=1)\n",
|
|
" return product"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"id": "2f697a70-ddaf-47b3-8950-9de820cabd15",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"100% ⋮————————————————————————————————————————————————————————————⋮ (8/8) 4.31s\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"keyboard = show_product()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"id": "fae0877e-16f1-46d4-9694-36a62eebd16d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Total generator runtime: 40.31s\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"toc = timeit.default_timer()\n",
|
|
"runtime = toc-tic\n",
|
|
"print(f\"Total generator runtime: {runtime:2.2f}s\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 31,
|
|
"id": "ff3054f9-f0bd-4665-9a5b-bfd658340008",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#assert False\n",
|
|
"#buttonplate = buttonplate - base\n",
|
|
"#buttonplate-buttonplate_cutspace"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c25d4553-ce80-4ff5-9679-09110c5fb86d",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Export models"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 32,
|
|
"id": "4c271c8f-c19e-487d-829a-f0e8ffc1dcee",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"[Errno 17] File exists: 'progress/2025-01-03'\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Statistics on Transfer (Write) ******\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Transfer Mode = 0 I.E. As Is ******\u001b[0m\n",
|
|
"\u001b[32;1m****** Transferring Shape, ShapeType = 0 ******\u001b[0m\n",
|
|
"\u001b[32;1m** WorkSession : Sending all data\u001b[0m\n",
|
|
"\u001b[32;1m Step File Name : progress/2025-01-03/kbbase.step(28394 ents) Write Done\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Statistics on Transfer (Write) ******\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Transfer Mode = 0 I.E. As Is ******\u001b[0m\n",
|
|
"\u001b[32;1m****** Transferring Shape, ShapeType = 0 ******\u001b[0m\n",
|
|
"\u001b[32;1m** WorkSession : Sending all data\u001b[0m\n",
|
|
"\u001b[32;1m Step File Name : progress/2025-01-03/buttonplate.step(31618 ents) Write Done\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Statistics on Transfer (Write) ******\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Transfer Mode = 0 I.E. As Is ******\u001b[0m\n",
|
|
"\u001b[32;1m****** Transferring Shape, ShapeType = 0 ******\u001b[0m\n",
|
|
"\u001b[32;1m** WorkSession : Sending all data\u001b[0m\n",
|
|
"\u001b[32;1m Step File Name : progress/2025-01-03/usbsocket.step(1260 ents) Write Done\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Statistics on Transfer (Write) ******\u001b[0m\n",
|
|
"\u001b[32;1m\n",
|
|
"*******************************************************************\n",
|
|
"****** Transfer Mode = 0 I.E. As Is ******\u001b[0m\n",
|
|
"\u001b[32;1m****** Transferring Shape, ShapeType = 0 ******\u001b[0m\n",
|
|
"export runtime: 7.30s\n",
|
|
"\u001b[32;1m** WorkSession : Sending all data\u001b[0m\n",
|
|
"\u001b[32;1m Step File Name : progress/2025-01-03/thumbplate.step(4565 ents) Write Done\u001b[0m\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"import datetime\n",
|
|
"import os\n",
|
|
"\n",
|
|
"ticc = timeit.default_timer()\n",
|
|
"\n",
|
|
"today = datetime.date.today()\n",
|
|
"basepath = \"progress/\"+today.isoformat()\n",
|
|
"try:\n",
|
|
" os.mkdir(basepath)\n",
|
|
"except FileExistsError as e:\n",
|
|
" print(e)\n",
|
|
"\n",
|
|
"# render stl for rendering in blender\n",
|
|
"cq.exporters.export(base, basepath+\"/kbbase.stl\")\n",
|
|
"#cq.exporters.export(handrest_top, basepath+\"/handrest.stl\")\n",
|
|
"cq.exporters.export(switches+thumb_switches, basepath+'/switches.stl')\n",
|
|
"cq.exporters.export(caps+thumb_caps, basepath+'/caps.stl')\n",
|
|
"cq.exporters.export(buttonplate, basepath+'/buttonplate.stl')\n",
|
|
"cq.exporters.export(usbsocket, basepath+\"/usbsocket.stl\")\n",
|
|
"\n",
|
|
"# render steps for production\n",
|
|
"cq.exporters.export(base, basepath+\"/kbbase.step\")\n",
|
|
"cq.exporters.export(buttonplate, basepath+\"/buttonplate.step\")\n",
|
|
"cq.exporters.export(usbsocket, basepath+\"/usbsocket.step\")\n",
|
|
"cq.exporters.export(thumbplate, basepath+\"/thumbplate.step\")\n",
|
|
"\n",
|
|
"\n",
|
|
"toc = timeit.default_timer()\n",
|
|
"runtime = toc-ticc\n",
|
|
"print(f\"export runtime: {runtime:2.2f}s\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "76401486-d51f-4e6d-87c8-792aac0fd28e",
|
|
"metadata": {},
|
|
"source": [
|
|
"# render svg graphics"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 33,
|
|
"id": "9371eb65-fd98-4bb6-a5f7-8e0f6b901458",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"ename": "AssertionError",
|
|
"evalue": "",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)",
|
|
"Cell \u001b[0;32mIn[33], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#base = build_base()\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 3\u001b[0m ticc \u001b[38;5;241m=\u001b[39m timeit\u001b[38;5;241m.\u001b[39mdefault_timer()\n\u001b[1;32m 4\u001b[0m base1 \u001b[38;5;241m=\u001b[39m base \u001b[38;5;241m+\u001b[39m buttonplate\u001b[38;5;241m.\u001b[39mtranslate([\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m74\u001b[39m]) \u001b[38;5;241m+\u001b[39m switches\u001b[38;5;241m.\u001b[39mtranslate([\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m130\u001b[39m])\n",
|
|
"\u001b[0;31mAssertionError\u001b[0m: "
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"#base = build_base()\n",
|
|
"assert False\n",
|
|
"ticc = timeit.default_timer()\n",
|
|
"base1 = base + buttonplate.translate([0,0,74]) + switches.translate([0,0,130])\n",
|
|
"base1 = base1 + thumb_switches.translate([0,0,130]) +thumb_caps.translate([0,0,180])+ caps.translate([0,0,180])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "1ad8fe33-18c5-4fa2-834d-bab85827bceb",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"hidden_color = (0, 255, 255)\n",
|
|
"stroke_color = (255, 0, 255)\n",
|
|
"stroke_color = (0xc7, 0xf8, 255)\n",
|
|
"#c7f8ffff\n",
|
|
"cq.exporters.export(\n",
|
|
" base1,\n",
|
|
" basepath+\"/smue_explode.svg\",\n",
|
|
" opt={\n",
|
|
" \"width\": 300,\n",
|
|
" \"height\": 300,\n",
|
|
" \"marginLeft\": 10,\n",
|
|
" \"marginTop\": 10,\n",
|
|
" \"showAxes\": False,\n",
|
|
" \"projectionDir\": (100, -20, 70),\n",
|
|
" \"strokeWidth\": 0.25,\n",
|
|
" \"strokeColor\": stroke_color,\n",
|
|
" \"hiddenColor\": hidden_color,\n",
|
|
" \"showHidden\": False,\n",
|
|
" },\n",
|
|
")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "201bab5c-213a-498f-9241-1077343430ce",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"toc = timeit.default_timer()\n",
|
|
"runtime = toc-ticc\n",
|
|
"total_runtime = toc -tic\n",
|
|
"print(f\"svg export runtime: {runtime:2.2f}s\")\n",
|
|
"print(f\"total runtime: {total_runtime:2.2f}s\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "28f7ea15-de5d-4f03-b7cd-3a6930593144",
|
|
"metadata": {},
|
|
"source": [
|
|
"# real finger tip trajectory instead of circles"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "153074b2-8e5c-44e0-b34d-bfbe7ac1b749",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"assert False\n",
|
|
"\n",
|
|
"\n",
|
|
"from numpy import cos, sin, linspace, pi\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from math import atan2\n",
|
|
"\n",
|
|
"\n",
|
|
"# define finger segment sizes\n",
|
|
"40+20+18\n",
|
|
"50+40+20\n",
|
|
"proximal_phalange = 40\n",
|
|
"intermediate_phalange = 20\n",
|
|
"distal_phalange = 18\n",
|
|
"phi_start = pi/4 #45deg\n",
|
|
"phi_end = pi/9 #10deg\n",
|
|
"\n",
|
|
"phi = linspace(phi_start, phi_end)\n",
|
|
"\n",
|
|
"x_proximal = -proximal_phalange * cos(phi) \n",
|
|
"y_proximal = - proximal_phalange * sin(phi)\n",
|
|
"\n",
|
|
"x_intermediate = -intermediate_phalange * cos(2*phi)\n",
|
|
"y_intermediate = -intermediate_phalange * sin(2*phi)\n",
|
|
"\n",
|
|
"x_distal = -distal_phalange * cos(3*phi)\n",
|
|
"y_distal = -distal_phalange * sin(3*phi)\n",
|
|
"\n",
|
|
"x = x_proximal + x_intermediate + x_distal\n",
|
|
"y = y_proximal + y_intermediate + y_distal\n",
|
|
"\n",
|
|
"end_x_dir = x[0] - x[1]\n",
|
|
"end_y_dir = y[0] - y[1]\n",
|
|
"rho = atan2(end_y_dir, end_x_dir)\n",
|
|
"x = x - x[0]\n",
|
|
"y = y - y[0]\n",
|
|
"\n",
|
|
"apts = np.vstack([x, y]).T\n",
|
|
"lengths = np.sqrt(np.sum(np.diff(apts, axis=0)**2, axis=1)) # Length between corners\n",
|
|
"total_length = np.sum(lengths)\n",
|
|
"pts = [tuple(pt) for pt in apts]\n",
|
|
"print(f\"{total_length = :.2f}mm {rho = }\")\n",
|
|
"plt.plot(x,y)\n",
|
|
"\n",
|
|
"path = (cq.Workplane(\"XZ\")\n",
|
|
" .polyline(pts)\n",
|
|
")\n",
|
|
"\n",
|
|
"part = ( cq.Workplane(\"YZ\").rotateAboutCenter([0, 1, 0], rho*2*pi)\n",
|
|
" .rect(column_width, plate_thickness)\n",
|
|
" #.sweep(path)\n",
|
|
")\n",
|
|
"show(part, path)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "ed64e437-0ba6-4957-b8fb-af831e742f55",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"path = (cq.Workplane(\"XZ\")\n",
|
|
" .polyline(pts)\n",
|
|
")\n",
|
|
"\n",
|
|
"part = ( cq.Workplane(\"YZ\").rotateAboutCenter([0, 1, 0], rho*2*pi)\n",
|
|
" .rect(column_width, plate_thickness)\n",
|
|
" #.sweep(path)\n",
|
|
")\n",
|
|
"show(part, path)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8b50622c-c504-4c87-94de-c9493d59d402",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"jupyter": {
|
|
"outputs_hidden": false
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"pts = [(0,0), (0,1), (3,1), (3,0)] # Corners of rectangle of height 1, length 3\n",
|
|
"apts = np.array(pts) # Make it a numpy array\n",
|
|
"lengths = np.sqrt(np.sum(np.diff(apts, axis=0)**2, axis=1)) # Length between corners\n",
|
|
"total_length = np.sum(lengths)\n",
|
|
"apts"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.10.8"
|
|
},
|
|
"name": "smue2.ipynb"
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|