class Socket(SimpleZenObj): colour = color.cyan size = Size(33.0, 15.0, 12.7 - Pcb.size.z) offset = vector3(0.0, 0.0, Pcb.size.z) room_size = Size(5.7, 2.0, 6.3) def __init__(self): socket = box(size=self.size) room = box(size=self.room_size).moveZ(self.size.z - self.room_size.z) socket = socket - room socket = socket.move(self.offset) super().__init__(socket)
class Battery(SimpleZenObj): colour = color.mech size = Size(26.0, 51.0, 22.0) def __init__(self): battery = box(self.size) super().__init__(battery)
class LcdMount(SimpleZenObj): colour = color.mech size = Size(6.0, 8.0, 4.5) offset = vector3(67.0, 35.0, -2.0) def __init__(self): mount = box(size=self.size).move(self.offset) super().__init__(mount)
class LcdWires(SimpleZenObj): colour = color.mech size = Size(9.5, 3.5, 7.0) offset = vector3(30.5, Pcb.size.y, 0.0) def __init__(self): wires = box(size=self.size).move(self.offset) super().__init__(wires)
class Quartz(SimpleZenObj): colour = color.mech size = Size(4.0, 10.0, 4.0) offset = vector3(48.0, 28.3, -size.z) def __init__(self): quartz = box(size=self.size).move(self.offset) super().__init__(quartz)
class ContactPads(SimpleZenObj): colour = color.mech size = Size(8.0, 15.5, 0.1) offset = vector3(41.3, 1.6, Pcb.size.z) def __init__(self): pads = box(self.size).move(self.offset) super().__init__(pads)
class ButtonMount(SimpleZenObj): colour = color.mech size = Size(9.0, 15.5, 2.5) offset = vector3(Pcb.size.x - 11.5, 0.0, -size.z) def __init__(self): mount = box(self.size).move(self.offset) super().__init__(mount)
class SocketTerminals(SimpleZenObj): colour = color.mech size = Size(17.5, 11.0, 2.5) offset = vector3(9.0, 2.0, -size.z) def __init__(self): terminals = box(self.size).move(self.offset) super().__init__(terminals)
class LcdScreen(SimpleZenObj): colour = color.green size = Size(54.0, 30.0, 0.4) offset = vector3( Lcd.offset.x + (Lcd.size.x - size.x) / 2.0, Lcd.offset.y + 1.0, Lcd.offset.z + Lcd.size.z ) def __init__(self): lcd = box(size=self.size).move(self.offset) super().__init__(lcd)
class Lcd(SimpleZenObj): colour = color(0.0, 0.4, 0.0) size = Size(58.6, 38.5, 6.6 - Pcb.size.z) offset = vector3( 6.5, Pcb.size.y - size.y, Pcb.size.z ) def __init__(self): lcd = box(size=self.size).move(self.offset) super().__init__(lcd)
class Button(SimpleZenObj): colour = color(0.2, 0.2, 0.2) size = Size(12.0, 12.0, 4.6 - Pcb.size.z) offset = vector3( Pcb.size.x - size.x - 1.1, 1.8, Pcb.size.z ) def __init__(self): button = box(size=self.size).move(self.offset) super().__init__(button)
class CaseProperties(object): default_margin = 1.0 pcb_margin = 1.8 battery_margin = 0.4 socket_margin = 0.36 button_cap_margin = 0.36 screen_margin = 1.0 contact_pads_margin = 2.2 screw_length_margin = 1.0 screw_radius_margin = 0.2 screw_cap_margin = 0.5 smd_margin = 3.0 screw_mount_width = 2.0 case_mount_width = 1.5 case_mount_height = 2.0 battery_wall_width = 4 battery_wall_offset_x = pcb_margin + LcdMount.offset.x + LcdMount.size.x + pcb_margin size = Size( battery_wall_offset_x + battery_wall_width + battery_margin + Battery.size.x + battery_margin, pcb_margin + Pcb.size.y + LcdWires.size.y + pcb_margin, EPS + Battery.size.z + battery_margin) width = 3.1 pcb_offset = vector3(pcb_margin, pcb_margin, size.z + width - Pcb.size.z - Socket.size.z) screw_black_mount_rounding_width = 1.0 screw_black_mount_width = (ScrewBlack.cap_r * 2 + screw_cap_margin * 4 + case_mount_width + screw_black_mount_rounding_width * 2) screw_black_offset = vector3( size.x - screw_cap_margin * 2 - ScrewBlack.cap_r - screw_black_mount_rounding_width, screw_cap_margin * 2 + ScrewBlack.cap_r + screw_black_mount_rounding_width, pcb_offset.z + Pcb.size.z - case_mount_height) battery_offset = vector3( battery_wall_offset_x + battery_wall_width + battery_margin, screw_black_mount_width + EPS, EPS) battery_frame_height = 1.5 battery_frame_width = 1.5
class Pcb(SimpleZenObj): colour = color.yellow size = Size(72.5, 60.1, 1.3) hole_r = 3.5 / 2.0 hole_vector_nw = vector3(hole_r + 1.1, size.y - hole_r - 1.5, 0.0) hole_vector_sw = vector3(hole_r + 1.1, size.y - hole_r - 39.0, 0.0) hole_vector_ne = vector3(size.x - hole_r - 1.1, size.y - hole_r - 1.5, 0.0) hole_vector_se = vector3(size.x - hole_r - 1.1, size.y - hole_r - 39.0, 0.0) hole_vectors = [hole_vector_nw, hole_vector_sw, hole_vector_ne, hole_vector_se] def __init__(self): pcb = box(size=self.size) hole_proto = cylinder(r=self.hole_r, h=self.size.z + EPS2).moveZ(-EPS) for v in self.hole_vectors: pcb = pcb - hole_proto.move(v) super().__init__(pcb)
class PowerTerminals(SimpleZenObj): colour = color.mech size = Size(5.0, 9.0, 1.5) offset = vector3(0.5, 26.5, -size.z) wires_radius = 3.5 / 2.0 wires_height = 3.5 wires_offset = vector3( offset.x + size.x / 2.0, offset.y + wires_radius, -wires_height ) def __init__(self): terminals = ( box(self.size).move(self.offset) + cylinder(r=self.wires_radius, h=self.wires_height).move(self.wires_offset) ) super().__init__(terminals)
class CaseTop(SimpleZenObj): colour = color.white size = Size(CaseProperties.size.x, CaseProperties.size.y, EPS) offset_z = CaseProperties.size.z - size.z bottom_center = (size.x / 2, size.y / 2, 0.0) def __init__(self, device, battery): """ :type device: Device :type battery: Battery """ case = thicksolid(proto=box(size=self.size), t=CaseProperties.width, refs=[self.bottom_center]) case = case.moveZ(self.offset_z) battery_wall = box(size=(CaseProperties.battery_wall_width, self.size.y + EPS2, EPS + EPS)).move( vector3( CaseProperties.battery_wall_offset_x, -EPS, self.offset_z)) case = case + battery_wall screen_frame_width = (CaseProperties.size.z - device.lcd_screen.bbox().zmax - CaseProperties.screen_margin) screen_frame = box( size=(CaseProperties.battery_wall_offset_x - EPS2, self.size.y - EPS2, screen_frame_width + EPS)).move( vector3(EPS, EPS, CaseProperties.size.z - screen_frame_width)) screen_frame_filler = box(size=(CaseProperties.battery_wall_offset_x + EPS2, self.size.y + EPS2, self.size.z + EPS)).move( vector3(-EPS, -EPS, self.offset_z)) case = case + screen_frame_filler + screen_frame controls_frame = box(size=( CaseProperties.battery_wall_offset_x - EPS2, device.lcd.bbox().ymin - CaseProperties.default_margin - EPS, # full contact with PCB, no gaps CaseProperties.size.z - device.pcb.bbox().zmax + EPS)).move( vector3(EPS, EPS, device.pcb.bbox().zmax)) case = case + controls_frame battery_frame = box(size=( CaseProperties.size.x - CaseProperties.battery_wall_offset_x - CaseProperties.battery_wall_width - EPS2, CaseProperties.size.y - EPS2, CaseProperties.battery_frame_height + EPS)) - box(size=( CaseProperties.size.x - CaseProperties.battery_wall_offset_x - CaseProperties.battery_wall_width, CaseProperties.size.y - EPS2 - CaseProperties.battery_frame_width * 2, CaseProperties.battery_frame_height + EPS2)).move( vector3(-EPS, CaseProperties.battery_frame_width, -EPS)) battery_frame = battery_frame.move( vector3( CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width + EPS, EPS, CaseProperties.size.z - CaseProperties.battery_frame_height)) case = case + battery_frame for info in CaseScrews.screw_info_dict.values(): screw_mount_offset = vector3(info.screw_offset.x, info.screw_offset.y, device.pcb.bbox().zmax) screw_mount = cylinder( r=info.screw_class.radius + CaseProperties.screw_mount_width, # full contact with PCB, no gaps h=CaseProperties.size.z - device.pcb.bbox().zmax + EPS).move(screw_mount_offset) case = case + screw_mount screw_layer_width = device.pcb.bbox().zmax - info.screw_offset.z screw_hole = cylinder( r=info.screw_class.radius, h=info.screw_class.length - screw_layer_width + CaseProperties.screw_length_margin).move(screw_mount_offset) case = case - screw_hole case = unify(case) socket_bbox = device.socket.bbox().with_border( CaseProperties.socket_margin) lever_hole = box( size=(CaseProperties.width + CaseProperties.pcb_margin + EPS2, Socket.room_size.y + CaseProperties.socket_margin * 2, Socket.room_size.z + CaseProperties.socket_margin * 2)).move( vector3( -CaseProperties.width - EPS, socket_bbox.offset.y, socket_bbox.offset.z + socket_bbox.size.z - Socket.room_size.z - CaseProperties.socket_margin)) socket_hole = box(socket_bbox.size).move(socket_bbox.offset) case = case - socket_hole - lever_hole cap_bbox = device.button_cap.bbox() # type: BBox cap_hole = cylinder( r=ButtonCap.radius + CaseProperties.button_cap_margin, h=ButtonCap.height).move( vector3(cap_bbox.center_offset.x, cap_bbox.center_offset.y, cap_bbox.zmax - ButtonCap.height)) case = case - cap_hole button_hole = box( size=(cap_bbox.size.x + CaseProperties.default_margin * 2, cap_bbox.size.y + CaseProperties.default_margin * 2, CaseProperties.size.z - device.pcb.bbox().zmax)).move( vector3( cap_bbox.offset.x - CaseProperties.default_margin, cap_bbox.offset.y - CaseProperties.default_margin, device.pcb.bbox().zmax)) case = case - button_hole screen_bbox = device.lcd_screen.bbox() # type: BBox screen_hole = box(size=(screen_bbox.size.x - EPS2, screen_bbox.size.y - EPS2, CaseProperties.size.z + CaseProperties.width - screen_bbox.zmax + EPS)).move( vector3(screen_bbox.xmin + EPS, screen_bbox.ymin + EPS, screen_bbox.zmax)) case = case - screen_hole contact_pads_bbox = device.contact_pads.bbox() # type: BBox contact_pads_bbox = contact_pads_bbox.with_border_x( CaseProperties.contact_pads_margin) contact_pads_bbox = contact_pads_bbox.with_border_y( CaseProperties.contact_pads_margin) contact_pads_bbox = contact_pads_bbox.with_border_z(EPS) contact_pads_hole = box( size=(contact_pads_bbox.size.x, contact_pads_bbox.ymax + CaseProperties.width + EPS, CaseProperties.size.z + CaseProperties.width - contact_pads_bbox.zmin)).move( vector3(contact_pads_bbox.offset.x, -CaseProperties.width - EPS, contact_pads_bbox.zmin)) case = case - contact_pads_hole lcd_screen_bbox = device.lcd_screen.bbox() # type: BBox case = fillet( case, r=CaseProperties.width / 2, refs=points([ (contact_pads_bbox.center_offset.x, contact_pads_bbox.ymax, CaseProperties.size.z + CaseProperties.width), (contact_pads_bbox.xmin, 1, CaseProperties.size.z + CaseProperties.width), (contact_pads_bbox.xmax, 1, CaseProperties.size.z + CaseProperties.width), (cap_bbox.center_offset.x, cap_bbox.center_offset.y, cap_bbox.zmax), (lcd_screen_bbox.xmin, lcd_screen_bbox.center_offset.y, CaseProperties.size.z + CaseProperties.width), (lcd_screen_bbox.xmax, lcd_screen_bbox.center_offset.y, CaseProperties.size.z + CaseProperties.width), (lcd_screen_bbox.center_offset.x, lcd_screen_bbox.ymin, CaseProperties.size.z + CaseProperties.width), (lcd_screen_bbox.center_offset.x, lcd_screen_bbox.ymax, CaseProperties.size.z + CaseProperties.width), ])) socket_bbox = device.socket.bbox() # type: BBox case = fillet(case, r=1.4, refs=points([ (socket_bbox.xmin, socket_bbox.center_offset.y, socket_bbox.zmax), (socket_bbox.xmax, socket_bbox.center_offset.y, socket_bbox.zmax), (socket_bbox.center_offset.x, socket_bbox.ymin, socket_bbox.zmax), (socket_bbox.center_offset.x, socket_bbox.ymax, socket_bbox.zmax), (0.01, socket_bbox.ymin + Socket.room_size.y + CaseProperties.socket_margin, socket_bbox.zmax), ])) case = fillet(case, r=1.0, refs=points([ (0, 0, CaseProperties.size.z - 0.5), (0, CaseProperties.size.y, CaseProperties.size.z - 0.5), (CaseProperties.battery_wall_offset_x, 0, CaseProperties.size.z - 0.5), (CaseProperties.battery_wall_offset_x, CaseProperties.size.y, CaseProperties.size.z - 0.5), (CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width, 0, CaseProperties.size.z - 0.5), (CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width, CaseProperties.size.y, CaseProperties.size.z - 0.5), (CaseProperties.size.x, 0, CaseProperties.size.z - 0.5), (CaseProperties.size.x, CaseProperties.size.y, CaseProperties.size.z - 0.5), ])) super().__init__(case)
class CaseBottom(SimpleZenObj): colour = color.white size = Size(CaseProperties.size.x, CaseProperties.size.y, CaseProperties.size.z - EPS) top_center = (size.x / 2, size.y / 2, size.z) def __init__(self, device, battery): """ :type device: Device :type battery: Battery """ case = thicksolid(proto=box(size=self.size), t=CaseProperties.width, refs=[self.top_center]) battery_wall = box(size=(CaseProperties.battery_wall_width, self.size.y + EPS2, self.size.z + EPS)).move( vector3( CaseProperties.battery_wall_offset_x, -EPS, -EPS)) case = case + battery_wall pcb_bed = box(size=( CaseProperties.battery_wall_offset_x + EPS2, self.size.y + EPS2, device.pcb.bbox().zmin + EPS # full contact with PCB, no gaps )).move(vector3(-EPS, -EPS, -EPS)) case = case + pcb_bed screw_black_mount = box( size=(CaseProperties.screw_black_mount_width + EPS, CaseProperties.screw_black_mount_width + EPS, device.pcb.bbox().zmax + EPS)).move( vector3( CaseProperties.size.x - CaseProperties.screw_black_mount_width, -EPS, -EPS)) case = case + screw_black_mount case = unify(case) socket_bbox = device.socket.bbox().with_border( CaseProperties.socket_margin) lever_hole = box( size=(CaseProperties.width + EPS2, Socket.room_size.y + CaseProperties.socket_margin * 2, Socket.room_size.z + CaseProperties.socket_margin * 2)).move( vector3( -CaseProperties.width - EPS, socket_bbox.offset.y, socket_bbox.offset.z + socket_bbox.size.z - Socket.room_size.z - CaseProperties.socket_margin)) case = case - lever_hole contact_pads_bbox = device.contact_pads.bbox() # type: BBox contact_pads_bbox = contact_pads_bbox.with_border_x( CaseProperties.contact_pads_margin) contact_pads_bbox = contact_pads_bbox.with_border_y( CaseProperties.contact_pads_margin) contact_pads_bbox = contact_pads_bbox.with_border_z(EPS) contact_pads_hole = box( size=(contact_pads_bbox.size.x, contact_pads_bbox.ymax + CaseProperties.width + EPS, CaseProperties.size.z + CaseProperties.width - contact_pads_bbox.zmin)).move( vector3(contact_pads_bbox.offset.x, -CaseProperties.width - EPS, contact_pads_bbox.zmin)) case = case - contact_pads_hole contact_pads_hole = box( size=(contact_pads_bbox.size.x, contact_pads_bbox.size.y - CaseProperties.pcb_margin - CaseProperties.default_margin, CaseProperties.smd_margin)).move( vector3( contact_pads_bbox.offset.x, contact_pads_bbox.offset.y + CaseProperties.pcb_margin + CaseProperties.default_margin, device.pcb.bbox().zmin - CaseProperties.smd_margin)) case = case - contact_pads_hole power_terminals_bbox = device.power_terminals.bbox() # type: BBox surface_mount_bbox = device.surface_mount.bbox() # type: BBox lcd_mount_bbox = device.lcd_mount.bbox() # type: BBox smd_hole_points = points([ (power_terminals_bbox.xmin - CaseProperties.default_margin, power_terminals_bbox.ymax + CaseProperties.default_margin, 0), (surface_mount_bbox.xmin - CaseProperties.default_margin, surface_mount_bbox.ymax + CaseProperties.default_margin, 0), (surface_mount_bbox.xmax + CaseProperties.default_margin, surface_mount_bbox.ymax + CaseProperties.default_margin, 0), (lcd_mount_bbox.xmax + CaseProperties.default_margin, lcd_mount_bbox.ymax + CaseProperties.default_margin, 0), (lcd_mount_bbox.xmax + CaseProperties.default_margin, lcd_mount_bbox.ymin - CaseProperties.default_margin, 0), (surface_mount_bbox.xmax + CaseProperties.default_margin, surface_mount_bbox.ymin - CaseProperties.default_margin, 0), (surface_mount_bbox.xmin - CaseProperties.default_margin, surface_mount_bbox.ymin - CaseProperties.default_margin, 0), (surface_mount_bbox.xmin - CaseProperties.default_margin, power_terminals_bbox.ymin - CaseProperties.default_margin, 0), (power_terminals_bbox.xmin - CaseProperties.default_margin, power_terminals_bbox.ymin - CaseProperties.default_margin, 0) ]) smd_hole = extrude( proto=polysegment(smd_hole_points, closed=True).fill(), vec=CaseProperties.smd_margin).moveZ(device.pcb.bbox().zmin - CaseProperties.smd_margin) case = case - smd_hole for obj in [ device.quarts, device.socket_terminals, device.button_mount, ]: case = case - obj.bbox().with_border( CaseProperties.default_margin).to_zen_box() lock_bbox = device.lcd_lock1.bbox() # type: BBox case = case - (cylinder( r=LcdLock1.radius + CaseProperties.default_margin, h=LcdLock1.height + 2 * CaseProperties.default_margin, center=True).move(lock_bbox.center_offset)) lock_bbox = device.lcd_lock2.bbox() # type: BBox case = case - (cylinder( r=LcdLock2.radius + CaseProperties.default_margin, h=LcdLock2.height + 2 * CaseProperties.default_margin, center=True).move(lock_bbox.center_offset)) lcd_wires_bbox = device.lcd_wires.bbox() # type: BBox lcd_wires_bbox = lcd_wires_bbox.with_border_x( CaseProperties.default_margin) lcd_wires_bbox = lcd_wires_bbox.with_border_y( CaseProperties.default_margin) lcd_wires_hole = box( size=(lcd_wires_bbox.size.x, lcd_wires_bbox.size.y, lcd_wires_bbox.size.z + CaseProperties.smd_margin)).move( vector3( lcd_wires_bbox.offset.x, lcd_wires_bbox.offset.y, lcd_wires_bbox.offset.z - CaseProperties.smd_margin)) case = case - lcd_wires_hole power_terminals_bbox = device.power_terminals.bbox() # type: BBox power_terminals_bbox = power_terminals_bbox.with_border( CaseProperties.default_margin) battery_wires_hole = cylinder( r=PowerTerminals.wires_radius + CaseProperties.default_margin, h=device.pcb.bbox().zmin).move( vector3( CaseProperties.pcb_offset.x + PowerTerminals.wires_offset.x, CaseProperties.pcb_offset.y + PowerTerminals.wires_offset.y, 0.0)) case = case - battery_wires_hole battery_wires_channel = box(size=( (CaseProperties.battery_offset.x - power_terminals_bbox.xmin) / cos(deg(-15)), PowerTerminals.wires_radius * 2 + CaseProperties.default_margin * 2, CaseProperties.size.z + EPS2)).moveY(-PowerTerminals.wires_radius - CaseProperties.default_margin).rotateZ(deg(-15)).move( vector3( CaseProperties.pcb_offset.x + PowerTerminals.wires_offset.x, CaseProperties.pcb_offset.y + PowerTerminals.wires_offset.y, 0.0)) case = case - battery_wires_channel for info in CaseScrews.screw_info_dict.values(): screw_hole_h = info.screw_offset.z + CaseProperties.width + EPS screw_mount = cone( r1=(info.screw_class.cap_r + CaseProperties.screw_cap_margin * 2 + CaseProperties.case_mount_width), r2=(info.screw_class.cap_r + CaseProperties.screw_cap_margin + CaseProperties.case_mount_width), h=screw_hole_h + CaseProperties.case_mount_height - CaseProperties.width).move( info.screw_offset).moveZ(-screw_hole_h + CaseProperties.width) case = case + screw_mount screw_hole = cone( r1=info.screw_class.cap_r + CaseProperties.screw_cap_margin * 2, r2=info.screw_class.cap_r + CaseProperties.screw_cap_margin, h=screw_hole_h).move(info.screw_offset).moveZ(-screw_hole_h) case = case - screw_hole screw_hole = cylinder( r=info.screw_class.radius + CaseProperties.screw_radius_margin, h=CaseProperties.case_mount_height + EPS2).move( info.screw_offset).moveZ(-EPS) case = case - screw_hole case = unify(case) case = fillet(case, r=CaseProperties.width / 2, refs=points([ (contact_pads_bbox.center_offset.x, -CaseProperties.width, contact_pads_bbox.zmin), (contact_pads_bbox.xmin, -CaseProperties.width, contact_pads_bbox.zmin + 1), (contact_pads_bbox.xmax, -CaseProperties.width, contact_pads_bbox.zmin + 1), ])) socket_bbox = device.socket.bbox() # type: BBox case = fillet( case, r=1.4, refs=points([ (-CaseProperties.width, socket_bbox.ymin, CaseProperties.size.z - 1), (-CaseProperties.width, socket_bbox.ymin + Socket.room_size.y + CaseProperties.socket_margin, CaseProperties.size.z - 1), (-CaseProperties.width, socket_bbox.ymin + (Socket.room_size.y + CaseProperties.socket_margin) / 2.0, CaseProperties.size.z + CaseProperties.width - Socket.room_size.z), ])) case = fillet(case, r=1.0, refs=points([ (info.screw_offset.x, info.screw_offset.y, -CaseProperties.width - 1) for info in CaseScrews.screw_info_dict.values() ])) case = fillet(case, r=1.4, refs=points([ (CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width, 0, 5), (CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width, 7, 5), (CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width, 10, 5), (CaseProperties.battery_wall_offset_x + CaseProperties.battery_wall_width, CaseProperties.size.y, 5), (CaseProperties.size.x, CaseProperties.size.y, 5), (CaseProperties.size.x - CaseProperties.screw_black_mount_width, CaseProperties.screw_black_mount_width, 5), (CaseProperties.size.x - CaseProperties.screw_black_mount_width / 2, CaseProperties.screw_black_mount_width, device.pcb.bbox().zmax), (CaseProperties.size.x - CaseProperties.screw_black_mount_width, CaseProperties.screw_black_mount_width / 2, device.pcb.bbox().zmax), ])) super().__init__(case)