import cadquery as cq import math # Size of the kbd board kbd_height = 95.5 kbd_width = 305 back_thickness = 17 front_thickness = 10 # Pythagoras actual_height = (kbd_height**2 - (back_thickness - front_thickness) ** 2) ** 0.5 kbd_angle = math.acos(actual_height / kbd_height) * 180 / math.pi kbd_pillar_positions = [ (19, 16), (142.5, 25.5), (kbd_width - 20, 16), (23.5, 79.5), (145.5, 82.5), (kbd_width - 19, 79.5), ] elements = [ # Shorter pillars { "x": 0, "y": 0, "z": 5.5, "shape": cq.Sketch().push(kbd_pillar_positions).circle(5, mode="a"), }, # Taller pillars with holes for self-tapping screws { "x": 0, "y": 0, "z": 2.5, "shape": ( cq.Sketch() .push(kbd_pillar_positions) .circle(2.4, mode="a") .circle(1.1, mode="s") ), }, ] def add( *, model, width, height, thickness, offset_x, offset_y, bottom_face, back_face, shell_t ): # This one is special, it creates angled things and cuts off the # case, so ... it's going to do weird stuff if bottom_face: model = ( model.faces(bottom_face) .workplane(centerOption="CenterOfBoundBox", offset=-front_thickness) .center( -width / 2, height / 2, ) .transformed(rotate=cq.Vector(kbd_angle, 0, 0)) .tag("kbd_sloped") ) for element in elements: model = ( model.workplaneFromTagged("kbd_sloped") .center(offset_x + element["x"], -offset_y - element["y"]) .workplane(offset=element["z"]) .placeSketch(element["shape"]) .extrude(100) ) model = ( model.workplaneFromTagged("mid_height") .transformed(offset=cq.Vector(0, 0, -thickness / 2)) .split(keepTop=True) .faces(">X") .workplane(centerOption="CenterOfBoundBox") .center(-height / 2, -thickness / 2) .placeSketch( cq.Sketch().polygon( [ [0, front_thickness], [actual_height, back_thickness], [actual_height, 1000], [0, 1000], [0, front_thickness], ] ) ) .cutBlind(-1000) ) return model