PanelCutting.jl
This package implements a utility for determining the optimal sequence of cuts to produce a set of rectangular panels of specified sizes from sheet good stock (e.g. plywood).
New users will probably want to go straight to the box example to get started.
Panels
The search is mediated by a progression of panels of various types:
PanelCutting.AvailablePanel
— TypeAvailablePanel
A sheet of plywood we can buy from the lumber yard.
PanelCutting.BoughtPanel
— TypeBoughtPanel
a BoughtPanel is created to wrap an AvailablePanel when we add it to the working set. This ensured that when it is cut it has a distinct identity from any other BoughtPanel of the same size.
PanelCutting.FinishedPanel
— TypeFinishedPanel
FinishedPanel wraps a Panel that matches an AbstractWantedPanel and associates that AbstractWantedPanel with the cut Panel.
PanelCutting.FlippedPanel
— TypeFlippedPanel
FlippedPanel wraps a WantedPanel to indicate that its want can be satisfied by a panel even if its length and width are swapped.
This allows the user to control whether flipping is allowed of if they care about grain direction.
When either the original or the flipped panel is finished then its counterpart will be removed from the unsatisfied wants as well. The function wantsmatch
is used for this test.
PanelCutting.Panel
— TypePanel
Panel represents a panel that has been cut from an AvailablePanel but does not yet match an AbstractWantedPanel.
PanelCutting.ScrappedPanel
— TypeScrappedPanel
ScrappedPanel wraps a Panel that is not big enough to cut any remaining AbstractWantedPanel from.
PanelCutting.WantedPanel
— TypeWantedPanel
WantedPanel describes a panel that we need to have cut from some sheet stock. A Set of AbstractWantedPanels establishes the goal of our search.
PanelCutting.Panels
— TypePanels
An immutable collections of Panels
Our SearchState
objects contain several collections of panels. We'd like these collections to be immutable, like the SearchStates themselves.
When transitioning from one SearchState to its possible successor states, these collections could change in the following ways:
- a WantedPanel and possibly its flipped counterpart, might be removed and a FinishedPanel added
- one or two CuttablePanels added to stock panels
- CuttablePanels moved from stock to waste if they are too small for any remaining wanted panels
PanelCutting.progenitor
— Functionprogenitor(panel)
Return the BoughtPanel that this panel was cut from.
An AbstractPanel is its own progenitor.
A WantedPanel is its own progenitor.
A FlippedPanel is its own progenitor.
progenitor is used in the overlap test: panels can not overlap if they have different progenitors.
PanelCutting.PanelOverlapError
— TypePanelOverlapError
An error that is thrown when panels that shouldn'y overlap do.
Methodology
We start with a goal of producing a set of WantedPanel
s of specified sizes.
We then select an AvailablePanel
and cut it. Each cut potentially produces two new offcut Panels.
When one of these Panels matches a WanterPanel
we associate that Panel
with the WantedPanel
using a FinishedPanel
.
We give Panels an X and Y 'origin' origin as well as a length (along x) and width (along y) to simplify SVG generation.
Everything Else
PanelCutting.AllOf
— TypeAllof(iterables...)
combine the iterables into a single iterable.
PanelCutting.area
— Functionarea(panel)
Return the area of the panel.
PanelCutting.STYLESHEET
— ConstantThe CSS stylesheet we use for SVG rendering in reports.
PanelCutting.SVG_PANEL_MARGIN
— ConstantThe space between panels in an SVG drawing, and space between panels and SVG edge.
PanelCutting.callerFile
— FunctioncallerFile()
Return the path of the file of the function that called callerFile's caller. Also return the line number.
PanelCutting.compatible
— Functioncompatible(panel, panel2):Bool
Return true if the panels have the same thickness and material.
PanelCutting.cut
— Functioncut(panel, axis, at; kerf, cost)::(panel1, panel2)
Cut panel at the specified distance along axis. The first returned panel is the piece cut to that distance. The second is what remains (accounting for kerf).
An empty Tuple is returned if the cut can't be made.
PanelCutting.elt
— Functionelt(f, tagname::AbstractString, things...)
elt(tagname::AbstractString, things...)
Return an XML element. f
is called with a single argument: either an XML.AbstractXMLNode or a Pair describing an XML attribute to be added to the resulting element.
PanelCutting.fitsin
— Functionfitsin(small::AbstractPanel, big::AbstractPanel)::Bool
See if small can be cut from big.
PanelCutting.inPluto
— FunctioninPluto()::Bool
Return true if the notebook is being run in Pluto, artyher than directly in Julia (e.g. command line or REPL).
PanelCutting.major
— Functionmajor(panel)
Return the greater of the Panel's two dimensions.
PanelCutting.minor
— Functionminor(panel)
Return the lesser of the Panel's two dimensions.
PanelCutting.orFlipped
— FunctionorFlipped(::WantedPanel)
Return a Vector
of AbstractWantedPanel
consisting of the WantedPanel
and possibly its corresponding FlippedPanel
.
PanelCutting.other
— Functionother(axis)
returns the axis that is perpendicular to the specified axis.
PanelCutting.panelUID
— FunctionpanelUID()
Generate a unique identifier for each panel when it is created. We do this because Julia does not have a notion of equality that distibguishes between two separately created immutable structs with the same contents.
PanelCutting.panelrect
— Functionpanelrect(panel::AbstractPanel, numbering::FinishedPanelNumbering)
Return an SVG element that will draw the representation of the panel.
PanelCutting.replace0
— Functionreplace0(defaultX, defaultY, newX, newY)
Return newX and newY so long as they are not 0. If zero, use the corresponding default value.
PanelCutting.report
— Functionreport(::Searcher)
Generate an HTML fragment that provides a detailed report of our cut search and results.
PanelCutting.runCmd
— FunctionrunCmd(cmd::Cmd, cmdOutput::IO)::IO
Run the external command cmd
, which will write output to cmdOutput
. The stream that's returnd can be written to to provide inoput to the command. The second return value is the stderr stream.
PanelCutting.smaller
— Functionsmaller(p1::AbstractPanel, p2::AbstractPanel)::Bool
An ordering function for sorting panels by size. smaller(p1, p2) does not imply fitsin(p1, p2).
PanelCutting.Searcher
— TypeSearcher
This Searcher implements A* search using a PriorityQueue.
One could implement other searchers to implement, for example, depth or breadth first search.
PanelCutting.Supplier
— TypeSupplier(name::String, costpercut, kerf, available_stock::Vector{AvailablePanel})
A single supplier of sheet stock.
Some suppliers will cut shet stock down to the customer's specifications. kerf
is the width of their saw custs. cost_per_cut
is what they charge for each cut.
PanelCutting.svgdistance
— Functionsvgdistance(d)
Turn a Unitful length quantity to a floating point number we can use in SVG.
Index
PanelCutting.STYLESHEET
PanelCutting.SVG_PANEL_MARGIN
PanelCutting.AllOf
PanelCutting.AvailablePanel
PanelCutting.Back
PanelCutting.Bottom
PanelCutting.BoughtPanel
PanelCutting.Box
PanelCutting.ButtJoint
PanelCutting.DadoJoint
PanelCutting.Edge
PanelCutting.Face
PanelCutting.FingerJoint
PanelCutting.FinishedPanel
PanelCutting.FlippedPanel
PanelCutting.Front
PanelCutting.GDEither
PanelCutting.GDLong
PanelCutting.GDShort
PanelCutting.GrainDirection
PanelCutting.JointType
PanelCutting.Left
PanelCutting.Panel
PanelCutting.PanelOverlapError
PanelCutting.Panels
PanelCutting.Right
PanelCutting.ScrappedPanel
PanelCutting.Searcher
PanelCutting.Supplier
PanelCutting.Top
PanelCutting.WantedPanel
PanelCutting.WantedPanels
PanelCutting.area
PanelCutting.callerFile
PanelCutting.compatible
PanelCutting.cut
PanelCutting.distance
PanelCutting.do_faces
PanelCutting.elt
PanelCutting.fitsin
PanelCutting.inPluto
PanelCutting.major
PanelCutting.minor
PanelCutting.neighbors
PanelCutting.opposite
PanelCutting.orFlipped
PanelCutting.other
PanelCutting.panelUID
PanelCutting.panelrect
PanelCutting.progenitor
PanelCutting.replace0
PanelCutting.report
PanelCutting.runCmd
PanelCutting.smaller
PanelCutting.svgdistance