Initial import

This commit is contained in:
2023-04-15 20:35:47 -03:00
commit ee43cc02de
37 changed files with 6842 additions and 0 deletions

0
components/__init__.py Normal file
View File

86
components/audio_plug.py Normal file
View File

@ -0,0 +1,86 @@
# Hole to expose a USB audio card (YMMV)
import cadquery as cq
from utils import extrude_shape, punch_hole
# The hole is for a random USB sound card.
# Consumers should set proper offsets for the hole
item_w = 49
item_h = 20.5
hole_w = 17
hole_h = 5
holes = [
# 2-jack plug
{
"x": -item_h / 2,
"y": 4,
"shape": cq.Sketch()
.trapezoid(hole_w, hole_h, 90, mode="a")
.vertices()
.fillet(2),
},
]
elements = [
# Outline
{
"x": item_w / 2,
"y": item_h / 2,
"shape": (
cq.Sketch()
.trapezoid(item_w, item_h, 90, mode="a")
.trapezoid(item_w - 2, item_h - 2, 90, mode="s")
),
"height": 0.2,
},
]
def add(
*,
model,
width,
height,
thickness,
offset_x,
offset_y,
bottom_face,
back_face,
shell_t
):
# Extrusions
if bottom_face:
for element in elements:
model = extrude_shape(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x,
y_offset=offset_y,
element=element,
height=-(element["height"] + shell_t),
)
# Holes
if back_face:
for hole in holes:
model = punch_hole(
model=model,
face=back_face,
# FIXME: This is weird because it's the RIGHT side,
# So it's height instead of w, offset_y instead of x
# need to work on making these coherent
w=height,
h=thickness,
x_offset=height - offset_y,
y_offset=shell_t,
hole=hole,
depth=shell_t,
)
return model

View File

@ -0,0 +1,150 @@
import cadquery as cq
from utils import extrude_shape, punch_hole, hex_vents
stand_positions = [(3.5, 3.5), (61.5, 3.5), (61.5, 52.5), (3.5, 52.5)]
stands = (
cq.Sketch().push(stand_positions).circle(3, mode="a").circle(2.65 / 2, mode="s")
)
pillar_height = 7
width = 85
height = 56
# This is a holder for DuPont cables so they connect to this
# things' pogo pins which are used to power the CPU
pin_positions = [(3.5, 0), (4 * 2.54 + 3.5, 0)]
pin_holder_width = 25
pin_holder_height = 15
pin_holder = (
cq.Sketch()
.polygon(
[
(0.5, 0),
(pin_holder_width, 0),
(pin_holder_width, pin_holder_height),
(0, pin_holder_height),
(0.5, 0),
],
mode="a",
)
.push(pin_positions)
.polygon(
[(0, 0), (2.6, 0), (2.6, pin_holder_height), (0, pin_holder_height), (0, 0)],
mode="s",
)
)
elements = [
# Battery holder stands
{
"x": 0,
"y": 0,
"shape": stands,
"height": pillar_height,
},
{
"x": 0,
"y": 0,
"shape": cq.Sketch().push(stand_positions).circle(5),
"height": 0,
},
# Pogo pin connector channels
{
"x": 3.5,
"y": 43.5,
"shape": pin_holder,
"height": 3,
},
# Perimeter
{
"x": width / 2,
"y": height / 2,
"shape": (
cq.Sketch()
.trapezoid(width, height, 90, mode="a")
.trapezoid(width - 2, height - 2, 90, mode="s")
.vertices()
.fillet(3)
),
"height": 0.2,
},
]
vents = hex_vents(size=3, width=width, height=height)
# Hole distances are relative to the rightmost pillar
# seen from the back of the case, that's why they are negative
# Heights are relative to base of pillars
# All distances are measured to the CENTER of the hole
holes = [
# Power inlet
{
"x": -18.5,
"y": -1 + pillar_height,
"shape": cq.Sketch().trapezoid(12, 6.5, 90, mode="a").vertices().fillet(1),
},
# Power button
{
"x": -70,
"y": 5.5 + pillar_height,
"shape": cq.Sketch().trapezoid(7, 7, 90, mode="a").vertices().fillet(1),
},
]
def add(
*,
model,
width,
height,
thickness,
offset_x,
offset_y,
bottom_face,
back_face,
shell_t
):
if bottom_face:
# Vents
for vent in vents:
model = punch_hole(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x + vent["x"],
y_offset=shell_t + offset_y + vent["y"],
hole=vent,
depth=shell_t,
)
# Battery holder stands and pogo pin holder
for element in elements:
model = extrude_shape(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x,
y_offset=shell_t + offset_y,
element=element,
height=-(element["height"] + shell_t),
)
if back_face:
# Holes
for hole in holes:
model = punch_hole(
model=model,
face=back_face,
w=width,
h=thickness,
x_offset=width - offset_x,
y_offset=shell_t,
hole=hole,
depth=shell_t,
)
return model

46
components/hdmi_out.py Normal file
View File

@ -0,0 +1,46 @@
# Hole to expose a USB audio card (YMMV)
import cadquery as cq
from utils import punch_hole
# The hole is for a random USB sound card.
# Consumers should set proper offsets for the hole
holes = [
# Hole for HDMI female adapter
{
"x": 0,
"y": 7,
"shape": cq.Sketch().trapezoid(22, 12.5, 90, mode="a").vertices().fillet(2),
},
]
def add(
*,
model,
width,
height,
thickness,
offset_x,
offset_y,
bottom_face,
back_face,
shell_t
):
# Holes
if back_face:
for hole in holes:
model = punch_hole(
model=model,
face=back_face,
w=width,
h=thickness,
x_offset=width - offset_x,
y_offset=shell_t,
hole=hole,
depth=shell_t,
)
return model

101
components/keyboard.py Normal file
View File

@ -0,0 +1,101 @@
import cadquery as cq
# These should be set from dimensions.py
elements = None
kbd_pillar_positions = []
kbd_height = 0
kbd_width = 0
kbd_back_thickness = 0
kbd_front_thickness = 0
kbd_actual_height = 0
kbd_angle = 0
kbd_pillar_offset_1 = 0
kbd_pillar_radius_1 = 0
kbd_pillar_offset_2 = 0
kbd_pillar_radius_2 = 0
kbd_screw_radius = 0
def init():
global elements
elements = [
# Shorter pillars
{
"x": 0,
"y": 0,
"z": kbd_pillar_offset_1,
"shape": cq.Sketch().push(kbd_pillar_positions).circle(kbd_pillar_radius_1, mode="a"),
},
# Taller pillars with holes for self-tapping screws
{
"x": 0,
"y": 0,
"z": kbd_pillar_offset_2,
"shape": (
cq.Sketch()
.push(kbd_pillar_positions)
.circle(kbd_pillar_radius_2, mode="a")
.circle(kbd_screw_radius, 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=-kbd_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, kbd_front_thickness],
[shell_t, kbd_front_thickness],
[kbd_actual_height + shell_t, kbd_back_thickness],
[kbd_actual_height + shell_t, 1000],
[0, 1000],
[0, kbd_front_thickness],
]
)
)
.cutBlind(-1000)
)
return model

View File

@ -0,0 +1,84 @@
from utils import extrude_shape, punch_hole
import cadquery as cq
elements = None
bottom_holes = None
# These are set from dimensions.py
pillar_width = 0
pillar_height = 0
screw_head_radius = 0
screw_head_depth = 0
screw_radius = 0
def init(positions, thickness):
"""Because these need to match in multiple models, we create the
elemments dynamically"""
global elements, bottom_holes
elements = [
{
"x": 0,
"y": 0,
"shape": cq.Sketch()
.push(positions)
.trapezoid(pillar_width, pillar_height, 90, mode="a"),
"height": thickness,
}
]
bottom_holes = [
{
"x": 0,
"y": 0,
"shape": cq.Sketch().push(positions).circle(screw_head_radius, mode="a"),
"depth": screw_head_depth,
},
{
"x": 0,
"y": 0,
"shape": cq.Sketch().push(positions).circle(screw_radius, mode="a"),
"depth": 100,
},
]
def add(
*,
model,
width,
height,
thickness,
offset_x,
offset_y,
bottom_face,
back_face,
shell_t
):
if bottom_face:
# Mounting pillars
for element in elements:
model = extrude_shape(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x,
y_offset=shell_t + offset_y,
element=element,
height=-(element["height"] + shell_t),
)
# Screw holes
for hole in bottom_holes:
model = punch_hole(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x,
y_offset=shell_t + offset_y,
hole=hole,
depth=hole["depth"],
)
return model

107
components/simple_lid.py Normal file
View File

@ -0,0 +1,107 @@
import cadquery as cq
import dimensions as dim
from utils import extrude_shape2, hex_vents, punch_hole, export
def model():
# Create the basic shape of the case lid
model = (
cq.Workplane("XY")
# Hollow box
.box(dim.width, dim.sl_height, dim.sl_thickness)
.edges("|Z and >Y")
.fillet(2)
)
# Make many holes
vent = hex_vents(size=6, width=dim.width * 0.9, height=dim.sl_height * 0.9)[0]
model = punch_hole(
model=model,
face=">Z",
w=dim.width,
h=dim.sl_height,
x_offset=0.05 * dim.width,
y_offset=0.05 * dim.sl_height,
hole=vent,
depth=dim.sl_thickness,
)
# Add screw holes
for position in dim.mounting_pillar_positions:
model = (
model.faces(">Z")
.workplane(centerOption="CenterOfBoundBox")
.center(
-dim.width / 2 + position[0],
dim.sl_height / 2 - position[1] - dim.shell_t,
)
.placeSketch(cq.Sketch().circle(dim.m4_top / 2 + 1.5))
.extrude(-dim.sl_thickness)
.faces(">Z")
.workplane(centerOption="CenterOfBoundBox")
.center(
-dim.width / 2 + position[0],
dim.sl_height / 2 - position[1] - dim.shell_t,
)
.cskHole(dim.m4_bottom, dim.m4_top, 82, depth=None)
)
# Add front lip
model = (
model.faces(">Z")
.workplane(centerOption="CenterOfBoundBox")
.center(0, -dim.sl_height / 2 + dim.sl_lip_thickness / 2)
.placeSketch(
cq.Sketch().trapezoid(dim.width - 2 * dim.shell_t, dim.sl_lip_thickness, 90)
)
.extrude(-dim.sl_front_lip - dim.sl_thickness)
)
return model
def decorative_cover():
# A decorative thingie to cover the ugly seam in the middle
model = cq.Workplane("XY").box(10, dim.sl_height, 1).edges("|Z").fillet(1)
vent = hex_vents(
size=6, width=dim.width * 0.9, height=dim.sl_height * 0.9, density=0.775
)[0]
model = extrude_shape2(
model=model,
face=">Z",
w=dim.width,
h=dim.sl_height,
x_offset=0.05 * dim.width,
y_offset=0.05 * dim.sl_height,
hole=vent,
depth=3,
)
return model
if __name__ == "__main__":
model = model()
export(model, "simple_lid.stl")
cover = decorative_cover()
export(cover, "simple_lid_cover.stl")
export(
model,
"simple_lid.svg",
opt={
"projectionDir": (0, 0, 1),
},
)
export(
model.faces(">X").workplane(offset=-dim.width / 2).split(keepTop=True),
"simple_lid_right.stl",
)
export(
model.faces(">X").workplane(offset=-dim.width / 2).split(keepBottom=True),
"simple_lid_left.stl",
)

101
components/usb_hub.py Normal file
View File

@ -0,0 +1,101 @@
import cadquery as cq
from utils import punch_hole, extrude_shape
# Measurements for my USB hub, YMMV
# The hole is for a USB-A plug, y is measured in the hub
# (from the bottom face to middle of the hole)
# Consumers should set proper offsets for the hole
item_w = 17
item_h = 93
holes = [
# USB-A port
{
"x": -item_w / 2,
"y": 4,
"shape": cq.Sketch().trapezoid(13, 5, 90, mode="a").vertices().fillet(1),
},
]
elements = [
# Thing to grab the hub
{
"x": item_w / 2,
"y": 5,
"shape": (
cq.Sketch().trapezoid(22, 10, 90, mode="a").trapezoid(17, 10, 90, mode="s")
),
"height": 8,
},
{
"x": item_w / 2 + 5.5,
"y": item_h - 3,
"shape": (cq.Sketch().circle(2.5, mode="a")),
"height": 8,
},
{
"x": item_w / 2 - 5.5,
"y": item_h - 3,
"shape": (cq.Sketch().circle(2.5, mode="a")),
"height": 8,
},
# Outline
{
"x": item_w / 2,
"y": item_h / 2,
"shape": (
cq.Sketch()
.trapezoid(item_w, item_h, 90, mode="a")
.trapezoid(item_w - 2, item_h - 2, 90, mode="s")
.vertices()
.fillet(3)
),
"height": 0.2,
},
]
def add(
*,
model,
width,
height,
thickness,
offset_x,
offset_y,
bottom_face,
back_face,
shell_t
):
# USB Hub extrusions
if bottom_face:
for element in elements:
model = extrude_shape(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x,
y_offset=shell_t + offset_y,
element=element,
height=-(element["height"] + shell_t),
)
# Holes
if back_face:
for hole in holes:
model = punch_hole(
model=model,
face=back_face,
w=width,
h=thickness,
x_offset=width - offset_x,
y_offset=shell_t,
hole=hole,
depth=shell_t,
)
return model

110
components/zero_holder.py Normal file
View File

@ -0,0 +1,110 @@
import cadquery as cq
from utils import extrude_shape, punch_hole, hex_vents
width = 65
height = 30
pillar_height = 7
stand_positions = [(3.5, 3.5), (3.5, 26.5), (61.5, 26.5), (61.5, 3.5)]
stands = (
cq.Sketch().push(stand_positions).circle(3, mode="a").circle(2.65 / 2, mode="s")
)
elements = [
# CPU holder stands
{
"x": 0,
"y": 0,
"shape": stands,
"height": pillar_height,
},
{
"x": 0,
"y": 0,
"shape": cq.Sketch().push(stand_positions).circle(5),
"height": 0,
},
# Perimeter
{
"x": width / 2,
"y": height / 2,
"shape": (
cq.Sketch()
.trapezoid(width, height, 90, mode="a")
.trapezoid(width - 2, height - 2, 90, mode="s")
.vertices()
.fillet(3)
),
"height": 0.2,
},
]
vents = hex_vents(size=3, width=width, height=height)
holes = [
# One hole for everything TODO: improve
{
"x": -width / 2,
"y": 1 + pillar_height,
"shape": cq.Sketch().trapezoid(50, 6, 90, mode="a").vertices().fillet(1),
}
]
def add(
*,
model,
width,
height,
thickness,
offset_x,
offset_y,
bottom_face,
back_face,
shell_t
):
if bottom_face:
# Vents
for vent in vents:
model = punch_hole(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x + vent["x"],
y_offset=shell_t + offset_y + vent["y"],
hole=vent,
depth=shell_t,
)
# CPU holder extrusions
for element in elements:
model = extrude_shape(
model=model,
face=bottom_face,
w=width,
h=height,
x_offset=offset_x,
y_offset=shell_t + offset_y,
element=element,
height=-(element["height"] + shell_t),
)
# Holes
if back_face:
for hole in holes:
model = punch_hole(
model=model,
face=back_face,
w=width,
h=thickness,
x_offset=width - offset_x,
y_offset=shell_t,
hole=hole,
depth=shell_t,
)
return model