{ "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(\"Y\").val().outerWire()\n", " right_finger_left_face = fingers[i+1].faces(\"Y\")#.edges(\">Z\")#.fillet(1)\n", " \n", " )\n", " cutout = rotate_keyplate(cutout).faces(\"Y\").edges(\"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\").wires().val()\n", " f1 = c1.faces(\">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(\">X[2]\")\n", " #.edges(\"|Z and >>X[2]\").fillet(10)\n", " .edges(\"|Z and >>Y[2]\").fillet(30)\n", " .edges(\"|Z and <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\").edges(\"<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(\"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(\"<Z\").fillet(12)\n", " .edges(\"|Z and >>Y[0]\").fillet(5)\n", " .faces(\">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(\"" ] }, "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(\"X\")\n", "# )\n", "\n", "#dowel = (handrest_top.faces(\" 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 }