Component Parts¶
Wood Panel¶
First we’ll need something to use the biscuits on, so we’ll just create a wooden panel with one edge at an angle.
from math import radians, tan, cos
import cadquery
import cqparts
from cqparts.params import *
from cqparts.constraint import Mate
from cqparts.utils import CoordSystem
from cqparts.display import display, render_props
class Panel(cqparts.Part):
# dimensions
height = PositiveFloat(50, doc="panel height (along join)")
depth = PositiveFloat(50, doc="panel depth (from join to opposite side)")
width = PositiveFloat(10, doc="thickness of panel")
join_angle = FloatRange(0, 89, 45, doc="angle of join (unit: degrees)")
_render = render_props(template='wood', alpha=0.5)
def make(self):
points = [
(0, 0),
(self.depth, 0),
(self.depth, self.width),
(self.width * tan(radians(self.join_angle)), self.width),
]
return cadquery.Workplane('XZ', origin=(0, self.height / 2, 0)) \
.moveTo(*points[0]).polyline(points[1:]).close() \
.extrude(self.height)
def get_mate_join(self, ratio=0.5):
# Return a mate that's somewhere along the join surface.
return Mate(self, (
CoordSystem().rotated(
(0, -(90 - self.join_angle), 0)
) + CoordSystem(
origin=(
(self.width / cos(radians(self.join_angle))) / 2,
(-self.height / 2) + (self.height * ratio),
0
),
)
))
@property
def mate_join(self):
# default is half way along join
return self.get_mate_join(ratio=0.5)
@property
def mate_join_reverse(self):
# reversed join rotated around X-axis 180 deg
return self.mate_join + CoordSystem().rotated((180, 0, 0))
So to illustrate what we’ve just made:
panel = Panel()
display(panel)
Biscuit¶
And of course the biscuit:
class Biscuit(cqparts.Part):
# Biscuit Dimensions
width = PositiveFloat(30, doc="twice penetration depth")
length = PositiveFloat(None, doc="length tip to tip")
thickness = PositiveFloat(5, doc="material thickness")
_render = render_props(template='wood_dark')
def initialize_parameters(self):
super(Biscuit, self).initialize_parameters()
# set default length as a ratio of width
if self.length is None:
self.length = (5. / 3) * self.width
def make(self):
# We'll just use the simplified model for this example
return self.make_simple()
# It could be rounded at the ends, and the sides chamfered, but
# for this example we'll just keep it simple.
def make_simple(self):
# Biscuit shaped like a eye, 2 arcs from end to end (length)
# Create left & right side, union them together
biscuit = cadquery.Workplane('XY')
for i in [1, -1]:
biscuit = biscuit.union(
cadquery.Workplane('XY', origin=(0, 0, -self.thickness / 2)) \
.moveTo(self.length / 2, 0) \
.threePointArc(
(0, i * self.width / 2),
(-self.length / 2, 0)
).close().extrude(self.thickness)
)
return biscuit
def make_cutter(self):
# the cutaway material is the same shape as the biscuit itself
# (the simplified model)
return self.make_simple()
So to illustrate what we’ve just made:
biscuit = Biscuit()
display(biscuit)