import cadquery2 as cq from cadquery2 import exporters from math import floor, atan, pi # Naming convention # _l means Y # _w means X # _h means Z shell_t = 2 # Shell thickness front_h = 25 # height at the front (near user) back_h = 40 # height at the back (away from user) width = 290 # width of the whole thing fillet_s = 4 # Fillet of case sides kbd_base_l = 150 # length of the front half of the case screen_base_l = 100 # length of the back half of the case kbd_angle = atan((back_h - front_h) / kbd_base_l) * 180 / pi print("kbd_angle=", kbd_angle) # Added an extra 1mm on each direction for tolerance to make sure it slots in kbd_w = 202 # width of the keyboard itself kbd_l = 127 # "length" of the keyboard kbd_h = 4 # depth of the keyboard holder cutoff kbd_fillet = 10 # width of the kbd corner fillet # battery dimensions (mx7) bat_w = 60 bat_l = 140 bat_h = 22 # width, length VISIBLE WITHIN THE BEZEL screen_w = 223 screen_l = 57 screen_left_margin = 10 # Distance from the left of the case to screen cutout # width, length, height INCLUDING_BEZEL display_w = 233 display_l = 65 display_h = 5 # Distance from the left of the case to display end (7 is bezel width on that side) display_left_margin = screen_left_margin - 7 # Distance from the right of the case to display end display_right_margin = width - display_left_margin - display_w # Distance from the top of the case to display top display_top_margin = (screen_base_l - display_l) / 2 display_bottom_margin = display_top_margin # Symmetrical kbd_cutout = ( cq.Sketch().trapezoid(kbd_w, kbd_l, 90).reset().vertices().fillet(kbd_fillet) ) bat_holder_top = ( cq.Sketch() .trapezoid(bat_w + 2 * shell_t, bat_h + 2 * shell_t, 90) .trapezoid(bat_w, bat_h, 90, mode="s") .trapezoid(bat_w + 10, bat_h - 10, 90, mode="s") ) # Base to hold (magnetically?) the keyboard (half the case) kbd_base = ( cq.Workplane("left") .lineTo(0, kbd_base_l) .lineTo(front_h, kbd_base_l) .lineTo(back_h, 0) .close() .extrude(width) .edges("+Z") .fillet(fillet_s) .edges("+Y") .fillet(fillet_s) # Cut kbd holder area from top face .faces(">Z") .workplane(centerOption="CenterOfBoundBox") .center((screen_w - width) / 2 + screen_left_margin, 0) .placeSketch(kbd_cutout) .cutBlind(-kbd_h) # Make it hollow .faces("Y") .shell(-shell_t) # Account for outer shell thickness in offset .faces(">Z") .workplane(offset=-display_h - shell_t) # Add friction shelve for screen assembly .lineTo(-width, 0) .lineTo(-width, -screen_base_l) .lineTo(0, -screen_base_l) .close() .extrude(-shell_t) # Cutout visible screen area from top face .faces(">Z") .workplane(centerOption="CenterOfBoundBox") .center((width - screen_w) / 2 - screen_left_margin, 0) .placeSketch(screen_cutout) .cutBlind(-shell_t) # Cut screen "shelf" to allow for cable routing .faces(">Z") .workplane(centerOption="CenterOfBoundBox", offset=-display_h - shell_t) .placeSketch(shelf_cutout) .cutBlind(-shell_t) # Stop the screen from sliding back and forward .faces(">Y") .workplane(centerOption="CenterOfBoundBox") .center(0, back_h / 2 - display_h - shell_t) .placeSketch(screen_vertical_stop) .extrude(-display_bottom_margin) .faces("X") .workplane(centerOption="CenterOfBoundBox") .center(0, back_h / 2 - display_h - shell_t) .placeSketch(screen_lateral_stop) .extrude(-display_left_margin) .faces("