Script43_Subpacker.lua
-- Lua example for Autodesk Netfabb
-- Pack selected parts first, optionally generate a cage, follow up with remaining parts in two stages
-- Similar to script30 but requires manual selection for first packing stage
system:executescriptfile("Examples\\LUA Scripts\\BaseRoutines.lua")
system:setloggingtooglwindow(true)
--Set up settings
MontecarloAccuracy_Phase2 = 1
MontecarloMinDistance_Phase2 = 0
MCPackerPhase2Border = 0
MontecarloPartRotation_Phase2 = 1
MontecarloBorderspacez_Phase2 = 0
SLBorder = 0
SL_Accuracy = 0
SL_Voxelsize = 1
SL_Interlockprotection = 1
SL_RotationSteps = 3
SL_AllowFlip = 1
edit_MontecarloMinDistance_Phase2 = 0
edit_MontecarloBorderspacez_Phase2 = 0
edit_MCPackerPhase2Border = 0
comboboxEfficeny_MC_Phase2 = 0
edit_SLBorder = 0
combobox_Scaneline = 0
combobox_SL_Voxelsize = 0
combobox_SL_RotationSteps = 0
checkbox_SL_Interlockprotection = 0
checkbox_SL_AllowFlip = 0
Package_BarWidth = 0.8
Package_BarThickness = 1.2
Package_PartSpacing = 1.2
Package_GridSizeXY = 3.8
Package_GridSizeZ = 2.4
edit_Package_BarWidth = 0
edit_Package_BarThickness = 0
edit_Package_PartSpacing = 0
edit_Package_GridSizeXY = 0
edit_Package_GridSizeZ = 0
dialog_wf_model = nil
dialog_wf_model_haschanged = true
dialog_wf_model_iscancel = false
package_text = nil
package_dropdown = nil
pack_selected = 0
packagetray_dropdown = nil
packagetray_selected = 0
package_create_boxchecked = false
function local_mc_packtray(Actualtray)
local packer = Actualtray:createpacker(Actualtray.packingid_montecarlo)
packer.borderspacingxy = MCPackerPhase2Border
packer.borderspacingz = MontecarloBorderspacez_Phase2
packer.packing_quality = MontecarloAccuracy_Phase2
packer.minimaldistance = tonumber(MontecarloMinDistance_Phase2)
packer.z_limit = 0.0 -- If z_limit is set to zero, the default value, MachineSizeZ will be used
packer.start_from_current_positions = false
ret = packer:pack()
Actualtray:updatetodesktop()
return ret
end
-- Scanline pack tray
function local_sl_packtray(Actualtray)
local packer = Actualtray:createpacker(Actualtray.packingid_3d)
packer.allowrotationaxis = SL_AllowFlip
packer.coarsening = SL_Accuracy + 1
packer.interlockingprotection = SL_Interlockprotection
packer.minimizeoutbox = true
packer.anglecount = SL_RotationSteps
packer.rastersize = SL_Voxelsize
packer.borderspacingxy = SLBorder
ret = packer:pack()
Actualtray:updatetodesktop()
return ret
end
function removetmptray()
local my_index = 0
for tray_index = 1, netfabbtrayhandler.traycount - 1 do
local tray = netfabbtrayhandler:gettray(tray_index)
if tray.name == "TMP_TRAY" then
my_index = tray_index
break
end
end
local ret = -1
if my_index ~= 0 then
ret = netfabbtrayhandler:removetray(my_index)
end
return ret
end
function model_pack_selected()
local meshes = {}
local selected_meshes = 0
local total_volume = 0
local total_ob_volume = 0
local calc_x = 0
local all_fits = false
local pack_result = 0
local number_of_packs = 0
local the_tray = netfabbtrayhandler:gettray(packagetray_selected)
for mesh_index = 0, the_tray.root.meshcount - 1 do
local traymesh = the_tray.root:getmesh(mesh_index)
if traymesh.selected then
table.insert(meshes, traymesh)
selected_meshes = selected_meshes + 1
total_volume = total_volume + traymesh.volume
total_ob_volume = total_ob_volume + traymesh.outboxvolume
calc_x = math.pow(total_ob_volume, 1 / 3)
end
end
if selected_meshes == 0 then
return 1
end
system:log(
"Selected meshes:" ..
selected_meshes .. " Volume: " .. total_volume .. " Bounding box volume: " .. total_ob_volume .. " X: " .. calc_x
)
while not all_fits do
local tmptray = netfabbtrayhandler:addtray("TMP_TRAY", calc_x, calc_x, calc_x)
copy2tray(meshes, tmptray)
if pack_selected == 0 then -- MC packer
pack_result = local_mc_packtray(tmptray)
else -- Scanline packer
pack_result = local_sl_packtray(tmptray)
end
number_of_packs = number_of_packs + 1
if pack_result > 0 and pack_result < 4 then -- parts do no fit
calc_x = calc_x + (calc_x / 10)
removemeshesfromtray(tmptray)
removetmptray()
elseif pack_result == 0 then -- all packed
local my_mesh = system:createmesh()
for mesh_index = 0, tmptray.root.meshcount - 1 do
local traymesh = tmptray.root:getmesh(mesh_index)
newMesh = traymesh.mesh:dupe()
local matrix = traymesh.matrix
newMesh:applymatrix(matrix)
my_mesh:merge(newMesh)
end
if package_create_boxchecked == false then
tray.root:addmesh(my_mesh)
removemeshesfromtray(tmptray)
removetmptray()
all_fits = true
else
if package_text.text ~= nil and package_text.text ~= "" then
newname = package_text.text
else
newname = "Cage with " .. selected_meshes .. " mesh(es)"
end
newcage =
my_mesh:createmodelpackage(
Package_BarWidth,
Package_BarThickness,
Package_PartSpacing,
Package_GridSizeXY,
Package_GridSizeZ,
newname
)
my_mesh:merge(newcage)
tray.root:addmesh(my_mesh, newname)
removemeshesfromtray(tmptray)
removetmptray()
all_fits = true
end
else -- some serious error
removemeshesfromtray(tmptray)
removetmptray()
system:log("Packing fatal error: " .. pack_result)
all_fits = true
return 2
end
if number_of_packs > 10 then
return 3
end
end
return 0
end
function GetValuesFromGui()
MontecarloMinDistance_Phase2 = tonumber(edit_MontecarloMinDistance_Phase2.text)
MontecarloBorderspacez_Phase2 = tonumber(edit_MontecarloBorderspacez_Phase2.text)
MCPackerPhase2Border = tonumber(edit_MCPackerPhase2Border.text)
MontecarloAccuracy_Phase2 = comboboxEfficeny_MC_Phase2.selecteditem
MontecarloPartRotation_Phase2 = comboboxRotationConstraint_MC_Phase2.selecteditem
SLBorder = tonumber(edit_SLBorder.text)
SL_Accuracy = combobox_Scaneline.selecteditem
SL_Voxelsize = combobox_SL_Voxelsize.selecteditem
SL_RotationSteps = combobox_SL_RotationSteps.selecteditem
if checkbox_SL_Interlockprotection.checked then
SL_Interlockprotection = 1
else
SL_Interlockprotection = 0
end
if checkbox_SL_AllowFlip.checked then
SL_AllowFlip = 1
else
SL_AllowFlip = 0
end
Package_BarWidth = tonumber(edit_Package_BarWidth.text)
Package_BarThickness = tonumber(edit_Package_BarThickness.text)
Package_PartSpacing = tonumber(edit_Package_PartSpacing.text)
Package_GridSizeXY = tonumber(edit_Package_GridSizeXY.text)
Package_GridSizeZ = tonumber(edit_Package_GridSizeZ.text)
end
function show_dialog_wf_model_ok()
GetValuesFromGui()
local ret = model_pack_selected()
if ret ~= 0 then
local message = ""
local exit_state = false
if ret == 1 then
message = "No selected models found in tray!"
elseif ret == 2 then
message = "Fatal packing error, exit"
exit_state = true
elseif ret == 3 then
message = "Too many iterations, exit"
exit_state = true
else
message = "Unknown error, exit"
exit_state = true
end
system:messagedlg(message)
dialog_wf_model:close(exit_state)
end
removetmptray()
application:triggerdesktopevent("updateparts")
dialog_wf_model:close(true)
end
function dialog_wf_model_pack_change()
pack_selected = package_dropdown.selecteditem
dialog_wf_model_haschanged = true
dialog_wf_model:close(false)
end
function dialog_wf_model_pack2_change()
packagetray_selected = packagetray_dropdown.selecteditem
dialog_wf_model_haschanged = true
dialog_wf_model:close(false)
end
function show_dialog_wf_model_oncancel()
dialog_wf_model_iscancel = true
dialog_wf_model:close(false)
end
function show_dialog_wf_model()
local dialog, groupbox, label, dropdown, subbox1, edit, checkbox1, checkbox2, splitter, button, slider
local default_wide1 = 150
local d_w = 450
dialog = application:createdialog()
tabcontrol = dialog:addtabcontrol()
dialog.caption = "Sub-pack"
dialog.width = d_w
dialog.translatecaption = false
dialog_wf_model = dialog
sheet = tabcontrol:addtabsheet()
sheet.caption = "Main settings"
sheet.translate = false
local groupboxExplanation = sheet:addgroupbox()
groupboxExplanation.caption = "Explanation"
groupboxExplanation.translate = false
label = groupboxExplanation:addlabel()
label.caption = "Selected parts will be packed in sub area of the build room."
label.translate = false
label = groupboxExplanation:addlabel()
label.caption = "The size of the packed area will be as small as possible. "
label.translate = false
groupboxMainSettings = sheet:addgroupbox()
groupboxMainSettings.caption = "Settings"
groupboxMainSettings.borderstyle = 1
groupboxMainSettings.horizontalpadding = 10
groupboxMainSettings.verticalpadding = 10
groupboxMainSettings.translate = false
dropdown = groupboxMainSettings:adddropdown()
dropdown.caption = "Select tray: "
dropdown.captionwidth = default_wide1
dropdown.translatecaption = false
for tray_index = 0, netfabbtrayhandler.traycount - 1 do
local model_tray = netfabbtrayhandler:gettray(tray_index)
local model_tname = model_tray.name
if tray_index == 0 then
model_tname = "Default tray"
end
dropdown:additem(model_tname, tray_index, 0, false)
end
dropdown.selecteditem = packagetray_selected
dropdown.onchange = "dialog_wf_model_pack2_change"
packagetray_dropdown = dropdown
dropdown = groupboxMainSettings:adddropdown()
dropdown.caption = "Which Packer to use: "
dropdown.captionwidth = default_wide1
dropdown.translatecaption = false
dropdown:additem("MonteCarlo", 0, 0, false)
dropdown:additem("Scanline", 1, 0, false)
dropdown.selecteditem = pack_selected
dropdown.onchange = "dialog_wf_model_pack_change"
package_dropdown = dropdown
checkbox1 = groupboxMainSettings:addcheckbox()
checkbox1.caption = "Create package?"
checkbox1.translate = false
checkbox1.onclick = "select_create_package_box"
checkbox1.checked = package_create_boxchecked
package_checkbox = checkbox
checkbox2 = groupboxMainSettings:addcheckbox()
checkbox2.caption = "Merge parts?"
checkbox2.translate = false
package_checkbox = checkbox
edit = groupboxMainSettings:addedit()
edit.caption = "Label package cage:"
edit.captionwidth = default_wide1
edit.text = ""
edit.translate = false
edit.enabled = true
package_text = edit
splitter = dialog:addsplitter()
splitter:settoleft()
button = splitter:addbutton()
button.caption = "OK"
button.translate = false
button.onclick = "show_dialog_wf_model_ok"
splitter:settoright()
button = splitter:addbutton()
button.caption = "Cancel"
button.translate = false
button.onclick = "show_dialog_wf_model_oncancel"
--Packersetting
sheet = tabcontrol:addtabsheet()
sheet.caption = "Packer settings"
sheet.translate = false
local groupboxMCPacker_Phase2 = sheet:addgroupbox()
groupboxMCPacker_Phase2.caption = "ADVPACKER_PACKERETTINGS_MCPPHASE2"
groupboxMCPacker_Phase2.translate = true
edit = groupboxMCPacker_Phase2:addedit()
edit.caption = "ADVPACKER_PACKERETTINGS_MINDISTBETWEENPART"
edit.captionwidth = 300
edit.translate = true
edit.text = tostring(MontecarloMinDistance_Phase2)
edit_MontecarloMinDistance_Phase2 = edit
edit = groupboxMCPacker_Phase2:addedit()
edit.caption = "ADVPACKER_PACKERETTINGS_DISTANCESIDEWALLS"
edit.captionwidth = 300
edit.translate = true
edit.text = tostring(MCPackerPhase2Border)
edit_MCPackerPhase2Border = edit
edit = groupboxMCPacker_Phase2:addedit()
edit.caption = "ADVPACKER_PACKERETTINGS_DISTANCEPLATFORM"
edit.captionwidth = 300
edit.translate = true
edit.text = tostring(MontecarloBorderspacez_Phase2)
edit_MontecarloBorderspacez_Phase2 = edit
comboboxEfficeny_MC_Phase2 = groupboxMCPacker_Phase2:adddropdown()
comboboxEfficeny_MC_Phase2.caption = "FORM_MONTECARLOPACKER_PACKINGQUALITY"
comboboxEfficeny_MC_Phase2.captionwidth = 300
comboboxEfficeny_MC_Phase2.translate = true
comboboxEfficeny_MC_Phase2:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_1", 8, 5, true, false)
comboboxEfficeny_MC_Phase2:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_2", 4, 4, true, false)
comboboxEfficeny_MC_Phase2:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_3", 0, 3, true, false)
comboboxEfficeny_MC_Phase2:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_4", -4, 2, true, false)
comboboxEfficeny_MC_Phase2:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_5", -8, 1, true, false)
comboboxEfficeny_MC_Phase2.selecteditem = MontecarloAccuracy_Phase2
comboboxRotationConstraint_MC_Phase2 = groupboxMCPacker_Phase2:adddropdown()
comboboxRotationConstraint_MC_Phase2.caption = "FORM_MONTECARLOPACKER_ITEMROTATION"
comboboxRotationConstraint_MC_Phase2.captionwidth = 300
comboboxRotationConstraint_MC_Phase2.translate = true
comboboxRotationConstraint_MC_Phase2:additem("FORM_MONTECARLOPACKER_ITEMROTATION_ARBITRARY", 0, 3, true, false)
comboboxRotationConstraint_MC_Phase2:additem("FORM_MONTECARLOPACKER_ITEMROTATION_ZAXIS", 1, 2, true, false)
comboboxRotationConstraint_MC_Phase2:additem("FORM_MONTECARLOPACKER_ITEMROTATION_FORBIDDEN", 2, 1, true, false)
comboboxRotationConstraint_MC_Phase2.selecteditem = MontecarloPartRotation_Phase2
local groupboxScanLinePacker = sheet:addgroupbox()
groupboxScanLinePacker.caption = "ADVPACKER_PACKERETTINGS_SLPHASE3"
groupboxScanLinePacker.translate = true
combobox_SL_Voxelsize = groupboxScanLinePacker:adddropdown()
combobox_SL_Voxelsize.caption = "FORM_DEFAULT_3DPACKING_GRIDSIZE"
combobox_SL_Voxelsize.captionwidth = 300
combobox_SL_Voxelsize.translate = true
combobox_SL_Voxelsize:additem("1 mm", 1, 1, false, false)
combobox_SL_Voxelsize:additem("2 mm", 2, 2, false, false)
combobox_SL_Voxelsize:additem("3 mm", 3, 3, false, false)
combobox_SL_Voxelsize:additem("4 mm", 4, 4, false, false)
combobox_SL_Voxelsize:additem("5 mm", 5, 5, false, false)
combobox_SL_Voxelsize.selecteditem = SL_Voxelsize
combobox_SL_RotationSteps = groupboxScanLinePacker:adddropdown()
combobox_SL_RotationSteps.caption = "FORM_DEFAULT_3DPACKING_ZROTATION"
combobox_SL_RotationSteps.captionwidth = 300
combobox_SL_RotationSteps.translate = true
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS0", 0, 0, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS1", 1, 1, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS2", 2, 2, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS3", 3, 3, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS4", 4, 4, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS5", 5, 5, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS6", 6, 6, true, false)
combobox_SL_RotationSteps:additem("ADVPACKER_PACKERETTINGS_SL_ROTATIONSTEPS7", 7, 7, true, false)
combobox_SL_RotationSteps.selecteditem = SL_RotationSteps
edit = groupboxScanLinePacker:addedit()
edit.caption = "ADVPACKER_PACKERETTINGS_DISTANCESIDEWALLS"
edit.captionwidth = 300
edit.translate = true
edit.text = tostring(SLBorder)
edit_SLBorder = edit
combobox_Scaneline = groupboxScanLinePacker:adddropdown()
combobox_Scaneline.caption = "FORM_MONTECARLOPACKER_PACKINGQUALITY"
combobox_Scaneline.captionwidth = 300
combobox_Scaneline.translate = true
combobox_Scaneline:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_1", 1, 5, true, false)
combobox_Scaneline:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_2", 2, 4, true, false)
combobox_Scaneline:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_3", 3, 3, true, false)
combobox_Scaneline:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_4", 4, 2, true, false)
combobox_Scaneline:additem("FORM_MONTECARLOPACKER_PACKINGQUALITY_5", 5, 1, true, false)
combobox_Scaneline.selecteditem = SL_Accuracy
checkbox = groupboxScanLinePacker:addcheckbox()
checkbox.caption = "FORM_DEFAULT_3DPACKING_INTERLOCKINGPROTECTION"
checkbox.translate = true
checkbox_SL_Interlockprotection = checkbox
if SL_Interlockprotection == 1 then
checkbox_SL_Interlockprotection.checked = true
else
checkbox_SL_Interlockprotection.checked = false
end
checkbox = groupboxScanLinePacker:addcheckbox()
checkbox.caption = "FORM_DEFAULT_3DPACKING_FLIPUPSIDEDOWN"
checkbox.translate = true
checkbox_SL_AllowFlip = checkbox
if SL_AllowFlip == 1 then
checkbox_SL_AllowFlip.checked = true
else
checkbox_SL_AllowFlip.checked = false
end
-- local Package_BarWidth = 0;
-- local Package_BarThickness = 0;
-- local Package_PartSpacing = 0;
-- local Package_GridSizeXY = 0;
-- local Package_GridSizeZ = 0;
--Packagesetting
sheet = tabcontrol:addtabsheet()
sheet.caption = "Package settings"
sheet.translate = false
local groupboxPackageSetting = sheet:addgroupbox()
groupboxPackageSetting.caption = "Package settings"
groupboxPackageSetting.translate = false
edit = groupboxPackageSetting:addedit()
edit.caption = "Bar width"
edit.captionwidth = 300
edit.translate = false
edit.text = tostring(Package_BarWidth)
edit_Package_BarWidth = edit
edit = groupboxPackageSetting:addedit()
edit.caption = "Bar thickness"
edit.captionwidth = 300
edit.translate = false
edit.text = tostring(Package_BarThickness)
edit_Package_BarThickness = edit
edit = groupboxPackageSetting:addedit()
edit.caption = "Part spacing"
edit.captionwidth = 300
edit.translate = false
edit.text = tostring(Package_PartSpacing)
edit_Package_PartSpacing = edit
edit = groupboxPackageSetting:addedit()
edit.caption = "Grid size XY"
edit.captionwidth = 300
edit.translate = false
edit.text = tostring(Package_GridSizeXY)
edit_Package_GridSizeXY = edit
edit = groupboxPackageSetting:addedit()
edit.caption = "Grid size Z"
edit.captionwidth = 300
edit.translate = false
edit.text = tostring(Package_GridSizeZ)
edit_Package_GridSizeZ = edit
if dialog:show() then
return true
end
return false
end
function wf_modelpack()
system:setloggingtooglwindow(true)
while dialog_wf_model_haschanged do
if show_dialog_wf_model() then
dialog_wf_model_haschanged = true
return
else
if dialog_wf_model_iscancel then
dialog_wf_model_iscancel = false
dialog_wf_model_haschanged = true
return
end
end
end
end
function select_create_package_box()
if package_create_boxchecked == false then
package_create_boxchecked = true
else
package_create_boxchecked = false
end
end
-- Model Package workflow END
wf_modelpack()