Skip to content

Commit

Permalink
Merge pull request #15 from CadQuery/marcus7070/hex-modular-drawers
Browse files Browse the repository at this point in the history
hexagonal modular drawers
  • Loading branch information
jmwright authored Mar 28, 2021
2 parents 8a2b754 + b8f0178 commit 3902f2b
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ A place to share CadQuery scripts, modules, tutorials and projects

<img src="examples/images/Thread.png" width="600"/>

* [Hexagonal modular drawers](examples/hexagonal_drawers/assembly.py) - Inspired by [this on Prusa Printers](https://www.prusaprinters.org/prints/54113-hexagonal-organizer-system), these drawers are 3D printed (without needing supports) and clip together.

<img src="examples/hexagonal_drawers/hmd.png" width="600"/>
<img src="examples/hexagonal_drawers/hmd.jpg" width="600"/>

### Tutorials

* [Ex000 Start Here.ipynb](tutorials/Ex000%20Start%20Here.ipynb) - iPython notebook that is the entry point for a set of CadQuery tutorials
Expand Down
74 changes: 74 additions & 0 deletions examples/hexagonal_drawers/assembly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Display the drawers
"""

import cadquery as cq
import importlib
import base
import organiser_collets
import organiser_3_125_bits
importlib.reload(base)
importlib.reload(organiser_collets)
importlib.reload(organiser_3_125_bits)

sep = 20 # seperation between parts
big_sep = 100 # extra for the organisers

assy = cq.Assembly()
assy.add(base.frame, name="frame")
assy.add(base.drawer, name="drawer")
assy.add(organiser_collets.collet_organiser, name="collet organiser")
assy.add(organiser_3_125_bits.bit_organiser, name="bit organiser")

# pull the drawer out
assy.constrain(
"frame",
base.frame.faces("<Y").val().translate((0, -sep, 0)),
"drawer",
base.drawer.faces(">Y").val(),
"Point",
)

# bit organiser aligns with back face of drawer and is big_sep above
assy.constrain(
"drawer",
base.drawer.faces("<Y[1]").val().translate((0, 0, big_sep)),
"bit organiser",
organiser_3_125_bits.bit_organiser.faces(">Y").val(),
"Point",
)
assy.constrain(
"bit organiser",
organiser_3_125_bits.bit_organiser.faces("<Y").val().translate((0, -sep, 0)),
"collet organiser",
organiser_collets.collet_organiser.faces(">Y").val(),
"Point",
)

# align the z and x axes between obj0 and obj1
align_these = (
("frame", "drawer"),
("drawer", "collet organiser"),
("drawer", "bit organiser"),
)
for obj0, obj1 in align_these:
assy.constrain(
obj0,
cq.Face.makePlane(),
obj1,
cq.Face.makePlane(),
"Axis",
0,
)
assy.constrain(
obj0,
cq.Face.makePlane(dir=(1, 0, 0)),
obj1,
cq.Face.makePlane(dir=(1, 0, 0)),
"Axis",
0,
)

assy.solve()
if "show_object" in locals():
show_object(assy)
119 changes: 119 additions & 0 deletions examples/hexagonal_drawers/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
The basic frame and drawer.
"""

import cadquery as cq
from types import SimpleNamespace
from math import tan, radians

hex_diam = 80 # outside of the drawer frame
wall_thick = 3
clearance = SimpleNamespace(tight=0.3)
clearance.loose = clearance.tight * 2
drawer_length = 150
dovetail_min_thick = wall_thick * 2

frame_y = drawer_length + clearance.loose + 2 * wall_thick

frame = (
cq.Workplane("XZ")
.polygon(6, hex_diam)
.extrude(frame_y)
.faces("<Y")
.shell(-2 * wall_thick)
)

drawer = (
frame
.faces("<Y[1]")
.wires()
.translate((0, -clearance.loose, 0))
.toPending()
.offset2D(-clearance.loose)
.extrude(drawer_length, combine=False)
.faces(">Z or >>Z[-2]")
.shell(-wall_thick)
)

handle = (
drawer
.faces("<Y")
.edges("<Z")
)
handle_width = handle.val().Length()
handle = (
handle
.workplane(centerOption="CenterOfMass")
.transformed(rotate=(-90, 0, 180))
.circle(handle_width / 2)
.circle(handle_width / 2 - wall_thick)
.transformed(rotate=(30, 0, 0))
.extrude(hex_diam / 2, combine=False)
.newObject([drawer.faces("<Y").val()])
.workplane(centerOption="CenterOfMass")
.split(keepTop=True)
)

drawer = drawer.union(handle)
del handle

top_length = frame.faces(">Z").val().BoundingBox().ylen
dovetail_base_radius = frame.faces("<Y").edges(">Z").val().Center().z
dovetail_length = 0.9 * top_length

# make the male dovetail join
# should extend wall_thick out from the frame
dovetail_positive = (
cq.Workplane()
.hLine(dovetail_min_thick / 2)
.line(wall_thick * tan(radians(30)), wall_thick)
.hLineTo(0)
.mirrorY()
.extrude(-dovetail_length)
.faces("<Z")
.edges("<Y")
.workplane()
.transformed(rotate=(60, 0, 0))
.split(keepBottom=True)
)
# provide some clearance around the straight section, but leave the sloped
# plane at the back alone so it mates as a backstop
# dovetail_straight_length = dovetail_positive.edges(">Y and |Z").val().Length()
dovetail_negative = (
dovetail_positive
.tag("dovetail_positive")
.faces(">Z")
.wires()
.toPending()
.offset2D(clearance.tight)
.faces(">Z", tag="dovetail_positive")
.workplane()
.extrude(-(dovetail_length + clearance.tight))
.faces("<Z")
.edges("<Y")
.workplane()
.transformed(rotate=(60, 0, 0))
.split(keepBottom=True)
.mirror("XZ")
)
dovetail_baseplane = (
frame
.faces("<Y")
.workplane(centerOption="CenterOfMass")
)
dovetail_positive = (
dovetail_baseplane
.polarArray(dovetail_base_radius, startAngle=-60, angle=120, count=3)
.eachpoint(lambda loc: dovetail_positive.val().located(loc), useLocalCoordinates=True)
)

dovetail_negative = (
dovetail_baseplane
.polarArray(dovetail_base_radius, startAngle=120, angle=120, count=3)
.eachpoint(lambda loc: dovetail_negative.val().located(loc), useLocalCoordinates=True)
)
frame = frame.union(dovetail_positive, glue=True).cut(dovetail_negative)

if "show_object" in locals():
show_object(frame, "frame", options={"alpha": 0.5, "color": "black"})
show_object(drawer, "drawer", options={"color": "green"})
Binary file added examples/hexagonal_drawers/hmd.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/hexagonal_drawers/hmd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions examples/hexagonal_drawers/organiser_3_125_bits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
Organiser for cutters with a shank of 3.125mm
"""

import cadquery as cq
import importlib
import base
import organiser_blank
importlib.reload(organiser_blank)

base_wp = (
organiser_blank.organiser
.faces(">Z")
.workplane(centerOption="CenterOfMass")
)

bit_3_125_points = (
base_wp
.rarray(
3.125 * 3,
3.125 * 4,
4,
4,
)
.vals()
)
bit_3_125_points.extend(
base_wp
.rarray(
3.125 * 3,
3.125 * 4,
3,
3,
)
.vals()
)
bit_organiser = (
base_wp
.newObject(bit_3_125_points)
.hole(
3.125 + 2 * base.clearance.loose,
depth=organiser_blank.organiser.val().BoundingBox().zlen - 1.5 * base.wall_thick,
)
)
37 changes: 37 additions & 0 deletions examples/hexagonal_drawers/organiser_blank.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
An organiser that takes up 1/3 of a drawer and has no cutouts yet.
"""

import cadquery as cq
import importlib
import base
importlib.reload(base)


# organiser base
# first grab the inner profile of the drawer
lines = (
base.drawer
.faces(">Y")
.workplane(offset=-base.drawer_length / 2)
.section()
.edges()
.vals()
)
assert len(lines) == 8
# sort lines by radius about y axis
lines.sort(
key=lambda x: cq.Vector(x.Center().x, 0, x.Center().z).Center().Length
)
wire = cq.Wire.assembleEdges(lines[0:3])
wire = cq.Wire.combine(
[wire, cq.Edge.makeLine(wire.endPoint(), wire.startPoint())]
)[0]
wire_center = wire.Center()
wire = wire.translate(cq.Vector(0, -wire_center.y, 0))
organiser = (
cq.Workplane("XZ")
.newObject([wire])
.toPending()
.extrude(base.drawer_length / 3 - base.clearance.loose)
)
61 changes: 61 additions & 0 deletions examples/hexagonal_drawers/organiser_collets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
An organiser with holes for ER11 collets.
"""

import cadquery as cq
from types import SimpleNamespace
import importlib
import organiser_blank
importlib.reload(organiser_blank)


collet_dims = SimpleNamespace(
upper_diam=11.35,
cone_height=13.55,
lower_diam=7.8,
)
collet = (
cq.Solid.makeCone(
collet_dims.upper_diam / 2,
collet_dims.lower_diam / 2,
collet_dims.cone_height,
)
.mirror("XY")
.translate(cq.Vector(0, 0, collet_dims.cone_height / 3))
)
collet_organiser_points = (
organiser_blank.organiser
.faces(">Z")
.workplane(centerOption="CenterOfMass")
.rarray(
collet_dims.upper_diam * 1.5,
collet_dims.upper_diam * 2.3,
3,
2,
)
.vals()
)
collet_organiser_points.extend(
organiser_blank.organiser
.faces(">Z")
.workplane(centerOption="CenterOfMass")
.rarray(
collet_dims.upper_diam * 1.5,
collet_dims.upper_diam * 2.3,
2,
1,
)
.vals()
)
collets = (
cq.Workplane()
.pushPoints(collet_organiser_points)
.eachpoint(lambda loc: collet.located(loc))
)
collet_organiser = (
organiser_blank.organiser
.cut(collets)
)

if "show_object" in locals():
show_object(collet_organiser, "collet organiser")

0 comments on commit 3902f2b

Please sign in to comment.