import cadquery as cq usb_h = 10.5 usb_v = 5.2 socket_distance_x = 10.8 socket_distance_y = 36.55 socket_width = 28 # the width of the bezel on the side of the inner relay side_bezel_width = 3.14 # how far the plug in the middle is from the side # where the socket that powers the relay coil is distance_from_socket_to_end = 46 relay_x_size = 120.2 relay_y_size = 168 # dimensions of the socket for coil power on the side end_socket_width = 30.4 end_socket_height = 22.6 # the distance from the side of the socket to the edge of the box # for the socket that powers the relay coil end_socket_distance_from_side = 3.47 + 3 # add 3mm for tape reset_button_dist_from_socket = 5.27 reset_width = 18.7 reset_height = 35.04 reset_lip_height = 3.37 # probably not needed # parameter definitions p_outerWidth = relay_x_size + 15 # Outer width of box enclosure p_outerLength = relay_y_size # Outer length of box enclosure p_outerHeight = 33.6 + 30 # Outer height of box enclosure p_thickness = 3.0 # Thickness of the box walls p_sideRadius = 10.0 # Radius for the curves around the sides of the box p_topAndBottomRadius = ( 2.0 # Radius for the curves on the top and bottom edges of the box ) p_screwpostInset = 12.0 # How far in from the edges the screw posts should be place. p_screwpostID = 4.0 # Inner Diameter of the screw post holes, should be roughly screw diameter not including threads p_screwpostOD = 10.0 # Outer Diameter of the screw posts.\nDetermines overall thickness of the posts p_boreDiameter = 8.0 # Diameter of the counterbore hole, if any p_boreDepth = 1.0 # Depth of the counterbore hole, if p_countersinkDiameter = 0.0 # Outer diameter of countersink. Should roughly match the outer diameter of the screw head p_countersinkAngle = 90.0 # Countersink angle (complete angle between opposite sides, not from center to one side) p_flipLid = True # Whether to place the lid with the top facing down or not. p_lipHeight = 1.0 # Height of lip on the underside of the lid.\nSits inside the box body for a snug fit. # outer shell oshell = ( cq.Workplane("XY") .rect(p_outerWidth, p_outerLength) .extrude(p_outerHeight + p_lipHeight) ) # weird geometry happens if we make the fillets in the wrong order if p_sideRadius > p_topAndBottomRadius: oshell = oshell.edges("|Z").fillet(p_sideRadius) oshell = oshell.edges("#Z").fillet(p_topAndBottomRadius) else: oshell = oshell.edges("#Z").fillet(p_topAndBottomRadius) oshell = oshell.edges("|Z").fillet(p_sideRadius) # inner shell ishell = ( oshell.faces("Z") .workplane(-p_thickness) .rect(POSTWIDTH, POSTLENGTH, forConstruction=True) .vertices() .circle(p_screwpostOD / 2.0) .circle(p_screwpostID / 2.0) .extrude(-1.0 * (p_outerHeight + p_lipHeight - p_thickness), True) ) # split lid into top and bottom parts (lid, bottom) = ( box.faces(">Z") .workplane(-p_thickness - p_lipHeight) .split(keepTop=True, keepBottom=True) .all() ) # splits into two solids lid = ( lid.workplane() .rect( socket_width + socket_distance_x, socket_distance_y + (socket_width), forConstruction=True, ) .tag("sockets") .vertices() .rect(socket_width, socket_width) .cutThruAll() ) bottom = ( bottom.faces(">Y") .workplane() .center(0, -end_socket_height + 8) .rect(end_socket_width, end_socket_height) .cutBlind("next") ) holes = ( cq.Workplane("XY") .rect((p_outerWidth - 20.0 * p_thickness), (p_outerLength - 20.0 * p_thickness)) .vertices() .cylinder(10, 3.1 / 2) ) bottom = bottom.cut(holes) bottom = ( bottom.faces(">Y[0]") .workplane(offset=0) .move(0, -(p_outerHeight / 2) - usb_v - 3.3) .box(usb_h, usb_v, 10, combine="cut") ) # lid = (lid.center(socket_width-8, socket_distance_y+(socket_width)-3) # .rect(reset_height, reset_width) # .cutThruAll()) # translate the lid, and subtract the bottom from it to produce the lid inset lowerLid = lid.translate((0, 0, -p_lipHeight)) cutlip = lowerLid.cut(bottom).translate( (p_outerWidth + p_thickness, 0, p_thickness - p_outerHeight + p_lipHeight) ) # compute centers for screw holes topOfLidCenters = ( cutlip.faces(">Z") .workplane(centerOption="CenterOfMass") .rect(POSTWIDTH, POSTLENGTH, forConstruction=True) .vertices() ) # add holes of the desired type if p_boreDiameter > 0 and p_boreDepth > 0: print("first") topOfLid = topOfLidCenters.cboreHole( p_screwpostID, p_boreDiameter, p_boreDepth, 2.0 * p_thickness ) elif p_countersinkDiameter > 0 and p_countersinkAngle > 0: print("second") topOfLid = topOfLidCenters.cskHole( p_screwpostID, p_countersinkDiameter, p_countersinkAngle, 2.0 * p_thickness ) else: print("third") topOfLid = topOfLidCenters.hole(p_screwpostID, 2.0 * p_thickness) # flip lid upside down if desired if p_flipLid: topOfLid = topOfLid.rotateAboutCenter((1, 0, 0), 180) # return the combined result result = topOfLid.union(bottom) cq.exporters.export(bottom, "/home/deck/model_files/enclosure_bottom.step") cq.exporters.export(topOfLid, "/home/deck/model_files/enclosure_lid.step") try: show_object(bottom) except NameError: pass