Using the Box type to define your panels
Sheet stock is typically used for making boxes, cabinets and drawers, all of which have a rectangular crosssection on each axis.
A Box
is first specified by its outside dimensions. The Unitful
package (and optionally UnitfulUS
) are used so we can specify units for the box dimensions.
using PanelCutting, Unitful, UnitfulUS
my_box = Box(0.3u"m", 0.2u"m", 0.1u"m")
Box(0.3 m, 0.2 m, 0.1 m, DataStructures.DefaultDict{Any, Any, Unitful.Quantity{Float64, 𝐋, Unitful.FreeUnits{(inch,), 𝐋, nothing}}}(), DataStructures.DefaultDict{Any, Any, Nothing}(), DataStructures.DefaultDict{Any, Any, Bool}(), DataStructures.DefaultDict{Any, Any, GDLong}(), DataStructures.DefaultDict{Any, Any, FingerJoint}())
The Box
has six faces which are identified by singleton types. The faces come in three opposite pairs: Top
and Bottom
, Left
and Right
, and Front
and Back
.
Once a box is defined, one can specify whether each face is open, or the thickness of the panel for that face. One can also specify what material should be used.
my_box.open[Top()] = true
do_faces(my_box) do face
# All faces are 5mm baltic birch:
my_box.thickness[face] = (1/4)u"inch"
my_box.material[face] = "Baltic Birch"
end
For each face of a box, one can also specify the grain direction (also represented by singleton types), one of GDLong
(the default), GDShort
or GDEither
.
my_box.grain_direction[Bottom()] = GDEither()
GDEither()
A Box
also has edges. An edge is identified by a pair of faces. Edge(Front(), Bottom())
specifies the edge where the bottom and front panels of the box meet.
One can specify the joint type to be used for each edge. The joint type affects this sizes of the panels which meet at that edge. For a butt joint, one face is shortened by the thickness of the other. For a finger joint, both panels would be at full length. For a dado/tongue and grrove joint, one panel is shortened by the thickness of the other but lengthened by the tongue length.
let
# Use finger joints between each pair of sides:
sides = [Left(), Back(), Right(), Front()]
for i in 0:(length(sides) - 1)
e = Edge(sides[i + 1],
sides[1 + (i + 1) % length(sides)])
my_box.joint_types[e] = FingerJoint()
end
# Use a dado joint for each edge of the bottom:
for n in neighbors(Bottom())
edge = Edge(Bottom(), n)
my_box.joint_types[edge] = DadoJoint(Bottom(), 2u"mm")
end
end
Once the box is fully specified, we can ask about the panels it requires, its WantedPanel
s:
WantedPanels(my_box)
6-element Vector{AbstractWantedPanel}:
WantedPanel(1, 0.2 m, 0.1 m, 0.25 inch, "Baltic Birch", "Back")
WantedPanel(2, 0.29129999999999995 m, 0.19130000000000003 m, 0.25 inch, "Baltic Birch", "Bottom")
FlippedPanel(3, WantedPanel(2, 0.29129999999999995 m, 0.19130000000000003 m, 0.25 inch, "Baltic Birch", "Bottom"))
WantedPanel(4, 0.2 m, 0.1 m, 0.25 inch, "Baltic Birch", "Front")
WantedPanel(5, 0.3 m, 0.1 m, 0.25 inch, "Baltic Birch", "Left")
WantedPanel(6, 0.3 m, 0.1 m, 0.25 inch, "Baltic Birch", "Right")
To make our box, we first need sheet stock, which comes from a Supplier
.
BOULTER_PLYWOOD = Supplier(
name = "Boulter Plywood",
kerf = (1/8)u"inch",
cost_per_cut = money(1.50),
available_stock = [
AvailablePanel(;
label = "1/4 5 × 5 Baltic Birch",
material = "Baltic Birch",
thickness = (1/4)u"inch",
length = 5u"ft",
width = 5u"ft",
cost = 84.00 # I've not been able to get UnitfulCurrency to work
),
AvailablePanel(;
label = "1/4 30 × 60 Baltic Birch",
material = "Baltic Birch",
thickness = (1/4)u"inch",
length = 60u"inch",
width = 30u"inch",
cost = 51.00
),
AvailablePanel(;
label = "1/4 30 × 30 Baltic Birch",
material = "Baltic Birch",
thickness = (1/4)u"inch",
length = 30u"inch",
width = 30u"inch",
cost = 36.00)
])
Supplier("Boulter Plywood", 1.5, 0.125 inch, AvailablePanel[AvailablePanel(7, "1/4 5 × 5 Baltic Birch", 5 ft, 5 ft, 0.25 inch, "Baltic Birch", 84.0), AvailablePanel(8, "1/4 30 × 60 Baltic Birch", 30 inch, 60 inch, 0.25 inch, "Baltic Birch", 51.0), AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)])
Now we can figure out where to make the cuts. We can multiply our list of WantedPanels by an integer if we want to make several boxes.
searcher = Searcher(BOULTER_PLYWOOD, 2 * WantedPanels(my_box))
search(searcher)
searcher.cheapest.finished
(FinishedPanel(18849, WantedPanel(16, 0.2 m, 0.1 m, 0.25 inch, "Baltic Birch", "Back 1/2"), Panel(18847, 0.2 m, 0.1 m, Panel(18840, 0.2 m, 0.34929999999999994 m, Panel(18833, 0.2 m, 0.45247499999999996 m, Panel(18819, 0.2 m, 0.55565 m, Panel(18816, 0.2 m, 0.658825 m, Panel(18739, 0.26435 m, 0.658825 m, Panel(90, 0.45882500000000004 m, 0.658825 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.103175 m, 20.988673628788938), 0.19130000000000003 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 13.04703363057249), 0.2 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 11.139683071176409), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.20635 m, 10.711873558299658), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.309525 m, 10.00147968377146), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.4127 m, 8.941613295217829), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.4127 m, 3.0167174561842782)), FinishedPanel(18841, WantedPanel(17, 0.2 m, 0.1 m, 0.25 inch, "Baltic Birch", "Back 2/2"), Panel(18839, 0.2 m, 0.1 m, Panel(18833, 0.2 m, 0.45247499999999996 m, Panel(18819, 0.2 m, 0.55565 m, Panel(18816, 0.2 m, 0.658825 m, Panel(18739, 0.26435 m, 0.658825 m, Panel(90, 0.45882500000000004 m, 0.658825 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.103175 m, 20.988673628788938), 0.19130000000000003 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 13.04703363057249), 0.2 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 11.139683071176409), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.20635 m, 10.711873558299658), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.309525 m, 10.00147968377146), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.309525 m, 2.5598663885536306)), FinishedPanel(18834, WantedPanel(22, 0.2 m, 0.1 m, 0.25 inch, "Baltic Birch", "Front 1/2"), Panel(18832, 0.2 m, 0.1 m, Panel(18819, 0.2 m, 0.55565 m, Panel(18816, 0.2 m, 0.658825 m, Panel(18739, 0.26435 m, 0.658825 m, Panel(90, 0.45882500000000004 m, 0.658825 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.103175 m, 20.988673628788938), 0.19130000000000003 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 13.04703363057249), 0.2 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 11.139683071176409), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.20635 m, 10.711873558299658), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.20635 m, 2.2103938745281977)), FinishedPanel(18820, WantedPanel(23, 0.2 m, 0.1 m, 0.25 inch, "Baltic Birch", "Front 2/2"), Panel(18818, 0.2 m, 0.1 m, Panel(18816, 0.2 m, 0.658825 m, Panel(18739, 0.26435 m, 0.658825 m, Panel(90, 0.45882500000000004 m, 0.658825 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.103175 m, 20.988673628788938), 0.19130000000000003 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 13.04703363057249), 0.2 m, LengthAxis(), 0.49765000000000004 m, 0.103175 m, 11.139683071176409), 0.1 m, WidthAxis(), 0.49765000000000004 m, 0.103175 m, 1.9278095128767496)), FinishedPanel(18812, WantedPanel(18, 0.29129999999999995 m, 0.19130000000000003 m, 0.25 inch, "Baltic Birch", "Bottom 1/2"), Panel(18810, 0.29129999999999995 m, 0.19130000000000003 m, Panel(18796, 0.29129999999999995 m, 0.2579999999999999 m, Panel(18793, 0.29129999999999995 m, 0.45247499999999996 m, Panel(64, 0.3 m, 0.45247499999999996 m, Panel(57, 0.3 m, 0.55565 m, Panel(34, 0.3 m, 0.658825 m, Panel(31, 0.3 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0 inch, 0 inch, 14.825552663657628), 0.1 m, WidthAxis(), 0.0 m, 0.103175 m, 14.17412741229432), 0.1 m, WidthAxis(), 0.0 m, 0.20635 m, 13.283503235935846), 0.1 m, WidthAxis(), 0.0 m, 0.309525 m, 12.107634963898949), 0.29129999999999995 m, LengthAxis(), 0.0 m, 0.309525 m, 13.354347056291632), 0.19130000000000003 m, WidthAxis(), 0.0 m, 0.504 m, 8.529760829119164), 0.19130000000000003 m, WidthAxis(), 0.0 m, 0.504 m, 7.529454514315695)), FinishedPanel(18797, WantedPanel(19, 0.29129999999999995 m, 0.19130000000000003 m, 0.25 inch, "Baltic Birch", "Bottom 2/2"), Panel(18795, 0.29129999999999995 m, 0.19130000000000003 m, Panel(18793, 0.29129999999999995 m, 0.45247499999999996 m, Panel(64, 0.3 m, 0.45247499999999996 m, Panel(57, 0.3 m, 0.55565 m, Panel(34, 0.3 m, 0.658825 m, Panel(31, 0.3 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0 inch, 0 inch, 14.825552663657628), 0.1 m, WidthAxis(), 0.0 m, 0.103175 m, 14.17412741229432), 0.1 m, WidthAxis(), 0.0 m, 0.20635 m, 13.283503235935846), 0.1 m, WidthAxis(), 0.0 m, 0.309525 m, 12.107634963898949), 0.29129999999999995 m, LengthAxis(), 0.0 m, 0.309525 m, 13.354347056291632), 0.19130000000000003 m, WidthAxis(), 0.0 m, 0.309525 m, 6.3245862271724675)), FinishedPanel(18778, FlippedPanel(20, WantedPanel(11, 0.29129999999999995 m, 0.19130000000000003 m, 0.25 inch, "Baltic Birch", "Bottom")), Panel(18776, 0.19130000000000003 m, 0.29129999999999995 m, Panel(18741, 0.19130000000000003 m, 0.36435000000000006 m, Panel(18738, 0.19130000000000003 m, 0.658825 m, Panel(90, 0.45882500000000004 m, 0.658825 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.103175 m, 20.988673628788938), 0.19130000000000003 m, LengthAxis(), 0.303175 m, 0.103175 m, 9.441639998216449), 0.29129999999999995 m, WidthAxis(), 0.303175 m, 0.39764999999999995 m, 6.080357711202872), 0.29129999999999995 m, WidthAxis(), 0.303175 m, 0.39764999999999995 m, 6.113817958810537)), FinishedPanel(18742, FlippedPanel(21, WantedPanel(11, 0.29129999999999995 m, 0.19130000000000003 m, 0.25 inch, "Baltic Birch", "Bottom")), Panel(18740, 0.19130000000000003 m, 0.29129999999999995 m, Panel(18738, 0.19130000000000003 m, 0.658825 m, Panel(90, 0.45882500000000004 m, 0.658825 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.103175 m, 20.988673628788938), 0.19130000000000003 m, LengthAxis(), 0.303175 m, 0.103175 m, 9.441639998216449), 0.29129999999999995 m, WidthAxis(), 0.303175 m, 0.103175 m, 4.861282287013575)), FinishedPanel(93, WantedPanel(24, 0.3 m, 0.1 m, 0.25 inch, "Baltic Birch", "Left 1/2"), Panel(91, 0.3 m, 0.1 m, Panel(89, 0.45882500000000004 m, 0.1 m, Panel(32, 0.45882500000000004 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 22.674447336342375), 0.1 m, WidthAxis(), 0.303175 m, 0.0 m, 3.1857737075534382), 0.3 m, LengthAxis(), 0.303175 m, 0.0 m, 3.085113820401692)), FinishedPanel(65, WantedPanel(25, 0.3 m, 0.1 m, 0.25 inch, "Baltic Birch", "Left 2/2"), Panel(63, 0.3 m, 0.1 m, Panel(57, 0.3 m, 0.55565 m, Panel(34, 0.3 m, 0.658825 m, Panel(31, 0.3 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0 inch, 0 inch, 14.825552663657628), 0.1 m, WidthAxis(), 0.0 m, 0.103175 m, 14.17412741229432), 0.1 m, WidthAxis(), 0.0 m, 0.20635 m, 13.283503235935846), 0.1 m, WidthAxis(), 0.0 m, 0.20635 m, 2.6758682720368974)), FinishedPanel(58, WantedPanel(26, 0.3 m, 0.1 m, 0.25 inch, "Baltic Birch", "Right 1/2"), Panel(56, 0.3 m, 0.1 m, Panel(34, 0.3 m, 0.658825 m, Panel(31, 0.3 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0 inch, 0 inch, 14.825552663657628), 0.1 m, WidthAxis(), 0.0 m, 0.103175 m, 14.17412741229432), 0.1 m, WidthAxis(), 0.0 m, 0.103175 m, 2.390624176358472)), FinishedPanel(35, WantedPanel(27, 0.3 m, 0.1 m, 0.25 inch, "Baltic Birch", "Right 2/2"), Panel(33, 0.3 m, 0.1 m, Panel(31, 0.3 m, 0.762 m, BoughtPanel(30, AvailablePanel(9, "1/4 30 × 30 Baltic Birch", 30 inch, 30 inch, 0.25 inch, "Baltic Birch", 36.0)), 0.3 m, LengthAxis(), 0 inch, 0 inch, 14.825552663657628), 0.1 m, WidthAxis(), 0 inch, 0 inch, 2.1514252513633085)))
We would like a clearer description though:
report(searcher;
includeCutDiagram=true,
includeCutGraph=false,
filename="box_example_panel_cut_report.html")
"box_example_panel_cut_report.html"
Box Faces
PanelCutting.Back
— TypeThe back face of a Box
.
PanelCutting.Bottom
— TypeThe bottom face of a Box
.
PanelCutting.Face
— TypeFace
Face is the abstract supertype for the tokens that identify each face of a Box.
Subtypes are Top, Bottom, Left, Right, Front and Back, which are all singleton types.
PanelCutting.Front
— TypeThe front face of a Box
.
PanelCutting.Left
— TypeThe left face of a Box
.
PanelCutting.Right
— TypeThe right face of a Box
.
PanelCutting.Top
— TypeThe top face of a Box
.
Edges
Between each pair of adjacent faces is an Edge
. For each edge, the type of joinery to be used at that edge can be specified.
PanelCutting.Edge
— TypeEdge(::Face, ::Face)
The edge of the box that connects the two specified faces.
Grain Direction
For each face of a box, one can specify the grain direction.
PanelCutting.GDEither
— TypeGDEither
Use GDEither()
if you don't care whether the grain runs parallel to the long or short edges of the panel.
PanelCutting.GDLong
— TypeGDLong
Use GDLong()
to indicate that the grain of the face should run parallel to its longer edges.
PanelCutting.GDShort
— TypeGDShort
Use GDShort()
to indicate that the grain of the face should run parallel to its shorter edges.
PanelCutting.GrainDirection
— TypeGrainDirection
GrainDirection is the abstract type for the choices of how the grain direction of the stock is oriented with respect to the shape of the panel.
Joint Type
PanelCutting.ButtJoint
— TypeButtJoint(shortened)
If the joint type specified for a pair of Faces is a ButtJoint, then the face specified by shortened
is shortened by the thickness of the other face.
PanelCutting.DadoJoint
— TypeDadoJoint(tongued::Face, tongue_length::LengthType)
If the joint type specified for a pair of faces is a DadoJoint, then the face specified by tongued
is shortened by the thickness of the other face and then lengthened by tongue_length
.
PanelCutting.FingerJoint
— TypeFingerJoint
If the joint type specified for a pair of faces is FingerJoint then the size of neither panel needs to be adjusted for that joint.
If you intend to make blind finger or dovetail joints, use DadoJoint.
If you want a miter joint, use FingerJoint.
PanelCutting.JointType
— TypeJointType
The abstract supertype for objects describing the joint type bwtween two faces.
Related Definitions
PanelCutting.Box
— TypeBox(length::LengthType, width::LengthType, height::LengthType)
Define a box of the spcified dimensions.
PanelCutting.distance
— Functiondistance(::Box, ::Face, ::Face)
Return the outside dimension of the box between the two faces.
PanelCutting.do_faces
— Functiondo_faces(::Function, ::Box)
Apply the function to each face of the Box that is not open/missing.
PanelCutting.neighbors
— Functionneighbors(face1::Face, face2::Face)::Boll
Return true if face1 is a neighbor of face2.
neighbors(face::Face)
Return the Face
s that are adjacent to the specified Face
.
PanelCutting.opposite
— Functionopposite(::Face)::Face
Return the Face
that is opposite to the specified face.
PanelCutting.WantedPanels
— FunctionWantedPanels(::Box)
Return the collection of WantedPanel
s to make the Box
.