From 04c7b07d0e48b671a72b240ee40d4dbf0efcdb14 Mon Sep 17 00:00:00 2001 From: Emmanuele Sassi Date: Thu, 16 Sep 2021 16:24:59 +0200 Subject: [PATCH] Primo commit --- .gitignore | 334 +++++++ Config.lua | 163 ++++ Config.lua.my | 152 +++ Errors.txt | 11 + Generate.lua | 73 ++ Main.lua | 1118 ++++++++++++++++++++++ NestingLib.lua | 2498 ++++++++++++++++++++++++++++++++++++++++++++++++ RESTLib.lua | 62 ++ UtilityLib.lua | 250 +++++ 9 files changed, 4661 insertions(+) create mode 100644 .gitignore create mode 100644 Config.lua create mode 100644 Config.lua.my create mode 100644 Errors.txt create mode 100644 Generate.lua create mode 100644 Main.lua create mode 100644 NestingLib.lua create mode 100644 RESTLib.lua create mode 100644 UtilityLib.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d61017f --- /dev/null +++ b/.gitignore @@ -0,0 +1,334 @@ +# ---> VisualStudio +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ +32/ +64/ +OrigClientServer/ +UpdateClientServer/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc +*.bat + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# ---> C Sharp +# Build Folders (you can keep bin if you'd like, to store dlls and pdbs) +[Bb]in/ +[Oo]bj/ + +# mstest test results +TestResults + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +x64/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.log +*.vspscc +*.vssscc +.builds + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper* + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +packages + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +[Bb]in +[Oo]bj +sql +TestResults +[Tt]est[Rr]esult* +*.Cache +ClientBin +[Ss]tyle[Cc]op.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + diff --git a/Config.lua b/Config.lua new file mode 100644 index 0000000..f894508 --- /dev/null +++ b/Config.lua @@ -0,0 +1,163 @@ +-- +-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT +-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEEEEEEEE GGGGGGGGGG TTTT +-- EEEEEEEEEE GGGGGG TTTT +-- +-- by EgalTech s.r.l. +-- File dei parametri di configurazione by EgalTech s.r.l. 2020/08/13 + +-- Tabella per definizione modulo +local Config = {} + +-------------------------- Main ------------------------- + +-- path chiamate REST +Config.sRESTPath = "http://seriate.steamware.net:8082/NKC/api/" +Config.sPathMat = Config.sRESTPath .. "Material" +Config.sPathBatch = Config.sRESTPath .. "BatchProc" +-- Nesting cycle waiting time +Config.CycleDelay = 3 + +-- Max bunk height +Config.MaxBunkThickness = 450 + +-- save data path +Config.sBasePath = "c:/Users/Dell/Dropbox/SVG" +----------------------------- NestingLib --------------------------------------- + +-- single nesting time for final nesting +Config.nFinalMaxTime = 5 +-- single nesting time for estimation +Config.nEstimMaxTime = 5 + +-- table of association layer names to machinings -> {{"LayerName"}, {'Machining1', 'Machining2', ...}} +Config.OutlineMachining = {{".375 ROUGHER", "ROUGHER"}, + {'3/8 MILLING', '1/4 MILLING'}} +Config.HoleMachining = {"HOLE", {'3/16 DRILLING', '1/4 DRILLING', '1/2 DRILLING', '1/8 DRILLING', '11/32 DRILLING', '13/32 DRILLING', + '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '17/32 DRILLING', '37/64 DRILLING'}} +Config.RampMachining = {"RAMP", '3/8 MILLING'} +-- list of pocketing machinings +Config.Pocketing = {'3/8 POCKETING', '1/4 POCKETING'} + + +Config.OutlineMachName = {".375 ROUGHER", "ROUGHER"} +Config.MXOutlineMachTools = {'3/8 MILLING', '1/4 MILLING'} +Config.NWOutlineMachTools = {'3/8 MILLING', '1/4 MILLING'} +Config.HoleMachName = {"HOLE"} +Config.MXHoleMachTools = {'3/16 DRILLING', '1/4 DRILLING', '1/2 DRILLING', '1/8 DRILLING', '11/32 DRILLING', '13/32 DRILLING', + '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '17/32 DRILLING', '37/64 DRILLING'} +Config.NWHoleMachTools = {'1/2 DRILLING', '1/8 DRILLING', '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '37/64 DRILLING', '1/4 DRILLING'} +Config.RampMachName = {"RAMP"} +Config.MXRampMachTools = {'3/8 MILLING'} +Config.NWRampMachTools = {'3/8 MILLING'} +Config.MXPocketingTools = {'3/8 POCKETING', '1/4 POCKETING'} +Config.NWPocketingTools = {'3/8 POCKETING', '1/4 POCKETING'} + +-- tolerance betwwen start and end of a path to consider it closed +Config.OpenPathTolerance = 0.01 +-- tolerance between part thickness and material thickness to consider a hole throught +Config.ThicknessTolerance = 0.09 +-- remnant minimum dimension +Config.RemnantMinDimension = 304.8 +-- minimum area in which position internal parts +Config.IntPartMinArea = 5000 +-- tolerance between hole diameter and tool diameter +Config.HoleTolerance = 0.1 + +-- managing small parts (tabs,skeleton, ...) +Config.nSkelSkinTabMode = 2 -- 0 = nothing ; 2 = Tabs ; 3 = Skeleton ; 4 = Skeleton&Tab +Config.dSkelSkinTab_MaxArea = 36500 --- area limit + +-- color for paths pocketing +Config.colPocketingPaths = Color3d( 0, 255, 255) +-- suddivisione area pezzi in categorie per ordinamento lavorazione dei pezzi +Config.dVerySmallPartArea = 3225 +Config.dSmallPartArea = 15200 -- 11612 +Config.dMediumPartArea = 60000 +-- lato massimo per rientrare in pezzi piccoli anche se con area grande +Config.dSmallPartSide = 50.8 + +-- attivazione distruzione scheletro +Config.bSkeletonReduction = true +Config.bSRMaxHeight = 100 * 25.4 +Config.bSRMaxWidth = 30 * 25.4 +-- quantita' di cui il taglio skeleton entra nello spazio vuoto di taglio pezzi +Config.dSkeletonCut = 0.5 + +-- spessore scheletro pezzi piccoli +Config.dSkeletonWidth = 1 * 25.4 + +-- riduzione feed su pezzi piccoli +Config.bSmallFeedReduce = true +Config.dSmallFeed = 8000 + +-- variabile che indica se modalita' doppia macchina +Config.bDoubleMach = false + +-- tab parameters for each material +Config.TabParams = {{MatId = 1, MatExtCode = 6120, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 2, MatExtCode = 6110, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 3, MatExtCode = 6049, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 4, MatExtCode = 6118, Length = 10.0, Height = 2.0, Angle = 30, Distance = 50, MinCount = 6, MaxCount = 12}, + {MatId = 5, MatExtCode = 6479, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 6, MatExtCode = 6408, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 7, MatExtCode = 6406, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 8, MatExtCode = 6478, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 9, MatExtCode = 6473, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 10, MatExtCode = 6474, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 11, MatExtCode = 6423, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 12, MatExtCode = 112268, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 13, MatExtCode = 119169, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 14, MatExtCode = 121214, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 15, MatExtCode = 111625, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 16, MatExtCode = 6127, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 17, MatExtCode = 6044, Length = 15.0, Height = 3.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 18, MatExtCode = 101523, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 19, MatExtCode = 6117, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 20, MatExtCode = 6119, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 21, MatExtCode = 6115, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 24, MatExtCode = 108360, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 25, MatExtCode = 124880, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + } + +-- parts minimum distance from raw part outline for each material +Config.Kerf = {{MatId = 1, MatExtCode = 6120, Kerf = 8}, + {MatId = 2, MatExtCode = 6110, Kerf = 20}, + {MatId = 3, MatExtCode = 6049, Kerf = 20}, + {MatId = 4, MatExtCode = 6118, Kerf = 20}, + {MatId = 5, MatExtCode = 6479, Kerf = 20}, + {MatId = 6, MatExtCode = 6408, Kerf = 20}, + {MatId = 7, MatExtCode = 6406, Kerf = 20}, + {MatId = 8, MatExtCode = 6478, Kerf = 30}, + {MatId = 9, MatExtCode = 6473, Kerf = 20}, + {MatId = 10, MatExtCode = 6474, Kerf = 20}, + {MatId = 11, MatExtCode = 6423, Kerf = 20}, + {MatId = 12, MatExtCode = 112268, Kerf = 20}, + {MatId = 13, MatExtCode = 119169, Kerf = 20}, + {MatId = 14, MatExtCode = 121214, Kerf = 20}, + {MatId = 15, MatExtCode = 111625, Kerf = 20}, + {MatId = 16, MatExtCode = 6127, Kerf = 20}, + {MatId = 17, MatExtCode = 6044, Kerf = 20}, + {MatId = 18, MatExtCode = 101523, Kerf = 20}, + {MatId = 19, MatExtCode = 6117, Kerf = 20}, + {MatId = 20, MatExtCode = 6119, Kerf = 20}, + {MatId = 21, MatExtCode = 6115, Kerf = 20}, + {MatId = 24, MatExtCode = 108360, Kerf = 20}, + {MatId = 25, MatExtCode = 124880, Kerf = 20}, + } + +Config.KitXModel = {{Model = '65w981', KitQty = 6}, + {Model = '62163t', KitQty = 12}, + {Model = '65w981s', KitQty = 6}, + {Model = '53xhp81', KitQty = 10}, + } + +--------------------------------------------------------------------- +return Config diff --git a/Config.lua.my b/Config.lua.my new file mode 100644 index 0000000..5646cc8 --- /dev/null +++ b/Config.lua.my @@ -0,0 +1,152 @@ +-- +-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT +-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEEEEEEEE GGGGGGGGGG TTTT +-- EEEEEEEEEE GGGGGG TTTT +-- +-- by EgalTech s.r.l. +-- File dei parametri di configurazione by EgalTech s.r.l. 2020/08/13 + +-- Tabella per definizione modulo +local Config = {} + +-------------------------- Main ------------------------- + +-- path chiamate REST +Config.sRESTPath = "http://seriate.steamware.net:8083/NKC/api/" +Config.sPathMat = Config.sRESTPath .. "Material" +Config.sPathBatch = Config.sRESTPath .. "BatchProc" +-- Nesting cycle waiting time +Config.CycleDelay = 3 + +-- Max bunk height +Config.MaxBunkThickness = 450 + +-- save data path +Config.sBasePath = "c:/Users/Dell/Dropbox/SVG" + +----------------------------- NestingLib --------------------------------------- + +-- single nesting time for final nesting +Config.nFinalMaxTime = 5 +-- single nesting time for estimation +Config.nEstimMaxTime = 5 + +-- table of association layer names to machinings -> {{"LayerName"}, {'Machining1', 'Machining2', ...}} +Config.OutlineMachining = {{".375 ROUGHER", "ROUGHER"}, + {'3/8 MILLING', '1/4 MILLING'}} +Config.HoleMachining = {"HOLE", {'3/16 DRILLING', '1/4 DRILLING', '1/2 DRILLING', '1/8 DRILLING', '11/32 DRILLING', '13/32 DRILLING', + '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '17/32 DRILLING', '37/64 DRILLING'}} +Config.RampMachining = {"RAMP", '3/8 MILLING'} +-- list of pocketing machinings +Config.Pocketing = {'3/8 POCKETING', '1/4 POCKETING'} + + +Config.OutlineMachName = {".375 ROUGHER", "ROUGHER"} +Config.MXOutlineMachTools = {'3/8 MILLING', '1/4 MILLING'} +Config.NWOutlineMachTools = {'3/8 MILLING', '1/4 MILLING'} +Config.HoleMachName = {"HOLE"} +Config.MXHoleMachTools = {'3/16 DRILLING', '1/4 DRILLING', '1/2 DRILLING', '1/8 DRILLING', '11/32 DRILLING', '13/32 DRILLING', + '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '17/32 DRILLING', '37/64 DRILLING'} +Config.NWHoleMachTools = {'1/2 DRILLING', '1/8 DRILLING', '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '37/64 DRILLING', '1/4 DRILLING'} +Config.RampMachName = {"RAMP"} +Config.MXRampMachTools = {'3/8 MILLING'} +Config.NWRampMachTools = {'3/8 MILLING'} +Config.MXPocketingTools = {'3/8 POCKETING', '1/4 POCKETING'} +Config.NWPocketingTools = {'3/8 POCKETING', '1/4 POCKETING'} + +-- tolerance betwwen start and end of a path to consider it closed +Config.OpenPathTolerance = 0.01 +-- tolerance between part thickness and material thickness to consider a hole throught +Config.ThicknessTolerance = 0.09 +-- remnant minimum dimension +Config.RemnantMinDimension = 304.8 +-- minimum area in which position internal parts +Config.IntPartMinArea = 5000 +-- tolerance between hole diameter and tool diameter +Config.HoleTolerance = 0.1 + +-- managing small parts (tabs,skeleton, ...) +Config.nSkelSkinTabMode = 2 -- 0 = nothing ; 2 = Tabs ; 3 = Skeleton ; 4 = Skeleton&Tab +Config.dSkelSkinTab_MaxArea = 36500 --- area limit + +-- color for paths pocketing +Config.colPocketingPaths = Color3d( 0, 255, 255) +-- suddivisione area pezzi in categorie per ordinamento lavorazione dei pezzi +Config.dVerySmallPartArea = 3225 +Config.dSmallPartArea = 15200 -- 11612 +Config.dMediumPartArea = 60000 +-- lato massimo per rientrare in pezzi piccoli anche se con area grande +Config.dSmallPartSide = 50.8 + +-- attivazione distruzione scheletro +Config.bSkeletonReduction = true +Config.bSRMaxHeight = 100 * 25.4 +Config.bSRMaxWidth = 30 * 25.4 +-- quantita' di cui il taglio skeleton entra nello spazio vuoto di taglio pezzi +Config.dSkeletonCut = 0.5 + +-- spessore scheletro pezzi piccoli +Config.dSkeletonWidth = 1 * 25.4 + +-- riduzione feed su pezzi piccoli +Config.bSmallFeedReduce = true +Config.dSmallFeed = 8000 + +-- tab parameters for each material +Config.TabParams = {{MatId = 1, MatExtCode = 6120, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 2, MatExtCode = 6110, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 3, MatExtCode = 6049, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 4, MatExtCode = 6118, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 5, MatExtCode = 6479, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 6, MatExtCode = 6408, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 7, MatExtCode = 6406, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 8, MatExtCode = 6478, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 9, MatExtCode = 6473, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 10, MatExtCode = 6474, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 11, MatExtCode = 6423, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 12, MatExtCode = 112268, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 13, MatExtCode = 119169, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 14, MatExtCode = 121214, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 15, MatExtCode = 111625, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 16, MatExtCode = 6127, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 17, MatExtCode = 6044, Length = 15.0, Height = 3.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 18, MatExtCode = 101523, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 19, MatExtCode = 6117, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 20, MatExtCode = 6119, Length = 10.0, Height = 1.5, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + {MatId = 21, MatExtCode = 6115, Length = 10.0, Height = 2.0, Angle = 30, Distance = 60, MinCount = 3, MaxCount = 4}, + } + +-- parts minimum distance from raw part outline for each material +Config.Kerf = {{MatId = 1, MatExtCode = 6120, Kerf = 20}, + {MatId = 2, MatExtCode = 6110, Kerf = 20}, + {MatId = 3, MatExtCode = 6049, Kerf = 20}, + {MatId = 4, MatExtCode = 6118, Kerf = 20}, + {MatId = 5, MatExtCode = 6479, Kerf = 20}, + {MatId = 6, MatExtCode = 6408, Kerf = 20}, + {MatId = 7, MatExtCode = 6406, Kerf = 20}, + {MatId = 8, MatExtCode = 6478, Kerf = 30}, + {MatId = 9, MatExtCode = 6473, Kerf = 20}, + {MatId = 10, MatExtCode = 6474, Kerf = 20}, + {MatId = 11, MatExtCode = 6423, Kerf = 20}, + {MatId = 12, MatExtCode = 112268, Kerf = 20}, + {MatId = 13, MatExtCode = 119169, Kerf = 20}, + {MatId = 14, MatExtCode = 121214, Kerf = 20}, + {MatId = 15, MatExtCode = 111625, Kerf = 20}, + {MatId = 16, MatExtCode = 6127, Kerf = 20}, + {MatId = 17, MatExtCode = 6044, Kerf = 20}, + {MatId = 18, MatExtCode = 101523, Kerf = 20}, + {MatId = 19, MatExtCode = 6117, Kerf = 20}, + {MatId = 20, MatExtCode = 6119, Kerf = 20}, + {MatId = 21, MatExtCode = 6115, Kerf = 20}, + } + + +--------------------------------------------------------------------- +return Config diff --git a/Errors.txt b/Errors.txt new file mode 100644 index 0000000..24e0746 --- /dev/null +++ b/Errors.txt @@ -0,0 +1,11 @@ +E.1 -> "Can't find DXF file" +E.2 -> "Can't find material tag in DXF" +E.4 -> "Can't find outline" +E.6 -> "Error in DXF reading" +E.7 -> "Impossible running estimation!", "Error in machining!" +E.8 -> "Open paths found" +E.9 -> "Outline tool diameter not found!" +E.10 -> "Error in nesting function!" +E.12 -> "Error on control counting. Lost part, sheet, bunk, etc..." +E.13 -> "Error, outline thickness must be negative!" +E.14 -> "There are entities that are not CompositeCurves or Arcs" \ No newline at end of file diff --git a/Generate.lua b/Generate.lua new file mode 100644 index 0000000..85d57f7 --- /dev/null +++ b/Generate.lua @@ -0,0 +1,73 @@ +-- necessary to find socket.core and mime.core +package.cpath = package.cpath .. ";/EgtProg/LuaLibs/?.dll" + +require( 'EgtBase') +_ENV = EgtProtectGlobal() +EgtEnableDebug( true) + +local AREA = "Area" + +local BasePath = "c:/Users/Dell/Dropbox/SVG" +local BatchDateId = "/2021/6/629" + +local MaxMatId = 25 +for MatId = 1, MaxMatId do + -- apro file + if EgtOpenFile(BasePath .. "/Nesting" .. BatchDateId .. "/" .. MatId .. ".nge") then + -- vado su gruppi di lavorazione + local nSheetGroupId = EgtGetFirstMachGroup() + while nSheetGroupId do + local sGroupName = EgtGetMachGroupName(nSheetGroupId) + local bOk = EgtSetCurrMachGroup(nSheetGroupId) + local nOp = EgtGetFirstOperation() +-- while nOp and false do +-- if EgtGetOperationType(nOp) == MCH_OY.MILLING then +-- local bOk = EgtSetCurrMachining(nOp) +-- local nOut = EgtGetMachiningGeometry() +-- local nPart = EgtGetParent(EgtGetParent(nOut[1][1])) +-- local dArea = EgtGetInfo(nPart, AREA, 'd') +-- +-- --local b3Part = EgtGetBBox(nPart, 13) +-- +-- if EgtGetMachiningParam(MCH_MP.USERNOTES) == 'Outline = 1' then -- and (b3Part:getX() < 18 * GEO.ONE_INCH or b3Part:getY() < 18 * GEO.ONE_INCH) then +-- EgtSetMachiningParam(MCH_MP.INVERT, true) +-- if dArea and dArea < 11652 then +-- EgtSetMachiningParam(MCH_MP.LEAVETAB, true) +-- EgtSetMachiningParam(MCH_MP.TABMIN, 2) +-- EgtSetMachiningParam(MCH_MP.TABMAX, 4) +-- EgtSetMachiningParam(MCH_MP.TABDIST, 60) +-- elseif dArea and dArea < 36500 then +-- EgtSetMachiningParam(MCH_MP.LEAVETAB, true) +-- EgtSetMachiningParam(MCH_MP.TABMIN, 4) +-- EgtSetMachiningParam(MCH_MP.TABMAX, 6) +-- EgtSetMachiningParam(MCH_MP.TABDIST, 200) +-- else +-- EgtSetMachiningParam(MCH_MP.TABDIST, 50000) +-- end +---- else +---- EgtSetMachiningParam(MCH_MP.DEPTH_STR, "TH+0.1") +-- end +-- end +-- nOp = EgtGetNextOperation(nOp) +-- end +-- local nRawPart = EgtGetFirstRawPart() +-- local nPart = EgtGetFirstPartInRawPart(nRawPart) +-- while nPart do +-- +-- nPart = EgtGetNextPartInRawPart(nPart) +-- end + EgtApplyAllMachinings() + EgtApplyAllMachinings() + -- genero + local sCncPath = BasePath .. "/CNC" .. BatchDateId .. "/" .. MatId .."/" .. EgtGetMachGroupName(nSheetGroupId) .. ".cnc" + local sPrintPath = BasePath .. "/CNC" .. BatchDateId .. "/" .. MatId .."/" .. EgtGetMachGroupName(nSheetGroupId) .. "_2.cnc" + local sNewPrintPath = BasePath .. "/CNC_PRINT" .. BatchDateId .. "/" .. MatId .."/" .. EgtGetMachGroupName(nSheetGroupId) .. ".cnc" + bOk = EgtGenerate(sCncPath) + -- sposto file di stampa + bOk = EgtCopyFile(sPrintPath, sNewPrintPath) + bOk = EgtEraseFile(sPrintPath) + nSheetGroupId = EgtGetNextMachGroup(nSheetGroupId) + end + EgtSaveFile() + end +end \ No newline at end of file diff --git a/Main.lua b/Main.lua new file mode 100644 index 0000000..7ed421d --- /dev/null +++ b/Main.lua @@ -0,0 +1,1118 @@ +-- +-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT +-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEEEEEEEE GGGGGGGGGG TTTT +-- EEEEEEEEEE GGGGGG TTTT +-- +-- by EgalTech s.r.l. +-- Nesting manager by EgalTech s.r.l. 2020/08/13 + +-- necessary to find socket.core and mime.core +package.cpath = package.cpath .. ";/EgtProg/LuaLibs/?.dll" +package.cpath = package.cpath .. ";/EgtDevTest/LUAREST/32/?.lua" + +require( 'EgtBase') +_ENV = EgtProtectGlobal() +EgtEnableDebug( true) + +-- Imposto direttorio libreria specializzata per Nesting +local sBaseDir = EgtGetSourceDir() +EgtOutLog("BaseDir=" .. sBaseDir) +EgtAddToPackagePath( sBaseDir .. '?.lua') + +local Config = require( 'Config') +local UtilityLib = require( 'UtilityLib') +local RESTLib = require( 'RESTLib') +local NestingLib = require( 'NestingLib') +local socket = require( 'socket') + +------------------------------------------- PARAMETERS ------------------------------------------- +local DebugCode = false +local ProblematicItem = 67328 + +------------------------------------------- ************** ------------------------------------------- + +local function ManageError(ErrorList, readBatch, Send) + if #ErrorList > 0 then + -- creo batch di risposta + local answ = {} + answ.BatchId = readBatch.BatchId + answ.EnvNum = readBatch.EnvNum + answ.ProcType = readBatch.ProcType + answ.MachineType = readBatch.MachineType + answ.OrderType = readBatch.OrderType + answ.ProcessNotes = "" + answ.EstimatedWorktime = 0 + answ.DrawingPath = "" + answ.PartList = {} + answ.CNCPath = "" + answ.SurfaceWork = 0 + answ.SurfaceTotal = 0 + answ.BunkList = {} + answ.CartList = {} + answ.BinList = {} + answ.ErrorList = ErrorList + answ.ProcessStatus = 2 + answ.ProcessingRuntime = EgtStopCounter() / 1000 + -- se doppia macchina + if not Send and Config.bDoubleMach then + return true, answ + end + -- invio dati + local bOk = RESTLib.set(Config.sPathBatch, answ) + if bOk then print("OK") end + return true + end + return false +end +-- + +-- funzione che esegue nesting finale +function Nesting(readBatch) + -- imposto macchina in uso + NestingLib.ManageMachine(false) + + -- elimino tutti i file presenti nella cartella nesting + EgtEmptyDirectory(Config.sBasePath .. "/Nesting" ) + + EgtOutText("Nesting start") + + -- lista errori + local ErrorList = {} + + -- conto tutto + if not readBatch.OrderList then return end + local OrderCount = #readBatch.OrderList + local KitCount = 0 + local PartCount = 0 + local NoDXFCount = 0 + local NoMaterialCount = 0 + local NoMaterialCount2 = 0 + for Order = 1, #readBatch.OrderList do + KitCount = KitCount + #readBatch.OrderList[Order].KitList + for Kit = 1, #readBatch.OrderList[Order].KitList do + PartCount = PartCount + #readBatch.OrderList[Order].KitList[Kit].PartList + end + end + + -- recupero lista materiali + local materials = RESTLib.get(Config.sPathMat) + for MaterialIndex = 1, #materials do + materials[MaterialIndex].PriorityList = {} + end + + -- leggo materiali per tutti i pezzi, metto i verniciati con priorita' 1 sui materiali ed elimino ordini e kit dei verniciati + local OrderList = {} + local CalcReadBatch = RESTLib.get(Config.sPathBatch) + if not CalcReadBatch or CalcReadBatch.BatchId == 0 then + -- error!! + end + + for OrderIndex = 1, #CalcReadBatch.OrderList do + table.insert(OrderList, CalcReadBatch.OrderList[OrderIndex]) + end + NestingLib.FilterPaintedParts(OrderList, materials, ErrorList) + + -- raggruppo gli ordini simili per ottimizzare l'uso del materiale + + -- creo cart + + -- assegno priorita' ai pezzi e li divido sui materiali + + + local Carts = {} -- lista dei cart + -- creo cart a partire da lista ordini e kit +-- NestingLib.CreateCart(readBatch, Carts) + NestingLib.CreateCart(OrderList, Carts) + + local StartCartIndex = 0 + if readBatch.NumIndexStart then + StartCartIndex = readBatch.NumIndexStart + end + for CartIndex = 1, #Carts do + Carts[CartIndex].CartIndex = StartCartIndex + CartIndex - 1 + end + + -- se debug + if DebugCode then + -- verifico di aver messo tutti i kit sui cart + local KitList = {} + -- raccolgo tutti i kit dai cart in una lista + for CartIndex = 1, #Carts do + for OrderIndex = 1, #Carts[CartIndex].OrderList do + for KitIndex = 1, #Carts[CartIndex].OrderList[OrderIndex].KitList do + table.insert(KitList, Carts[CartIndex].OrderList[OrderIndex].KitList[KitIndex]) + end + end + end + -- aggiungo i kit dei painted + for OrderIndex = 1, #OrderList do + for KitIndex = 1, #OrderList[OrderIndex].KitList do + if OrderList[OrderIndex].KitList[KitIndex].IsPaint then + table.insert(KitList, OrderList[OrderIndex].KitList[KitIndex]) + end + end + end + -- passo i kit del readbatch + for OrderIndex = 1, #readBatch.OrderList do + for BKitIndex = 1, #readBatch.OrderList[OrderIndex].KitList do + local bFound = false + for VKitIndex = #KitList, 1, -1 do + if readBatch.OrderList[OrderIndex].KitList[BKitIndex].KitId == KitList[VKitIndex].KitId then + if not bFound then + bFound = true + table.remove(KitList, VKitIndex) + else + table.insert(ErrorList, {ErrType = "E.12", Uid = "KitId = " .. readBatch.OrderList[OrderIndex].KitList[BKitIndex].KitId, Description = "Kit duplicated after putting them on cart!"}) + end + end + end + if not bFound then + table.insert(ErrorList, {ErrType = "E.12", Uid = "KitId = " .. readBatch.OrderList[OrderIndex].KitList[BKitIndex].KitId, Description = "Kit lost after putting them on cart!"}) + end + end + end + -- verifico se sono rimasti elementi nella tabella kit + if #KitList > 0 then + table.insert(ErrorList, {ErrType = "E.12", Uid = "KitId = " .. KitList[1].KitId, Description = #KitList .. " kit more than in batch request after putting kit on cart!"}) + end + end + + -- imposto priorità sui pezzi in base ai carrelli e li divido per materiale e priorità + NestingLib.SetPriorityProcessMaterial(Carts, materials, ErrorList) + + -- se debug + if DebugCode then + -- verifico di aver messo tutti i part su un materiale + local PartList = {} + -- raccolgo tutti i part dai materiali in una lista + for MaterialIndex = 1, #materials do + for PriorityIndex = 1, #materials[MaterialIndex].PriorityList do + for PartIndex = 1, #materials[MaterialIndex].PriorityList[PriorityIndex].PartList do + table.insert(PartList, materials[MaterialIndex].PriorityList[PriorityIndex].PartList[PartIndex]) + end + end + end + -- passo i part del readbatch + for OrderIndex = 1, #readBatch.OrderList do + for KitIndex = 1, #readBatch.OrderList[OrderIndex].KitList do + for BPartIndex = 1, #readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList do + local bFound = false + for VPartIndex = #PartList, 1, -1 do + if readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList[BPartIndex].PartId == PartList[VPartIndex].PartId then + if not bFound then + bFound = true + table.remove(PartList, VPartIndex) + else + table.insert(ErrorList, {ErrType = "E.12", Uid = "PartId = " .. readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList[BPartIndex].PartId, Description = "Part duplicated after distributing them on materials!"}) + end + end + end + if not bFound then + table.insert(ErrorList, {ErrType = "E.12", Uid = "PartId = " .. readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList[BPartIndex].PartId, Description = "Part lost after distributing them on materials!"}) + end + end + end + end + -- verifico se sono rimasti elementi nella tabella kit + if #PartList > 0 then + table.insert(ErrorList, {ErrType = "E.12", Uid = "PartId = " .. PartList[1].PartId, Description = #PartList .. " part more than in batch request after distributing them on materials!"}) + end + end + + -- creo bin necessari + local Bins = {} + NestingLib.CreateBin(materials, Bins) + + -- se debug + if DebugCode then + -- verifico di aver messo tutti i painted part su un bin + + end + + PartCount1 = 0 + local MatIde = 21 +-- local MatIndex = MatIde + 1 +-- local MatCount = MatIndex + local MatIndex = 1 + local MatCount = #materials + --for Material = 1, #materials do + for Material = MatIndex, MatCount do + --for Material = 2, 2 do + for Priority = 1, #materials[Material].PriorityList do + for Part = 1, #materials[Material].PriorityList[Priority].PartList do + PartCount1 = PartCount1 + 1 + if materials[Material].PriorityList[Priority].PartList[Part].PartId == ProblematicItem then + local x = 2 + end + end + end + end + + -- contatore dei pezzi ricevuti per errori sul numero finale dei pezzi + --local VPartList = {} + --for Priority = 1, #materials[11].PartList do + -- for Part = 1, #materials[11].PartList[Priority].PartList do + -- table.insert(VPartList, materials[11].PartList[Priority].PartList[Part].PartId) + -- end + --end + function comparePriority(a,b) + return a.Priority < b.Priority + end + -- per ogni materiale riordino le priorita' + local SortingArray = {} + for MaterialIndex = 1, #materials do + table.sort(materials[MaterialIndex].PriorityList, comparePriority) + end + + -- per ogni materiale creo un progetto + local PARTID = "PartId" + local PRIORITY = "Priority" + local ROUGHER = {".375 ROUGHER","ROUGHER"} + local DTMXPOS = "DATA MATRIX CODE POSITION" + local MatSheetList = {} + --for Material = 1, #materials do + for Material = MatIndex, MatCount do + --for Material = 2, 2 do + --for Material = 4, 4 do + -- se è il materiale nullo salto al prossimo + if materials[Material].MatId ~= 0 and #materials[Material].PriorityList > 0 then + EgtOutText("Material: " .. materials[Material].MatDesc) + EgtNewFile() + materials[Material].SheetList = {} + local LastRawId = GDB_ID.NULL + -- recupero lista verniciati (priorità 1) + local PartToBeMachined = {} + -- verifico se c'è lista pezzi verniciati +-- if materials[Material].PartList[1].Priority == 1 then +---- PartToBeMachined = materials[Material].PartList[1].PartList +-- PartToBeMachined = {} +-- for Part = 1, #materials[Material].PartList[1].PartList do +-- table.insert(PartToBeMachined, materials[Material].PartList[1].PartList[Part]) +-- end +-- -- chiamo il nesting sui verniciati +-- LastRawId = NestingLib.NestPartInRawPart(nil, PartToBeMachined, materials[Material], ErrorList) +-- -- recupero lista di pezzi di priorità più bassa +-- if #materials[Material].PartList > 1 then +---- PartToBeMachined = materials[Material].PartList[2].PartList +-- PartToBeMachined = {} +-- for Part = 1, #materials[Material].PartList[2].PartList do +-- table.insert(PartToBeMachined, materials[Material].PartList[2].PartList[Part]) +-- end +-- +-- end +-- -- riempio con questi +-- LastRawId = NestingLib.NestPartInRawPart(LastRawId, PartToBeMachined, materials[Material], ErrorList) +-- end + -- for Index = 1, materials[Material].PartList do + -- if materials[Material].PartList[Index].Priority == 1 then + -- PartToBeMachined = materials[Material].PartList[Index].PartList + -- end + -- end + + -- for Index = 1, materials[Material].PartList do + -- if materials[Material].PartList[Index].Priority == 2 then + -- PartToBeMachined = materials[Material].PartList[Index].PartList + -- end + -- end + -- -- riempio con quelli di priorità 2 + -- LastRawId = NestingLib.NestPartInRawPart(LastRawId, PartToBeMachined, materials[Material]) + + -- se il primo gruppo ha priorita' 1, ne aggiungo i pezzi a quelli da nestare + if materials[Material].PriorityList[1].Priority == 1 then + for Part = 1, #materials[Material].PriorityList[1].PartList do + table.insert(PartToBeMachined, materials[Material].PriorityList[1].PartList[Part]) + if materials[Material].PriorityList[1].PartList[Part].PartId == ProblematicItem then + local x = 2 + end + end + end + local Counter = true + local PriorityCount = #materials[Material].PriorityList + -- ciclo sulle priorità dei pezzi + for Index = 1, PriorityCount do + -- verifico che non siano i verniciati + if materials[Material].PriorityList[Index].Priority ~= 1 then + if Counter then + -- annullo LastRaw perche' devo partire con un nuovo grezzo, altrimenti aggiungo pezzi sbagliati (riempimento gia' fatto!) + LastRawId = GDB_ID.NULL + for Part = 1, #materials[Material].PriorityList[Index].PartList do + table.insert(PartToBeMachined, materials[Material].PriorityList[Index].PartList[Part]) + if materials[Material].PriorityList[Index].PartList[Part].PartId == ProblematicItem then + local x = 2 + end + end + -- PartToBeMachined = materials[Material].PartList[Index].PartList + else + PartToBeMachined = {} + for Part = 1, #materials[Material].PriorityList[Index].PartList do + table.insert(PartToBeMachined, materials[Material].PriorityList[Index].PartList[Part]) + if materials[Material].PriorityList[Index].PartList[Part].PartId == ProblematicItem then + local x = 2 + end + end +-- PartToBeMachined = materials[Material].PartList[Index].PartList + end + -- se Counter true faccio il nesting, se false completo grezzo + -- verifico anche che non sia il primo giro in cui dovrei prima riempire i pannelli dei pezzi painted + LastRawId = NestingLib.NestPartInRawPart(LastRawId, PartToBeMachined, materials[Material], ErrorList, false, false) + if ManageError(ErrorList, readBatch) then return end + Counter = not Counter + elseif PriorityCount == 1 then + LastRawId = NestingLib.NestPartInRawPart(GDB_ID.NULL, PartToBeMachined, materials[Material], ErrorList, false, false) + if ManageError(ErrorList, readBatch) then return end + end + -- -- se Counter true faccio il nesting, se false completo grezzo + -- -- verifico anche che non sia il primo giro in cui dovrei prima riempire i pannelli dei pezzi painted + -- if Counter and not materials[Material].PartList[Index].Priority == 2 then -- LastRawId = NestPartInRawPart(LastRawId, PartList, materials[Material]) + -- end + end + + -- se il numero di gruppi delle priorita' e' dispari eseguo un altro nesting sui pezzi rimasti dal riempimento + if materials[Material].PriorityList[1].Priority == 1 then + PriorityCount = PriorityCount - 1 + end + if PriorityCount % 2 == 0 then + -- annullo LastRaw perche' devo partire con un nuovo grezzo, altrimenti aggiungo pezzi sbagliati (riempimento gia' fatto!) + LastRawId = GDB_ID.NULL + LastRawId = NestingLib.NestPartInRawPart(LastRawId, PartToBeMachined, materials[Material], ErrorList, false, false) + if ManageError(ErrorList, readBatch) then return end + end + + -- calcolo lavorazioni, stime, ecc + NestingLib.PostNestOp(materials[Material], ErrorList, false, readBatch.BatchId, 1) + NestingLib.PostNestOp(materials[Material], ErrorList, false, readBatch.BatchId, 2) + if ManageError(ErrorList, readBatch) then return end + + -- salvo il progetto di nesting + local sProjectPath = NestingLib.VerifyPath("Nesting", readBatch.BatchId, nil) + EgtSaveFile(sProjectPath .. "/" .. materials[Material].MatId .. ".nge") + end + end + + EgtOutText("End sheets nest") + + -- se debug + if DebugCode then + -- verifico di aver messo tutti i part su un grezzo + local PartList = {} + -- raccolgo tutti i part dai materiali in una lista + for MaterialIndex = 1, #materials do + if materials[MaterialIndex].SheetList then + for SheetIndex = 1, #materials[MaterialIndex].SheetList do + for PartIndex = 1, #materials[MaterialIndex].SheetList[SheetIndex].PartList do + table.insert(PartList, tonumber(materials[MaterialIndex].SheetList[SheetIndex].PartList[PartIndex].PartId)) + end + end + end + end + -- passo i part del readbatch + for OrderIndex = 1, #readBatch.OrderList do + for KitIndex = 1, #readBatch.OrderList[OrderIndex].KitList do + for BPartIndex = 1, #readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList do + local bFound = false + for VPartIndex = #PartList, 1, -1 do + if readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList[BPartIndex].PartId == PartList[VPartIndex] then + if not bFound then + bFound = true + table.remove(PartList, VPartIndex) + else + table.insert(ErrorList, {ErrType = "E.12", Uid = "PartId = " .. readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList[BPartIndex].PartId, Description = "Part duplicated after nesting!"}) + end + end + end + if not bFound then + table.insert(ErrorList, {ErrType = "E.12", Uid = "PartId = " .. readBatch.OrderList[OrderIndex].KitList[KitIndex].PartList[BPartIndex].PartId, Description = "Part lost after nesting!"}) + end + end + end + end + -- verifico se sono rimasti elementi nella tabella kit + if #PartList > 0 then + table.insert(ErrorList, {ErrType = "E.12", Uid = "PartId = " .. PartList[1], Description = #PartList .. " part more than in batch request after nesting!"}) + end + end + + local MPCount = 0 + -- ordino fogli da mettere sui bunk + local SheetList = {} + for Material = 1, #materials do + if materials[Material].SheetList and #materials[Material].SheetList > 0 then + for Sheet = 1, #materials[Material].SheetList do + -- segno dimensioni materiale sul foglio + materials[Material].SheetList[Sheet].L_mm = materials[Material].L_mm + materials[Material].SheetList[Sheet].W_mm = materials[Material].W_mm + materials[Material].SheetList[Sheet].T_mm = materials[Material].T_mm + -- elimino priorita' 1 + for PriorityIndex = 1, #materials[Material].SheetList[Sheet].PriorityList do + if tonumber(materials[Material].SheetList[Sheet].PriorityList[PriorityIndex]) == 1 then + table.remove(materials[Material].SheetList[Sheet].PriorityList, PriorityIndex) + if #materials[Material].SheetList[Sheet].PriorityList == 0 then + table.insert(materials[Material].SheetList[Sheet].PriorityList, "2") + end + end + end + -- verifico conto pezzi + for Part = 1, #materials[Material].SheetList[Sheet].PartList do + if materials[Material].SheetList[Sheet].PartList[Part].PartId == tostring(ProblematicItem) then + local x = 2 + end + MPCount = MPCount + 1 + end + -- se lista ordinata non vuota + if #SheetList > 0 then + local bInserted = false + -- scorro le priorita' + for SearchIndex = 1, #SheetList do + local bNotToBeInserted = false + local MaxList = math.min(#SheetList[SearchIndex].PriorityList, #materials[Material].SheetList[Sheet].PriorityList) + for PriorityIndex = 1, MaxList do + if not bInserted and not bNotToBeInserted and + ((tonumber(SheetList[SearchIndex].PriorityList[PriorityIndex]) > tonumber(materials[Material].SheetList[Sheet].PriorityList[PriorityIndex])) or + (tonumber(SheetList[SearchIndex].PriorityList[PriorityIndex]) == tonumber(materials[Material].SheetList[Sheet].PriorityList[PriorityIndex]) and + PriorityIndex == MaxList and #SheetList[SearchIndex].PriorityList > #materials[Material].SheetList[Sheet].PriorityList)) then + table.insert(SheetList, SearchIndex, materials[Material].SheetList[Sheet]) + bInserted = true + elseif + (tonumber(SheetList[SearchIndex].PriorityList[PriorityIndex]) < tonumber(materials[Material].SheetList[Sheet].PriorityList[PriorityIndex])) then + bNotToBeInserted = true +-- elseif ((SheetList[SearchIndex].PriorityList[PriorityIndex] == materials[Material].SheetList[Sheet].PriorityList[PriorityIndex]) +-- and PriorityIndex == MaxList) then +-- if #SheetList[SearchIndex].PriorityList > #materials[Material].SheetList[Sheet].PriorityList then +-- table.insert(SheetList, PriorityIndex, materials[Material].SheetList[Sheet]) +-- else +-- table.insert(SheetList, PriorityIndex + 1, materials[Material].SheetList[Sheet]) +-- end + end + end + end + if not bInserted then + table.insert(SheetList, materials[Material].SheetList[Sheet]) + end + else + table.insert(SheetList, materials[Material].SheetList[Sheet]) + end + end + end + end + + -- BUNK CREATI PER PRIORITA' E ALTEZZA MASSIMA + -- creo bunk prendendo X fogli con priorita' piu' bassa + local SheetXBunk = 10 + local BunkList = {} + local BunkIndex = 1 + local CurrBunk = {BunkIndex = BunkIndex, SheetList = {}} + table.insert(BunkList, CurrBunk) + local CurrSheetOnBunk = 0 + local CurrBunkPriority = 2 + local CurrBunkThickness = 0 + for Sheet = 1, #SheetList do +-- if tonumber(SheetList[Sheet].PriorityList[1]) == 1 or tonumber(SheetList[Sheet].PriorityList[#SheetList[Sheet].PriorityList]) <= CurrBunkPriority + 1 then + if tonumber(SheetList[Sheet].PriorityList[#SheetList[Sheet].PriorityList]) <= CurrBunkPriority + 1 and CurrBunkThickness + SheetList[Sheet].T_mm < Config.MaxBunkThickness then + SheetList[Sheet].SheetIndex = CurrSheetOnBunk + 1 + table.insert(CurrBunk.SheetList, SheetList[Sheet]) + CurrSheetOnBunk = CurrSheetOnBunk + 1 + CurrBunkThickness = CurrBunkThickness + SheetList[Sheet].T_mm + else + BunkIndex = BunkIndex + 1 + SheetList[Sheet].SheetIndex = 1 + CurrBunk = {BunkIndex = BunkIndex, SheetList = {}} + table.insert(CurrBunk.SheetList, SheetList[Sheet]) + table.insert(BunkList, CurrBunk) + CurrSheetOnBunk = 1 + local nSheetFirstPriority = tonumber(SheetList[Sheet].PriorityList[1]) + for i = 2, #(SheetList[Sheet].PriorityList) do + nSheetFirstPriority = min(nSheetFirstPriority, tonumber(SheetList[Sheet].PriorityList[i])) + end + CurrBunkPriority = EgtIf( nSheetFirstPriority == 2, nSheetFirstPriority, nSheetFirstPriority + 1) + CurrBunkThickness = 0 + end + end + + -- BUNK CREATI CON SPESSORE MASSIMO +-- -- creo bunk prendendo X fogli con priorita' piu' bassa +-- local MaxBunkThickness = 500 +-- local BunkList = {} +-- local BunkIndex = 1 +-- local CurrBunk = {BunkIndex = BunkIndex, SheetList = {}} +-- table.insert(BunkList, CurrBunk) +-- local CurrBunkThickness = 0 +-- local CurrSheetOnBunk = 0 +-- for Sheet = 1, #SheetList do +-- if CurrBunkThickness < Config.MaxBunkThickness then +-- SheetList[Sheet].SheetIndex = CurrSheetOnBunk + 1 +-- table.insert(CurrBunk.SheetList, SheetList[Sheet]) +-- CurrSheetOnBunk = CurrSheetOnBunk + 1 +-- CurrBunkThickness = CurrBunkThickness + SheetList[Sheet].T_mm +-- else +-- BunkIndex = BunkIndex + 1 +-- SheetList[Sheet].SheetIndex = 1 +-- CurrBunk = {BunkIndex = BunkIndex, SheetList = {}} +-- table.insert(CurrBunk.SheetList, SheetList[Sheet]) +-- table.insert(BunkList, CurrBunk) +-- CurrSheetOnBunk = 1 +-- CurrBunkThickness = SheetList[Sheet].T_mm +-- end +-- end + + -- BUNK CREATI CON NUMERO MASSIMO DI FOGLI +-- -- creo bunk prendendo X fogli con priorita' piu' bassa +-- local SheetXBunk = 10 +-- local BunkList = {} +-- local BunkIndex = 1 +-- local CurrBunk = {BunkIndex = BunkIndex, SheetList = {}} +-- table.insert(BunkList, CurrBunk) +-- local CurrSheetOnBunk = 0 +-- for Sheet = 1, #SheetList do +-- if CurrSheetOnBunk < SheetXBunk then +-- SheetList[Sheet].SheetIndex = CurrSheetOnBunk + 1 +-- table.insert(CurrBunk.SheetList, SheetList[Sheet]) +-- CurrSheetOnBunk = CurrSheetOnBunk + 1 +-- else +-- BunkIndex = BunkIndex + 1 +-- SheetList[Sheet].SheetIndex = 1 +-- CurrBunk = {BunkIndex = BunkIndex, SheetList = {}} +-- table.insert(CurrBunk.SheetList, SheetList[Sheet]) +-- table.insert(BunkList, CurrBunk) +-- CurrSheetOnBunk = 1 +-- end +-- end + + -- Ordino fogli sui singoli BUNK per dimensione + for BunkIndex = 1, #BunkList do + local OrderedSheets = {} + -- divido i fogli in gruppi della stessa lunghezza + for SheetIndex = 1, #BunkList[BunkIndex].SheetList do + if #OrderedSheets > 0 then + local bInserted = false + for OrderedSheetIndex = 1, #OrderedSheets do + if BunkList[BunkIndex].SheetList[SheetIndex].L_mm == OrderedSheets[OrderedSheetIndex].L_mm then + bInserted = true + table.insert(OrderedSheets[OrderedSheetIndex].SheetList, BunkList[BunkIndex].SheetList[SheetIndex]) + end + end + if not bInserted then + table.insert(OrderedSheets, {L_mm = BunkList[BunkIndex].SheetList[SheetIndex].L_mm, SheetList = {BunkList[BunkIndex].SheetList[SheetIndex]}}) + end + else + table.insert(OrderedSheets, {L_mm = BunkList[BunkIndex].SheetList[SheetIndex].L_mm, SheetList = {BunkList[BunkIndex].SheetList[SheetIndex]}}) + end + end + -- ordino i gruppi di pari lunghezza + function compareLenght(a,b) + return a.L_mm < b.L_mm + end + -- per ogni materiale riordino le priorita' +-- for SheetIndex = 1, #OrderedSheets do + table.sort(OrderedSheets, compareLenght) + -- ordino i fogli per materiale all'interno dei gruppi + function compareMaterial(a,b) + return a.MatId < b.MatId + end + for OrderedIndex = 1, #OrderedSheets do + table.sort(OrderedSheets[OrderedIndex].SheetList, compareMaterial) + end +-- end + -- rimetto in lista tutti gli sheet come ordinati + BunkList[BunkIndex].SheetList = {} + local Index = 1 + for OrderedSheetIndex = 1, #OrderedSheets do + for SheetIndex = 1, #OrderedSheets[OrderedSheetIndex].SheetList do + OrderedSheets[OrderedSheetIndex].SheetList[SheetIndex].SheetIndex = Index + table.insert(BunkList[BunkIndex].SheetList, OrderedSheets[OrderedSheetIndex].SheetList[SheetIndex]) + Index = Index + 1 + end + end + end + + -- segno info con contenuto etichetta fogli +-- local SHEETLABEL = "SheetLabel" +-- for Material = 1, #materials do +-- if EgtOpenFile(Config.sBasePath .. "/Nesting/" .. materials[Material].MatId .. ".nge") then +-- local nMachGroupId = EgtGetFirstMachGroup() +-- while nMachGroupId do +-- local bOk = EgtSetCurrMachGroup(nMachGroupId) +-- local sMachGroupName = EgtGetMachGroupName(nMachGroupId) +-- for BunkIndex = 1, #BunkList do +-- for SheetIndex = 1, #BunkList[BunkIndex].SheetList do +-- if BunkList[BunkIndex].SheetList[SheetIndex].MatId == materials[Material].MatId and BunkList[BunkIndex].SheetList[SheetIndex].MachGroupName == sMachGroupName then +-- local nRaw = EgtGetFirstRawPart() +-- local nSheetLabel = EgtGetFirstNameInGroup(nRaw, SHEETLABEL) +-- local bOk = EgtSetInfo(nSheetLabel, SHEETLABEL, BunkIndex .. "." .. SheetIndex) +-- end +-- end +-- end +-- nMachGroupId = EgtGetNextMachGroup(nMachGroupId) +-- end +-- EgtSaveFile() +-- end +-- end + + -- se debug + if DebugCode then + -- verifico di aver messo tutti gli sheet sui bunk + local SheetList = {} + -- raccolgo tutti gli sheet dai bunk in una lista + for BunkIndex = 1, #BunkList do + for SheetIndex = 1, #BunkList[BunkIndex].SheetList do + table.insert(SheetList, BunkList[BunkIndex].SheetList[SheetIndex]) + end + end + -- passo gli sheet dei material + for MaterialIndex = 1, #materials do + if materials[MaterialIndex].SheetList then + for BSheetIndex = 1, #materials[MaterialIndex].SheetList do + local bFound = false + for VSheetIndex = 1, #SheetList do + if materials[MaterialIndex].SheetList[BSheetIndex] == SheetList[VSheetIndex] then + bFound = true + table.remove(SheetList, VSheetIndex) + end + end + if not bFound then + table.insert(ErrorList, {ErrType = "E.12", Uid = "SheetId = " ..materials[MaterialIndex].MaterialId .." - " .. materials[MaterialIndex].SheetList[BSheetIndex].SheetIndex, + Description = "Sheet lost after distribution on bunks!"}) + end + end + end + end + -- verifico se sono rimasti elementi nella tabella kit + if #SheetList > 0 then + table.insert(ErrorList, {ErrType = "E.12", Uid = "SheetId = " .. SheetList[1].SheetIndex, Description = #PartList .. " sheet more than in materials after distribution on bunks!"}) + end + end + + local MPCount2 = 0 + local TotThickness = 0 + for CurrBunk = 1, #BunkList do + for CurrSheet = 1, #BunkList[CurrBunk].SheetList do + TotThickness = TotThickness + BunkList[CurrBunk].SheetList[CurrSheet].T_mm + MPCount2 = MPCount2 + 1 + end + end + + -- verifica assenza pezzi tra ricevuti e messi sui fogli + --local SVPartList = {} + --for Sheet = 1, #materials[11].SheetList do + -- for Part = 1, #materials[11].SheetList[Sheet].PartList do + -- table.insert(SVPartList, materials[11].SheetList[Sheet].PartList[Part].PartId) + -- end + --end + --table.sort(VPartList) + --table.sort(SVPartList) + --local ListCount = #VPartList + --local List1 = VPartList + --local List2 = SVPartList + --local Only1 = {} + --local Only2 = {} + --if #SVPartList > #VPartList then + -- ListCount = #SVPartList + -- List1 = SVPartList + -- List2 = VPartList + --end + --local Index1, Index2 = 1, 1 + --while Index1 <= #List1 do + -- if Index2 <= #List2 then + -- if List1[Index1] > tonumber(List2[Index2]) then + -- table.insert(Only2, List2[Index2]) + -- Index2 = Index2 + 1 + -- elseif List1[Index1] < tonumber(List2[Index2]) then + -- table.insert(Only1, List2[Index2]) + -- Index1 = Index1 + 1 + -- Index2 = Index2 + 1 + -- end + -- else + -- table.insert(Only1, List2[Index2]) + -- Index1 = Index1 + 1 + -- end + --end + + + -- creo batch di risposta + local answ = {} + answ.BatchId = readBatch.BatchId + answ.EnvNum = readBatch.EnvNum + answ.ProcType = readBatch.ProcType + answ.MachineType = readBatch.MachineType + answ.OrderType = readBatch.OrderType + answ.ProcessNotes = "" + + -- sommo tempo totale di lavorazione e superficie materiale utilizzata + local TotTime = 0 + local SurfaceWork = 0 + local SurfaceTotal = 0 + + local ChangeSheetTime = 100 + for Material = 1, #materials do + if materials[Material] and materials[Material].SheetList and #materials[Material].SheetList > 0 then + for Sheet = 1, #materials[Material].SheetList do + TotTime = TotTime + materials[Material].SheetList[Sheet].EstimatedWorktime + ChangeSheetTime + SurfaceWork = SurfaceWork + materials[Material].SheetList[Sheet].SurfaceWork + SurfaceTotal = SurfaceTotal + materials[Material].SheetList[Sheet].SurfaceTotal + end + end + end + answ.EstimatedWorktime = TotTime + answ.SurfaceWork = SurfaceWork + answ.SurfaceTotal = SurfaceTotal + + -- aggiungo i bunk alla risposta + answ.BunkList = BunkList + + -- aggiungo carrelli con kit alla risposta eliminando gli ordini +-- local StartCartIndex = 0 +-- if readBatch.NumIndexStart then +-- StartCartIndex = readBatch.NumIndexStart +-- end + for CartIndex = 1, #Carts do + Carts[CartIndex].KitList = {} +-- Carts[CartIndex].CartIndex = StartCartIndex + CartIndex - 1 + for OrderIndex = 1, #Carts[CartIndex].OrderList do + for KitIndex = 1, #Carts[CartIndex].OrderList[OrderIndex].KitList do + table.insert(Carts[CartIndex].KitList, Carts[CartIndex].OrderList[OrderIndex].KitList[KitIndex]) + end + end + end + answ.CartList = Carts + + -- aggiungo bins alla risposta + answ.BinList = Bins + + -- attacco lista errori e tempo di computazione + answ.ErrorList = ErrorList + if #ErrorList == 0 then + answ.ProcessStatus = 3 + else + answ.ProcessStatus = 2 + end + answ.ProcessingRuntime = EgtStopCounter() / 1000 + + -- invio dati + local bOk = RESTLib.set(Config.sPathBatch, answ) + if bOk then print("OK") end + + EgtOutText("Nesting end") + +end +-- + +-- funzione che esegue calcolo stima tempi +function Estimate(readBatch) + + -- calcolo lavorazioni, stime, ecc + local IsOffLine = false + if readBatch.OrderType == 1 then + IsOffLine = true + end + + -- imposto macchina in uso + NestingLib.ManageMachine(IsOffLine) + + EgtOutText("Estimate start") + + -- lista errori + local ErrorList = {} + + -- conto tutto + local OrderCount = #readBatch.OrderList + local KitCount = 0 + local PartCount = 0 + local NoDXFCount = 0 + local NoMaterialCount = 0 + local NoMaterialCount2 = 0 + for Order = 1, #readBatch.OrderList do + KitCount = KitCount + #readBatch.OrderList[Order].KitList + for Kit = 1, #readBatch.OrderList[Order].KitList do + PartCount = PartCount + #readBatch.OrderList[Order].KitList[Kit].PartList + end + end + + -- recupero lista materiali + local materials = RESTLib.get(Config.sPathMat) + + -- aggiungo liste pezzi + for Material = 1, #materials do + if not materials[Material].PartList then materials[Material].PartList = {} end + end + + -- divido pezzi per materiale + local CurrOrderIndex = 1 + local CurrOrderCount = #readBatch.OrderList + if Config.bDoubleMach then + CurrOrderIndex = readBatch.CurrOrderIndex + CurrOrderCount = readBatch.CurrOrderIndex + end + for Order = CurrOrderIndex, CurrOrderCount do + OrderCount = OrderCount + 1 + for Kit = 1, #readBatch.OrderList[Order].KitList do + KitCount = KitCount + 1 + for Part = 1, #readBatch.OrderList[Order].KitList[Kit].PartList do + PartCount = PartCount + 1 + local TempPart = readBatch.OrderList[Order].KitList[Kit].PartList[Part] + -- leggo le proprietà dal dxf e le imposto + local MatExtCode, PdfLink, Paint, OptParameters, ErrorType = UtilityLib.readDXF(TempPart.CadFilePath, TempPart.PartExtCode, true) + -- solo se trovo il materiale vado avanti per questo pezzo + if ErrorType == 0 and MatExtCode then + TempPart.MatExtCode = MatExtCode + TempPart.OptParameters = OptParameters + TempPart.OptParameters.PdfLink = PdfLink + local PaintVal = "NO" + if Paint then + PaintVal = "YES" + end + TempPart.OptParameters.PaintFlag = PaintVal + -- suddivido i pezzi per materiale + for Material = 1, #materials do + if TempPart.MatExtCode == materials[Material].MatExtCode then + TempPart.MatId = materials[Material].MatId + -- aggiungo il pezzo all'interno del materiale + table.insert(materials[Material].PartList, TempPart) + end + end + elseif ErrorType == 1 then + table.insert(ErrorList, {ErrType = "E.1", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find DXF file"}) + EgtOutLog("Part skipped: " .. TempPart.PartId) + elseif ErrorType == 2 then + table.insert(ErrorList, {ErrType = "E.2", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find material tag in DXF"}) + EgtOutLog("Part skipped: " .. TempPart.PartId) + else + table.insert(ErrorList, {ErrType = "E.6", Uid = "PartId = " .. TempPart.PartId, Description = "Error in DXF reading"}) + EgtOutLog("Part skipped: " .. TempPart.PartId) + end + end + end + end + + PartCount1 = 0 + local MatIde = 10 +-- local MatIndex = MatIde + 1 +-- local MatCount = MatIndex + local MatIndex = 1 + local MatCount = #materials + + -- per ogni materiale creo un progetto + local PARTID = "PartId" + local PRIORITY = "Priority" + local ROUGHER = {".375 ROUGHER","ROUGHER"} + local DTMXPOS = "DATA MATRIX CODE POSITION" + local MatSheetList = {} + --for Material = 1, #materials do + for Material = MatIndex, MatCount do + -- se è il materiale nullo salto al prossimo + if materials[Material].MatId ~= 0 and #materials[Material].PartList > 0 then + EgtOutText("Material: " .. materials[Material].MatDesc) + EgtNewFile() + materials[Material].SheetList = {} + local PartToBeMachined = {} + for Part = 1, #materials[Material].PartList do + table.insert(PartToBeMachined, materials[Material].PartList[Part]) + end + local IsValidation = false + if readBatch.MaxTime == 1 then + IsValidation = true + end + NestingLib.NestPartInRawPart(nil, PartToBeMachined, materials[Material], ErrorList, true, IsValidation) + local bOk, answ = ManageError(ErrorList, readBatch) + -- se doppia macchina + if bOk then + if Config.bDoubleMach then + return answ + else + return + end + end + + NestingLib.PostNestOp(materials[Material], ErrorList, true, readBatch.BatchId) + bOk, answ = ManageError(ErrorList, readBatch) + -- se doppia macchina + if bOk then + if Config.bDoubleMach then + return answ + else + return + end + end + +-- -- salvo il progetto di nesting +-- EgtSaveFile(Config.sBasePath .. "/Estimate/" .. materials[Material].MatId .. ".nge") + -- salvo il progetto di nesting + local sProjectPath = NestingLib.VerifyPath("Estimate", readBatch.BatchId, nil) + EgtSaveFile(sProjectPath .. "/" .. materials[Material].MatId .. ".nge") + end + end + + EgtOutText("End sheets estimate") + + + -- creo batch di risposta + local answ = {} + answ.BatchId = readBatch.BatchId + answ.EnvNum = readBatch.EnvNum + answ.ProcType = readBatch.ProcType + answ.MachineType = readBatch.MachineType + answ.OrderType = readBatch.OrderType + answ.ProcessNotes = "" + + -- sommo tempo totale di lavorazione + local TotTime = 0 + local ChangeSheetTime = 100 + for Material = 1, #materials do + if materials[Material] and materials[Material].SheetList and #materials[Material].SheetList > 0 then + for Sheet = 1, #materials[Material].SheetList do + TotTime = TotTime + materials[Material].SheetList[Sheet].EstimatedWorktime + ChangeSheetTime + end + end + end + answ.EstimatedWorktime = TotTime + (TotTime * 0.1) -- aggiungo 10% di sicurezza + + if readBatch.OrderType == 1 then + answ.DrawingPath = NestingLib.VerifyPath("SVG", readBatch.BatchId, nil) .. "/" + answ.CNCPath = NestingLib.VerifyPath("CNC", readBatch.BatchId, nil) .. "/" + end + + -- recupero pezzi analizzati + answ.PartList = {} + for Material = MatIndex, MatCount do + if materials[Material].PartList and #materials[Material].PartList > 0 then + for Part = 1, #materials[Material].PartList do + table.insert(answ.PartList, materials[Material].PartList[Part]) + end + end + end + + -- attacco lista errori e tempo di computazione + answ.ErrorList = ErrorList + if #ErrorList == 0 then + answ.ProcessStatus = 3 + else + answ.ProcessStatus = 2 + end + answ.ProcessingRuntime = EgtStopCounter() / 1000 + + -- se doppia macchina + if Config.bDoubleMach then + return answ + end + + -- invio dati + local bOk = RESTLib.set(Config.sPathBatch, answ) + if bOk then print("OK") end + + EgtOutText("Estimate end") + +end +-- + +-- funzione che esegue calcolo stima tempi +function ExtendedEstimate(readBatch) + -- creo batch di risposta + local answ = {} + answ.BatchId = readBatch.BatchId + answ.EnvNum = readBatch.EnvNum + answ.ProcType = readBatch.ProcType + answ.MachineType = readBatch.MachineType + answ.OrderType = readBatch.OrderType + answ.ProcessNotes = "" + + -- lista errori + local ErrorList = {} + -- tempo totale stimato + local TotTime = 0 + + answ.EstOrderList = {} + answ.PartList = {} + -- chiamo stima per ogni materiale + for Order = 1, #readBatch.OrderList do + readBatch.CurrOrderIndex = Order + local estm = Estimate(readBatch) + -- aggiungo pezzi a lista pezzi del risultato + if #estm.ErrorList == 0 then + for PartIndex = 1, #estm.PartList do + table.insert(answ.PartList, estm.PartList[PartIndex]) + end + end + -- accodo errori dell'ordine + for ErrorIndex = 1, #estm.ErrorList do + table.insert(ErrorList, estm.ErrorList[ErrorIndex]) + end + if ManageError(ErrorList, readBatch, true) then return end + -- recupero lista materiali + local materials = RESTLib.get(Config.sPathMat) + for MaterialIndex = 1, #materials do + materials[MaterialIndex].PriorityList = {} + end + local OrderList = {} + local Carts = {} + table.insert( OrderList, readBatch.OrderList[Order]) + -- calcolo numero carrelli + NestingLib.FilterPaintedParts(OrderList, materials, ErrorList) + NestingLib.CreateCart(OrderList, Carts) + -- imposto priorità sui pezzi in base ai carrelli e li divido per materiale e priorità + NestingLib.SetPriorityProcessMaterial(Carts, materials, ErrorList) + -- creo bin necessari + local Bins = {} + NestingLib.CreateBin(materials, Bins) + -- riporto numero pezzi, carrelli e stima tempo taglio nell'ordine + readBatch.OrderList[Order].NumCart = #Carts + readBatch.OrderList[Order].NumBin = #Bins + readBatch.OrderList[Order].NumPart = #estm.PartList + readBatch.OrderList[Order].TotTime = estm.EstimatedWorktime + TotTime = TotTime + estm.EstimatedWorktime + -- aggiungo ordine a lista ordini del risultato + table.insert(answ.EstOrderList, readBatch.OrderList[Order]) + end + + -- correggo e riporto tempo totale di lavorazione + answ.EstimatedWorktime = TotTime + + -- attacco lista errori e tempo di computazione + answ.ErrorList = ErrorList + if #ErrorList == 0 then + answ.ProcessStatus = 3 + else + answ.ProcessStatus = 2 + end + answ.ProcessingRuntime = EgtStopCounter() / 1000 + + -- invio dati + local bOk = RESTLib.set(Config.sPathBatch, answ) + if bOk then print("OK") end + + EgtOutText("ExtendedEstimate end") + +end +-- + +-- ciclo principale +while true do + EgtNewFile() + if EgtProcessEvents( 1, 5) == 1 then + break + else + -- leggo un batch + local readBatch = RESTLib.get(Config.sPathBatch) + if not readBatch or readBatch.BatchId == 0 then --or #readBatch == 0 then + EgtPause(Config.CycleDelay) + -- socket.sleep(0.5) + -- EgtOutLog("Server connection error!") + else + EgtStartCounter() + -- readBatch.OrderType = 1 -> Offline + if readBatch.ProcType == 1 or readBatch.OrderType == 1 then + Estimate(readBatch) + elseif readBatch.ProcType == 3 then + Config.bDoubleMach = true + ExtendedEstimate(readBatch) + else + Nesting(readBatch) + end + end + end + +end diff --git a/NestingLib.lua b/NestingLib.lua new file mode 100644 index 0000000..e5758b0 --- /dev/null +++ b/NestingLib.lua @@ -0,0 +1,2498 @@ +-- +-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT +-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEEEEEEEE GGGGGGGGGG TTTT +-- EEEEEEEEEE GGGGGG TTTT +-- +-- by EgalTech s.r.l. +-- Libreria delle funzioni di nesting by EgalTech s.r.l. 2020/08/13 + +-- Tabella per definizione modulo +local NestingLib = {} + +-- Include +require( 'EgtBase') +local Config = require( 'Config') +local UtilityLib = require( 'UtilityLib') + +------------------------------------------- PARAMETERS ------------------------------------------- +local DebugCode = false +local ProblematicItem = 67328 + +local OrderXCart = 1 -- ordini che si possono mettere su un carrello +local KitXCart = 6 -- kit che si possono mettere su un carrello + +local CartActiveUnload = 4 -- carrelli attivi tra quelli disponibili allo scarico +local TotCartUnload = 6 -- carrelli totali disponibili allo scarico + +-- distanza tra i rulli pressori +local MXRollerDist = 400 +local NWRollerDist = 300 + +-- dati skin +local dSkinThickness = 1 +-- ordinare lavorazioni per tipo o pezzo +local nMachOrderType = 3 -- 1 = per tipologia lavorazione ; 2 = per pezzo ; 3 = per tipologia ordinando pezzi + +-- dimensione codici QR su second screen +local nQRDim = 50 +-- path generatore codici QR +local sQRCodeGenPath = "https://qrcode.steamware.net/HOME" + +------------------------------------------- ************** ------------------------------------------- + +-- liste lavorazioni +local OutlineMachining = {} --{{".375 ROUGHER", "ROUGHER"}, {'3/8 MILLING', '1/4 MILLING'}} +local HoleMachining = {} --{"HOLE", {'3/16 DRILLING', '1/4 DRILLING', '1/2 DRILLING', '1/8 DRILLING', '11/32 DRILLING', '13/32 DRILLING', + -- '3/8 DRILLING', '5/16 DRILLING', '7/16 DRILLING', '17/32 DRILLING', '37/64 DRILLING'}} +local RampMachining = {} -- {"RAMP", '3/8 MILLING'} --, '1/4 MILLING'}} +local Pocketing = {} -- {'3/8 POCKETING', '1/4 POCKETING'} +local sCurrMachName = "" +local IsOffline = false + +-- liste lavorazioni divise per tipo ed utensile per ottimizzazione algoritmo tsp +local OutlineList = {} +local SmallOutlineList = {} +local IntIntOutlineList = {} +local SkinOutlineList = {} +local IntExtOutlineList = {} +local InternalOutlineList = {} +local PocketingList = {} +local RampList = {} +local HoleList = {} + +-- funzione che legge i dxf con le proprieta' dei pezzi +function NestingLib.FilterPaintedParts(OrderList, materials, ErrorList) + local DeleteOrder = {} + for Order = 1, #OrderList do + OrderList[Order].IsPaint = true + local DeleteKit = {} + for Kit = 1, #OrderList[Order].KitList do + OrderList[Order].KitList[Kit].IsPaint = true + for Part = 1, #OrderList[Order].KitList[Kit].PartList do + local TempPart = OrderList[Order].KitList[Kit].PartList[Part] + -- leggo le proprietà dal dxf e le imposto + local MatExtCode, PdfLink, Paint, OptParameters, ErrorType, Revision = UtilityLib.readDXF(TempPart.CadFilePath, TempPart.PartExtCode, false) + -- solo se trovo il materiale vado avanti per questo pezzo + if ErrorType == 0 and MatExtCode then + TempPart.MatExtCode = MatExtCode + TempPart.OptParameters = OptParameters + TempPart.OptParameters.PdfLink = PdfLink + TempPart.PartRev = Revision + local PaintVal = "NO" + if Paint then + PaintVal = "YES" + end + TempPart.OptParameters.PaintFlag = PaintVal + -- se pezzo pitturato + if Paint then + PaintVal = "YES" + -- cerco il suo materiale + for Material = 1, #materials do + if TempPart.MatExtCode == materials[Material].MatExtCode then + TempPart.MatId = materials[Material].MatId + -- gli do' priorita' 1 perchè i pitturati devono essere fatti per primi + TempPart.Priority = 1 + -- se non esiste gia' lista priorita' + if #materials[Material].PriorityList == 0 then + -- la creo e gli aggiungo il pezzo + materials[Material].PriorityList = {{Priority = 1, PartList = {TempPart}}} + else + table.insert(materials[Material].PriorityList[1].PartList, TempPart) + end + end + end + else + OrderList[Order].KitList[Kit].IsPaint = false + OrderList[Order].IsPaint = false + end + elseif ErrorType == 1 then + table.insert(ErrorList, {ErrType = "E.1", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find DXF file"}) + EgtOutLog("Part skipped: " .. TempPart.PartId) + elseif ErrorType == 2 then + table.insert(ErrorList, {ErrType = "E.2", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find material tag in DXF"}) + EgtOutLog("Part skipped: " .. TempPart.PartId) + else + table.insert(ErrorList, {ErrType = "E.6", Uid = "PartId = " .. TempPart.PartId, Description = "Error in DXF reading"}) + EgtOutLog("Part skipped: " .. TempPart.PartId) + end + end + end + end + + -- ordino per modelli kit + function compareOrderExtCode(a,b) + return a.OrderCod < b.OrderCod + end + table.sort(OrderList, compareOrderExtCode) + +end + +-- funzione che distribuisce ordini e kit sui cart +function NestingLib.CreateCart(OrderList, Carts) + local CurrCartIndex = 0 + local OrderOnCart = 0 + local KitOnCart = 0 + local bFirstKit = true + -- suddivido ordini e kit sui cart + for Order = 1, #OrderList do + -- verifico che non sia un ordine di painted parts + if not OrderList[Order].IsPaint then + -- leggo quantita' kit per modello + local KitXOrderModel = KitXCart + for Model = 1, #Config.KitXModel do + if OrderList[Order].OrderCod == Config.KitXModel[Model].Model then + KitXOrderModel = Config.KitXModel[Model].KitQty + end + end + -- verifico se ho completato il carrello con il numero necessario di ordini o kit + if OrderOnCart > 0 and OrderOnCart < OrderXCart and KitOnCart < KitXOrderModel then + OrderOnCart = OrderOnCart + 1 + table.insert(Carts[CurrCartIndex].OrderList, {OrderId = OrderList[Order].OrderId, KitList = {}}) + -- se e' completo passo al carrello successivo + else + CurrCartIndex = CurrCartIndex + 1 + table.insert(Carts, {CartIndex = CurrCartIndex, OrderList = {}}) + table.insert(Carts[CurrCartIndex].OrderList, {OrderId = OrderList[Order].OrderId, KitList = {}}) + KitOnCart = 0 + OrderOnCart = 1 + end + for Kit = 1, #OrderList[Order].KitList do + -- verifico che non sia un kit di painted parts + if not OrderList[Order].KitList[Kit].IsPaint then + -- se c'e' spazio per altri kit, lo aggiungo + if KitOnCart < KitXOrderModel then + table.insert(Carts[CurrCartIndex].OrderList[OrderOnCart].KitList, OrderList[Order].KitList[Kit]) + KitOnCart = KitOnCart + 1 + -- altrimenti creo un nuovo carrello e vi aggiungo il kit + else + CurrCartIndex = CurrCartIndex + 1 + KitOnCart = 1 + OrderOnCart = 1 + table.insert(Carts, {CartIndex = CurrCartIndex, OrderList = {}}) + table.insert(Carts[CurrCartIndex].OrderList, {OrderId = OrderList[Order].OrderId, KitList = {}}) + table.insert(Carts[CurrCartIndex].OrderList[OrderOnCart].KitList, OrderList[Order].KitList[Kit]) + end + end + end + end + end +end +-- + +-- funzione che distribuisce ordini e kit sui cart +--function NestingLib.CreateCart(readBatch, Carts) +-- local CurrCartIndex = 1 +-- local OrderOnCart = 0 +-- local KitOnCart = 0 +-- -- aggiungo primo elemento +-- table.insert(Carts, {CartIndex = 1, OrderList = {}}) +-- -- suddivido ordini e kit sui cart +-- for Order = 1, #readBatch.OrderList do +-- -- verifico se ho completato il carrello con il numero necessario di ordini o kit +-- if OrderOnCart < OrderXCart and KitOnCart < KitXCart then +-- OrderOnCart = OrderOnCart + 1 +-- table.insert(Carts[CurrCartIndex].OrderList, {OrderId = readBatch.OrderList[Order].OrderId, KitList = {}}) +-- -- se e' completo passo al carrello successivo +-- else +-- CurrCartIndex = CurrCartIndex + 1 +-- table.insert(Carts, {CartIndex = CurrCartIndex, OrderList = {}}) +-- table.insert(Carts[CurrCartIndex].OrderList, {OrderId = readBatch.OrderList[Order].OrderId, KitList = {}}) +-- KitOnCart = 0 +-- OrderOnCart = 1 +-- end +-- for Kit = 1, #readBatch.OrderList[Order].KitList do +-- -- se c'e' spazio per altri kit, lo aggiungo +-- if KitOnCart < KitXCart then +-- table.insert(Carts[CurrCartIndex].OrderList[OrderOnCart].KitList, readBatch.OrderList[Order].KitList[Kit]) +-- KitOnCart = KitOnCart + 1 +-- -- altrimenti creo un nuovo carrello e vi aggiungo il kit +-- else +-- CurrCartIndex = CurrCartIndex + 1 +-- KitOnCart = 1 +-- OrderOnCart = 1 +-- table.insert(Carts, {CartIndex = CurrCartIndex, OrderList = {}}) +-- table.insert(Carts[CurrCartIndex].OrderList, {OrderId = readBatch.OrderList[Order].OrderId, KitList = {}}) +-- table.insert(Carts[CurrCartIndex].OrderList[OrderOnCart].KitList, readBatch.OrderList[Order].KitList[Kit]) +-- end +-- end +-- end +--end +-- + +-- funzione che riordina gli ordini secondo i materiali utilizzati +--function NestingLib.SortOrderList(readBatch, Orders) +-- local CurrCartIndex = 1 +-- local OrderOnCart = 0 +-- local KitOnCart = 0 +-- -- suddivido ordini e kit sui cart +-- for Order = 1, #readBatch.OrderList do +-- readBatch.OrderList[Order].MaterialList = {} +-- for Kit = 1, #readBatch.OrderList[Order].KitList do +-- for Part = 1, #readBatch.OrderList[Order].KitList[Kit].PartList do +-- local TempPart = readBatch.OrderList[Order].KitList[Kit].PartList[Part] +-- -- leggo le proprietà dal dxf e le imposto +-- local MatExtCode, PdfLink, Paint, OptParameters, ErrorType = UtilityLib.readDXF(TempPart.CadFilePath) +-- -- solo se trovo il materiale vado avanti per questo pezzo +-- if ErrorType == 0 and MatExtCode then +-- TempPart.MatExtCode = MatExtCode +-- TempPart.PdfLink = PdfLink +-- TempPart.OptParameters = OptParameters +-- local PaintVal = "NO" +-- if Paint then +-- PaintVal = "YES" +-- end +-- TempPart.OptParameters.PaintFlag = PaintVal +-- -- verifico se il materiale di questo pezzo e' gia' tra quelli dell'ordine +-- local bMaterialFound = false +-- for MaterialIndex = 1, #Orders.MaterialList do +-- if readBatch.OrderList[Order].MaterialList[MaterialIndex] == MatExtCode then +-- bMaterialFound = true +-- end +-- end +-- if not bMaterialFound then +-- table.insert(readBatch.OrderList[Order].MaterialList, MatExtCode) +-- end +-- elseif ErrorType == 1 then +-- table.insert(ErrorList, {ErrType = "E.1", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find DXF file"}) +-- EgtOutLog("Part skipped: " .. TempPart.PartId) +-- elseif ErrorType == 2 then +-- table.insert(ErrorList, {ErrType = "E.2", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find material tag in DXF"}) +-- EgtOutLog("Part skipped: " .. TempPart.PartId) +-- else +-- table.insert(ErrorList, {ErrType = "E.6", Uid = "PartId = " .. TempPart.PartId, Description = "Error in DXF reading"}) +-- EgtOutLog("Part skipped: " .. TempPart.PartId) +-- end +-- end +-- end +-- end +-- +-- local Orders = {} +-- for OrderIndex = 1, #readBatch.OrderList do +-- -- se lista ordinata non vuota +-- if #Orders > 0 then +-- local bInserted = false +-- -- scorro le priorita' +-- for SearchIndex = 1, #Orders do +-- local bNotToBeInserted = false +-- local MaxList = math.min(#readBatch.OrderList[OrderIndex].MaterialList, #Orders[SearchIndex].MaterialList) +-- for MaterialIndex = 1, MaxList do +-- if not bInserted and not bNotToBeInserted and +-- ((tonumber(Orders[SearchIndex].MaterialList[MaterialIndex]) > tonumber(readBatch.OrderList[OrderIndex].MaterialList[MaterialIndex])) or +-- (tonumber(SheetList[SearchIndex].PriorityList[PriorityIndex]) == tonumber(materials[Material].SheetList[Sheet].PriorityList[PriorityIndex]) and +-- PriorityIndex == MaxList and #SheetList[SearchIndex].PriorityList > #materials[Material].SheetList[Sheet].PriorityList)) then +-- table.insert(SheetList, SearchIndex, materials[Material].SheetList[Sheet]) +-- bInserted = true +-- elseif +-- (tonumber(SheetList[SearchIndex].PriorityList[PriorityIndex]) < tonumber(materials[Material].SheetList[Sheet].PriorityList[PriorityIndex])) then +-- bNotToBeInserted = true +-- end +-- end +-- end +-- if not bInserted then +-- table.insert(SheetList, materials[Material].SheetList[Sheet]) +-- end +-- else +-- table.insert(SheetList, materials[Material].SheetList[Sheet]) +-- end +-- end +--end +-- + +-- funzione che dati i Cart setta le priorità e divide i pezzi per materiale +function NestingLib.SetPriorityProcessMaterial(Carts, materials, ErrorList) + -- assegno priorità ai carrelli/pezzi + local ActiveCartIndex = 0 + local TotCartIndex = 0 + local Priority = 2 + local PartDoneCount = 0 + for Cart = 1, #Carts do + for Order = 1, #Carts[Cart].OrderList do + for Kit = 1, #Carts[Cart].OrderList[Order].KitList do + for Part = 1, #Carts[Cart].OrderList[Order].KitList[Kit].PartList do + local TempPart = Carts[Cart].OrderList[Order].KitList[Kit].PartList[Part] + if TempPart.OptParameters.PaintFlag == "NO" then + if TempPart.PartId == ProblematicItem then + local x = 2 + end + -- segno su quale cart va il pezzo + TempPart.Cart = Carts[Cart].CartIndex + if TempPart.MatExtCode then + -- suddivido i pezzi per materiale + for Material = 1, #materials do + -- aggiungo liste pezzi + if not materials[Material].PriorityList then materials[Material].PriorityList = {} end + if TempPart.MatExtCode == materials[Material].MatExtCode then + TempPart.MatId = materials[Material].MatId + TempPart.Priority = Priority + -- aggiungo il pezzo alla lista della sua priorita' all'interno del materiale + local bFound = false + for Index = 1, #materials[Material].PriorityList do + if materials[Material].PriorityList[Index].Priority == TempPart.Priority then + table.insert(materials[Material].PriorityList[Index].PartList, TempPart) + bFound = true + end + end + if not bFound then + local Item = {Priority = TempPart.Priority, PartList = {TempPart}} + table.insert(materials[Material].PriorityList, Item) + end + end + end + else + table.insert(ErrorList, {ErrType = "E.10", Uid = "PartId = " .. TempPart.PartId, Description = "Material not found!"}) + end + end + end + end + end + + -- se arrivo al numero di carrelli attivo allo scarico incremento la priorità di uno + local bPriorityIncrement = false + ActiveCartIndex = ActiveCartIndex + 1 + if ActiveCartIndex == CartActiveUnload then + bPriorityIncrement = true + ActiveCartIndex = 0 + end + -- dopo il primo gruppo di cart totali + if Cart > TotCartUnload - CartActiveUnload then + TotCartIndex = TotCartIndex + 1 + -- se arrivo al numero totale di carrelli disponibili allo scarico incremento la priorità di uno + if TotCartIndex == CartActiveUnload then + bPriorityIncrement = true + TotCartIndex = 0 + end + end + if bPriorityIncrement then + Priority = Priority + 1 + end + end +end +-- + +-- funzione che dati i Cart setta le priorità e divide i pezzi per materiale +--function NestingLib.SetPriorityProcessMaterial(Carts, materials, ErrorList) +-- local OrderCount = 0 +-- local KitCount = 0 +-- local PartCount = 0 +-- -- assegno priorità ai carrelli/pezzi +-- local ActiveCartIndex = 0 +-- local TotCartIndex = 0 +-- local Priority = 2 +-- local PartDoneCount = 0 +-- for Cart = 1, #Carts do +-- for Order = 1, #Carts[Cart].OrderList do +-- OrderCount = OrderCount + 1 +-- for Kit = 1, #Carts[Cart].OrderList[Order].KitList do +-- KitCount = KitCount + 1 +-- for Part = 1, #Carts[Cart].OrderList[Order].KitList[Kit].PartList do +-- PartCount = PartCount + 1 +-- local TempPart = Carts[Cart].OrderList[Order].KitList[Kit].PartList[Part] +-- -- segno su quale cart va il pezzo +-- TempPart.Cart = Carts[Cart].CartIndex +-- -- leggo le proprietà dal dxf e le imposto +-- local MatExtCode, PdfLink, Paint, OptParameters, ErrorType = UtilityLib.readDXF(TempPart.CadFilePath) +-- -- solo se trovo il materiale vado avanti per questo pezzo +-- if ErrorType == 0 and MatExtCode then +-- PartDoneCount = PartDoneCount + 1 +-- TempPart.MatExtCode = MatExtCode +-- TempPart.PdfLink = PdfLink +-- TempPart.OptParameters = OptParameters +-- local PaintVal = "NO" +-- if Paint then +-- PaintVal = "YES" +-- end +-- TempPart.OptParameters.PaintFlag = PaintVal +-- -- suddivido i pezzi per materiale +-- for Material = 1, #materials do +-- -- aggiungo liste pezzi +-- if not materials[Material].PartList then materials[Material].PartList = {} end +-- if TempPart.MatExtCode == materials[Material].MatExtCode then +-- TempPart.MatId = materials[Material].MatId +-- -- do priorità 0 ai pezzi pitturati perchè devono essere fatti per primi +-- if Paint == true then +-- TempPart.Priority = 1 +-- else +-- TempPart.Priority = Priority +-- end +-- -- aggiungo il pezzo alla lista della sua priorita' all'interno del materiale +-- local bFound = false +-- for Index = 1, #materials[Material].PartList do +-- if materials[Material].PartList[Index].Priority == TempPart.Priority then +-- table.insert(materials[Material].PartList[Index].PartList, TempPart) +-- bFound = true +-- end +-- end +-- if not bFound then +-- local Item = {Priority = TempPart.Priority, PartList = {TempPart}} +-- table.insert(materials[Material].PartList, Item) +-- end +-- end +-- end +-- elseif ErrorType == 1 then +-- table.insert(ErrorList, {ErrType = "E.1", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find DXF file"}) +-- EgtOutLog("Part skipped: " .. TempPart.PartId) +-- elseif ErrorType == 2 then +-- table.insert(ErrorList, {ErrType = "E.2", Uid = "PartId = " .. TempPart.PartId, Description = "Can't find material tag in DXF"}) +-- EgtOutLog("Part skipped: " .. TempPart.PartId) +-- else +-- table.insert(ErrorList, {ErrType = "E.6", Uid = "PartId = " .. TempPart.PartId, Description = "Error in DXF reading"}) +-- EgtOutLog("Part skipped: " .. TempPart.PartId) +-- end +-- end +-- end +-- end +-- +-- -- se arrivo al numero di carrelli attivo allo scarico incremento la priorità di uno +-- local bPriorityIncrement = false +-- ActiveCartIndex = ActiveCartIndex + 1 +-- if ActiveCartIndex == CartActiveUnload then +-- bPriorityIncrement = true +-- ActiveCartIndex = 0 +-- end +-- -- dopo il primo gruppo di cart totali +-- if Cart > TotCartUnload - CartActiveUnload then +-- TotCartIndex = TotCartIndex + 1 +-- -- se arrivo al numero totale di carrelli disponibili allo scarico incremento la priorità di uno +-- if TotCartIndex == CartActiveUnload then +-- bPriorityIncrement = true +-- TotCartIndex = 0 +-- end +-- end +-- if bPriorityIncrement then +-- Priority = Priority + 1 +-- end +---- -- se arrivo al numero di carrelli attivo allo scarico incremento la priorità di uno +---- if ActiveCartIndex == CartActiveUnload then +---- Priority = Priority + 1 +---- ActiveCartIndex = 0 +---- end +---- -- se arrivo al numero totale di carrelli disponibili allo scarico incremento la priorità di uno +---- if TotCartIndex == TotCartUnload then +---- Priority = Priority + 1 +---- TotCartIndex = 0 +---- end +-- end +--end +-- + +-- funzione che dati i materiali prende tutti i pezzi di priorita' 1 e crea i bin +function NestingLib.CreateBin(materials, Bins) + -- per ogni materiale + for materialIndex = 1, #materials do + -- cerco il gruppo di pezzi a priorita' 1 + for PriorityIndex = 1, #materials[materialIndex].PriorityList do + if materials[materialIndex].PriorityList[PriorityIndex] and materials[materialIndex].PriorityList[PriorityIndex].Priority == 1 then + -- ciclo sui pezzi a priorita' 1 + for PartIndex = 1, #materials[materialIndex].PriorityList[PriorityIndex].PartList do + -- ciclo sui bin + local BinFound = false + for BinIndex = 1, #Bins do + if materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].PartExtCode == Bins[BinIndex].PartExtCode then + table.insert(Bins[BinIndex].PartList, {PartId = materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].PartId}) + -- scrivo indice bin sul pezzo + materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].Bin = BinIndex + BinFound = true + end + end + if not BinFound then + table.insert(Bins, {BinIndex = #Bins + 1, + PartExtCode = materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].PartExtCode, + PartRev = materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].PartRev, + PartList = {{PartId = materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].PartId}}}) + -- scrivo indice bin sul pezzo + materials[materialIndex].PriorityList[PriorityIndex].PartList[PartIndex].Bin = #Bins + end + end + end + end + end +end + +-- key per info area +local AREA = "Area" +local OUTLINE = "Outline" +local HOLE = "HOLE" +local PARTID = "PartId" +local PRIORITY = "Priority" +local DTMXPOS = "DATA MATRIX CODE POSITION" +local CARTBININFO = "CARTBININFO" +local INTPART = "INTPART" +local RAMP = "RAMP" +local SKELETONTRACK = "SKELETONTRACK" +local SKELETONPART = "SKELETON" +local CUTOPT = "CUTOPT" +-- funzione legge il dxf ed aggiunge il pezzo al nesting +local function AddPartListToNesting(PartList, ErrorList, Material) + local LastId = GDB_ID.ROOT + for Part = 1, #PartList do + -- tipo di rotazione del pezzo consentita : 0 -> rotazione libera, 1 -> rotazione solo di 180°, 2 -> nessuna rotazione + local RotationType = 0 + -- verifico se gia' presente per importazione precedente + local PartId1 = EgtGetFirstNameInGroup(GDB_ID.ROOT, PartList[Part].PartId) + if not PartId1 then + -- importo il dxf del pezzo + DXFpath = string.gsub(PartList[Part].CadFilePath, "\\", '/') + EgtImportDxf(DXFpath) + -- se LastId nullo carico primo pezzo + if LastId == GDB_ID.ROOT then + PartId1 = EgtGetLastInGroup(GDB_ID.ROOT) + LastId = PartId1 + else + PartId1 = EgtGetNextPart(LastId) + end + -- verifico se è un solo pezzo + local PartId2 = EgtGetLastPart(LastId) + if PartId1 == PartId2 then + LastId = PartId1 + else + -- ERRORE!! + return + end + -- assegno l'Id del pezzo e la priorità + EgtSetInfo(PartId1, PARTID, PartList[Part].PartId) + EgtSetName(PartId1, PartList[Part].PartDtmx) + EgtSetInfo(PartId1, PRIORITY, PartList[Part].Priority) + end + -- lista lavorazioni interne + local InternalMach = {} + -- lista percorsi interni per pezzi piccoli + local IntMachSmallPart = {} + -- regione skeleton + local nSkeletonRegionId = GDB_ID.NULL + -- spengo tutti i layer inutili + local LayerId = EgtGetFirstLayer(PartId1) + local nMaxId = GDB_ID.NULL + local bFound = false + while LayerId do + local layerName = EgtGetName(LayerId) + local bOutline = false + -- verifico se ha un nome di outline + for Mach = 1, #OutlineMachining[1] do + if layerName == OutlineMachining[1][Mach] then + bOutline = true + end + end + if bOutline then + -- prendo quello più grande che sarà l'esterno + local dMaxArea = 0 + local GeomList = {} + local OutlineId = EgtGetFirstInGroup(LayerId) + while OutlineId do + if EgtGetType( OutlineId) == GDB_TY.CRV_COMPO or EgtGetType( OutlineId) == GDB_TY.CRV_ARC then + -- ne verifico lo spessore + local OutlineDepth = EgtCurveThickness(OutlineId) + if OutlineDepth >= 0 then + table.insert(ErrorList, {ErrType = "E.13", Uid = "PartId = " .. PartList[Part].PartId, Description = "Error, outline thickness must be negative!"}) + EgtOutLog("Error in ".. PartList[Part].CadFilePath ..": outline thickness must be negative!") + return + end + -- se entro la tolleranza + if -OutlineDepth >= (Material.T_mm - Config.ThicknessTolerance) and -OutlineDepth <= (Material.T_mm + Config.ThicknessTolerance) then + EgtModifyCurveThickness(OutlineId, -Material.T_mm) + end + -- se il percorso non è chiuso + if not EgtCurveIsClosed(OutlineId) then + -- calcolo distanza tra inizio e fine + local StartPoint = EgtSP(OutlineId) + local EndPoint = EgtEP(OutlineId) + if abs(Vector3d.len(StartPoint - EndPoint)) <= Config.OpenPathTolerance then + -- accorcio estremi di mezzo decimo di millimetro per evitare successivi problemi con offset + EgtTrimCurveStartAtLen(OutlineId, 0.015) + EgtTrimCurveEndAtLen(OutlineId, EgtCurveLength(OutlineId) - 0.015) + EgtCloseCurveCompo(OutlineId) + else + table.insert(ErrorList, {ErrType = "E.8", Uid = "PartId = " .. PartList[Part].PartId, Description = "Open paths found"}) + EgtOutLog("Error in ".. PartList[Part].CadFilePath ..": open paths found") + return + end + end + local dArea = EgtCurveAreaXY(OutlineId) + if dArea and abs(dArea) > dMaxArea then + dMaxArea = abs(dArea) + nMaxId = OutlineId + -- sposto entità contorno esterno per prima + table.insert(GeomList, 1, OutlineId) + else + table.insert(GeomList, OutlineId) + end + else + table.insert(ErrorList, {ErrType = "E.8", Uid = "PartId = " .. PartList[Part].PartId, Description = "There are entities that are not CompositeCurves or Arcs"}) + EgtOutLog("Warning in ".. PartList[Part].CadFilePath ..": there is entities that are not compo or arcs") + end + OutlineId = EgtGetNext(OutlineId) + end + -- se ho trovato il contorno esterno + if nMaxId ~= GDB_ID.NULL then + -- se necessario inverto le curve per dividere contorni interni ed esterno + OutlineId = EgtGetFirstInGroup(LayerId) + while OutlineId do + local dArea = EgtCurveAreaXY(OutlineId) + if not dArea then + table.insert(ErrorList, {ErrType = "E.8", Uid = "PartId = " .. PartList[Part].PartId, Description = "Open paths found"}) + EgtOutLog("Error in ".. PartList[Part].CadFilePath ..": open paths found") + return + else + -- se contorno esterno in senso orario o contorno interno antiorario lo inverto + if (OutlineId == nMaxId and dArea < 0) or (OutlineId ~= nMaxId and dArea > 0) then + EgtInvertCurve(OutlineId) + end + end + OutlineId = EgtGetNext(OutlineId) + end + -- salvo area come info + local dArea = EgtCurveAreaXY(nMaxId) + EgtSetInfo(PartId1, AREA, dArea) + -- scrivo carrello e gruppo carrelli a cui appartiene + local BBox = EgtGetBBox(nMaxId,GDB_BB.STANDARD) + local CartText = "" + if PartList[Part].Bin then + CartText = "B" .. PartList[Part].Bin + elseif PartList[Part].Cart then + CartText = "C" .. PartList[Part].Cart + end + if DebugCode and PartList[Part].Priority then + CartText = CartText .. "-" .. PartList[Part].Priority + end + local CartIndexLayer = EgtGroup(PartId1) + EgtSetName(CartIndexLayer, CARTBININFO) + EgtSetInfo(CartIndexLayer, "DTMX", PartList[Part].PartDtmx) + if PartList[Part].OptParameters.RoundEdge == 'YES' or PartList[Part].OptParameters.TNutFlag == 'YES' then + EgtSetInfo(CartIndexLayer, "TEXT", CartText .. '*') + else + EgtSetInfo(CartIndexLayer, "TEXT", CartText) + end + EgtSetInfo(CartIndexLayer, "MATID", PartList[Part].MatId) + EgtTextAdv(CartIndexLayer, + Point3d(BBox:getCenter():getX(), BBox:getCenter():getY(), BBox:getMax():getZ()), + 0, CartText, "Arial", 2, 'S', 30, 2, 0, GDB_TI.MC) + EgtSetColor(CartIndexLayer, 'WHITE') + -- EgtText( int nParentId, Point3d PtIni, string Text, num dH [, int nRefType = GDB_RT.LOC]) + -- calcolo box per sapere se girare il pezzo + local OutlineBox = EgtGetBBox(nMaxId, GDB_BB.STANDARD) + local MinOutlineBox = BBox3d.getMin(OutlineBox) + local MaxOutlineBox = BBox3d.getMax(OutlineBox) + local OutlineY = Point3d.getY(MaxOutlineBox) - Point3d.getY(MinOutlineBox) + local OutlineX = Point3d.getX(MaxOutlineBox) - Point3d.getX(MinOutlineBox) + -- imposto RollerDist + local RollerDist = MXRollerDist + if IsOffline then + RollerDist = NWRollerDist + end + -- if dArea < Config.dVerySmallPartArea then + -- RotationType = 2 + -- controllo se ha una venatura da rispettare + local nGrainLayerId = EgtGetFirstNameInGroup(PartId1, 'GRAIN') + if nGrainLayerId then +-- -- recupero linea di direzione +-- local nGrainId = EgtGetFirstInGroup(nGrainLayerId) +-- if nGrainId then +-- local vtGrain = EgtSV(nGrainId) +-- end + RotationType = 1 + elseif OutlineX <= RollerDist and OutlineY > RollerDist then + EgtRotate(PartId1, ORIG(), Z_AX(), 90) + RotationType = 1 + elseif OutlineY <= RollerDist and OutlineX > RollerDist then + RotationType = 1 + end + EgtSetName(nMaxId, OUTLINE) + -- copio outline in un layer dedicato + local OutlineLayer = EgtGroup(PartId1) + EgtSetName(OutlineLayer, OUTLINE) + local OutlineCopy = EgtCopy(nMaxId, OutlineLayer) + EgtSetName(OutlineCopy, OUTLINE) + -- creo regione del pezzo + local RegId = EgtSurfFlatRegion(OutlineLayer, GeomList) + EgtSetName(RegId, PartList[Part].PartDtmx) + EgtSetColor(RegId, Color3d(255,128,0,50)) + EgtSetStatus(LayerId, GDB_ST.ON) + -- creo regione traccia utensile + local ToolDiam = 0 + if EgtMdbSetCurrMachining(OutlineMachining[2][1]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + end + -- verifico se ci sono opzioni di lavorazione + if PartList[Part].OptParameters.CutOpt then + if PartList[Part].OptParameters.CutOpt == SKELETONPART or PartList[Part].OptParameters.CutOpt == "SKELETON&TAB" then + -- creo regione per skeleton + local nSkeletonId = EgtOffsetCurveAdv(nMaxId, ToolDiam + Config.dSkeletonWidth) + EgtSetName(nSkeletonId, "SkeletonOutline") + EgtRelocateGlob(nSkeletonId, OutlineLayer) + local srfSkeletonId = EgtSurfFlatRegion(OutlineLayer, {nMaxId, nSkeletonId}) + EgtSetName(srfSkeletonId, "SKELETON") + EgtSetStatus(nSkeletonId, GDB_ST.OFF) + EgtSetStatus(srfSkeletonId, GDB_ST.OFF) + nSkeletonRegionId = srfSkeletonId + end + -- salvo l'info per processarla in lavorazione + EgtSetInfo(OutlineLayer, CUTOPT, PartList[Part].OptParameters.CutOpt) + end + -- se c'e' opzione dimensione etichetta + if PartList[Part].OptParameters.Label then + -- la salvo + EgtSetInfo(OutlineLayer, "LABEL", PartList[Part].OptParameters.Label) + end + -- ciclo sui percorsi del pezzo + OutlineId = EgtGetFirstInGroup(LayerId) + while OutlineId do + -- se contorno interno + if OutlineId ~= nMaxId then + -- classifico percorsi interni come svuotature o buchi per pezzi + -- classifico percorso rispetto al pezzo + local OutlineClassification = EgtCurveWithRegionClassify(OutlineId, RegId) + -- verifico spessore percorsi interni + local OutlineDepth = EgtCurveThickness(OutlineId) + -- se spesso come il pezzo e area maggiore di quella minima per un buco + local dIntArea = EgtCurveAreaXY(OutlineId) + if -OutlineDepth >= (Material.T_mm - Config.ThicknessTolerance) and math.abs(dIntArea) >= Config.IntPartMinArea then + EgtSetInfo(OutlineId, INTPART, 1) + EgtSetInfo(PartId1, INTPART, 1) + table.insert(IntMachSmallPart, OutlineId) + elseif OutlineClassification == GDB_CRC.OUT or OutlineClassification == GDB_CRC.INTERS then + -- se contorno interno, lo aggiungo alla lista lavorazioni interne + table.insert(InternalMach, OutlineId) + end + end + -- creo regione traccia utensile + local ToolDiam = 0 + if EgtMdbSetCurrMachining(OutlineMachining[2][1]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + end + if Config.bSkeletonReduction then + local nOffId, nOffCnt = EgtOffsetCurveAdv(OutlineId, ToolDiam + 0.01) + -- elimino gli offset successivi al primo risultanti da porzioni di percorso con distanza inferiore all'offset + for Index = 1, nOffCnt - 1 do + EgtErase(nOffId + Index) + end + if not nOffId then + table.insert(ErrorList, {ErrType = "E.8", Uid = "PartId = " .. PartList[Part].PartId, Description = "Open paths found"}) + EgtOutLog("Error in ".. PartList[Part].CadFilePath ..": open paths found") + return + end + EgtSetName(nOffId, "SkeletonToolOutline") + EgtRelocateGlob(nOffId, OutlineLayer) + local srfToolId = GDB_ID.NULL + if OutlineId == nMaxId then + srfToolId = EgtSurfFlatRegion(OutlineLayer, {OutlineId, nOffId}) + else + -- verifico se dimensioni minori della griglia + local b3Outline = EgtGetBBoxGlob(OutlineId, GDB_BB.STANDARD + GDB_BB.ONLY_VISIBLE + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM) + if b3Outline:getDimX() < Config.bSRMaxWidth and b3Outline:getDimY() < Config.bSRMaxHeight or nOffId == GDB_ID.NULL then + srfToolId = EgtSurfFlatRegion(OutlineLayer, OutlineId) + else + srfToolId = EgtSurfFlatRegion(OutlineLayer, {nOffId, OutlineId}) + end + EgtInvertSurf(srfToolId) + end + EgtSetName(srfToolId, SKELETONTRACK) + EgtSetStatus(nOffId, GDB_ST.OFF) + EgtSetStatus(srfToolId, GDB_ST.OFF) + end + -- vado a percorso successivo + OutlineId = EgtGetNext(OutlineId) + end + bFound = true + -- se non ho trovato il contorno esterno do' errore + else + EgtOutLog("Error outline not found in part " .. PartList[Part].PartId) + table.insert(ErrorList, {ErrType = "E.4", Uid = "PartId = " .. PartList[Part].PartId, Description = "Can't find outline"}) + return + end + elseif layerName == DTMXPOS then + -- recupero punti dentro questo layer + local bFirstPoint = true + local nPointId = EgtGetFirstInGroup(LayerId) + local dArea = EgtGetInfo(PartId1, AREA, "d") + while nPointId and nPointId ~= GDB_ID.NULL do + if bFirstPoint or (dArea and dArea > Config.dSkelSkinTab_MaxArea) then + -- li chiamo con nome part piu' _QR + EgtSetName(nPointId, "$QR$" .. PartList[Part].PartDtmx) + bFirstPoint = false + end + nPointId = EgtGetNext(nPointId) + end + EgtSetStatus(LayerId, GDB_ST.ON) + elseif layerName == OUTLINE or layerName == HOLE or layerName == CARTBININFO or layerName == RAMP then + EgtSetStatus(LayerId, GDB_ST.ON) + else + EgtSetStatus(LayerId, GDB_ST.OFF) + end + LayerId = EgtGetNext(LayerId) + end + -- se non ho trovato il contorno esterno do' errore + if not bFound then + EgtOutLog("Error outline not found in part " .. PartList[Part].PartId) + table.insert(ErrorList, {ErrType = "E.4", Uid = "PartId = " .. PartList[Part].PartId, Description = "Can't find outline"}) + return + end + -- preparo pezzo per il nesting + local Priority = 0 + if PartList[Part].Priority then + Priority = PartList[Part].Priority + end + local bCanRotate, dRotStep = true, 0 + if RotationType == 1 then + dRotStep = 180 + elseif RotationType == 2 then + bCanRotate = false + end + -- aggiungo pezzo al nesting + EgtAutoNestAddPart( PartId1, nMaxId, false, bCanRotate, dRotStep, Priority, 1) + -- EgtAutoNestAddPart( PartId, OutlineId, bCanFlip, bCanRotate, dRotStep, nPriority, nCount) + -- aggiungo le lavorazioni interne abbastanza grandi da poterci aggiungere pezzi + for IntPart = 1, #IntMachSmallPart do + EgtAutoNestAddHoleToPart( PartId1, IntMachSmallPart[IntPart]) + -- EgtAutoNestAddToolOutlineToPart( int nPartId, int nToolOutlineId) + end + -- aggiungo le lavorazioni interne come possibili ingombri + for IntMach = 1, #InternalMach do + EgtAutoNestAddToolOutlineToPart( PartId1, InternalMach[IntMach]) + -- EgtAutoNestAddToolOutlineToPart( int nPartId, int nToolOutlineId) + end + EgtAutoNestAddToolOutlineToPart( PartId1, nSkeletonRegionId) + end +end +-- + +-- funzione che imposta le macchine multiax secondo indice +local function SetMachineByIndex(MachId) + if MachId == 1 then + sCurrMachName = "Multiax-NE_Nest01" + EgtSetCurrMachine(sCurrMachName) + elseif MachId == 2 then + sCurrMachName = "Multiax-NE_Nest02" + EgtSetCurrMachine(sCurrMachName) + end +end +-- + +-- funzione che crea gruppi di lavorazione con grezzi e pezzi secondo nesting +local function CreateMachSheets(LastMachGroupId, SheetPartId, Material, PartList, MachId, nRaw1Id, FirstMachIndex) + -- imposto macchina secondo indice, se NE + if not IsOffline then + SetMachineByIndex(MachId) + end + -- disposizione sheet e parts + local SheetId = GDB_ID.NULL + local vtAdd = V_NULL() + local nRawId = GDB_ID.NULL +-- local SheetCounter = 0 + local Sheet = {PartList = {}} + local bFirstSheet = true + local nMach2SheetId = FirstMachIndex + for i = 0, 999 do + local nType, nId, nFlag, dX, dY, dAngRot = EgtAutoNestGetOneResult( i) + if not nType then break end + -- se sheet + if nType > 0 then +-- SheetCounter = SheetCounter + 1 + if LastMachGroupId then + if bFirstSheet then + bFirstSheet = false + -- attivo gruppo di lavorazione + EgtSetCurrMachGroup(LastMachGroupId) + -- imposto grezzo + nRawId = EgtGetFirstRawPart() + -- se seconda macchina, recupero il grezzo corretto + if MachId == 2 then + nRawId = EgtGetInfo(nRawId, 'LastRaw2') + EgtSetCurrMachGroup(EgtGetParent(EgtGetParent(nRawId))) + end + -- imposto foglio + Sheet = Material.SheetList[#Material.SheetList] + else + nRawId = nil + end + else + -- creo gruppo di lavorazione + local MachGroupName + if MachId == 2 then + nMach2SheetId = nMach2SheetId + 1 + --MachGroupName = "Sheet" .. nMach2SheetId .. "_2" + --MachGroupName = "Sheet" .. nRaw1Id + MachGroupName = EgtGetMachGroupNewName("M2_Sheet") + MachGroupName = "M2Sheet" .. nMach2SheetId + else + MachGroupName = "Sheet" .. #Material.SheetList + 1 --SheetCounter + end +-- local sMachine = "Multiax-NE_Nest" +-- if IsOffline then +-- sMachine = "Northwood-RHD" +-- end + local bOk = EgtAddMachGroup(MachGroupName, sCurrMachName) + -- se macchina 2 aggiungo info e riferimento a foglio della macchina 1 + if MachId ==2 then + EgtSetInfo(EgtGetCurrMachGroup(), 'MachId', MachId) + local nOrigSheetId = EgtGetMachGroupId("Sheet" .. nMach2SheetId) + EgtSetInfo(EgtGetCurrMachGroup(), 'OrigSheetId', nOrigSheetId) + end + -- imposto tavola + local vtOffs = UtilityLib.SetupMachineTable(IsOffline) + -- creo grezzo + if bOk then + nRawId = UtilityLib.RawPartCreation(SheetPartId, vtOffs, IsOffline) + -- creo foglio e lo aggiungo a lista + Sheet = {MachGroupName = MachGroupName, PartList = {}} + if MachId == 1 then + table.insert(Material.SheetList, Sheet) + end + else + nRawId = nil + --SheetCounter = SheetCounter - 1 + end + end + --EgtOutLog( string.format( 'Sheet %d mult=%d parts=%d', nId, nType, nFlag)) + + -- altrimenti pezzo + else + --EgtOutLog( string.format( ' Part %d pos=%f,%f rot=%f flip=%d', nId, dX, dY, dAngRot, nFlag)) + -- se ho un grezzo valido metto i pezzi + local PartId = nId + if MachId ~= 2 then + if nFlag ~= 0 then + EgtMirror( PartId, ORIG(), Y_AX(), GDB_RT.GLOB) + end + EgtRotate( PartId, ORIG(), Z_AX(), dAngRot, GDB_RT.GLOB) + EgtMove( PartId, Vector3d( dX, dY, 0) + vtAdd, GDB_RT.GLOB) + end + -- se c'e' un grezzo valido + if nRawId then + local PartBBox = EgtGetBBoxGlob(PartId, GDB_BB.STANDARD) + local ptPos = Point3d(PartBBox:getMin():getX(), PartBBox:getMin():getY(), 0) + local bOk = EgtAddPartToRawPart(PartId, ptPos, nRawId) + -- se pezzo aggiunto al grezzo + if bOk and MachId == 1 then + -- lo aggiungo alla lista pezzi del foglio + table.insert(Sheet.PartList, {PartId = EgtGetInfo(PartId, PARTID)}) + if tonumber(EgtGetInfo(PartId, PARTID)) == ProblematicItem then + local x = 2 + end + -- lo elimino dalla lista pezzi + local PartIndex = 0 + for Index = 1, #PartList do + if PartList[Index].PartId == tonumber(EgtGetInfo(PartId, PARTID)) then + PartIndex = Index + end + end + table.remove(PartList, PartIndex) + end + end + end + end + -- aggiorno visualizzazione + EgtZoom( SCE_ZM.ALL) + return nRawId +end +-- + +local SHEETLABEL = "SheetLabel" +-- funzione che nesta i pezzi passatigli dato un grezzo di partenza e/o un materiale +-- LastRaw: grezzo incompleto da riempire +-- PartList: lista dei pezzi da nestare +-- Material: materiale su cui nestare i pezzi +function NestingLib.NestPartInRawPart(LastRaw, PartList, Material, ErrorList, IsEstimate, IsValidation) + -- inizio nesting automatico + EgtAutoNestStart() + + -- creo pannello del materiale + local SheetPartId = EgtGroup(GDB_ID.ROOT) + EgtSetName(SheetPartId, "Sheet") + local SheetLayerId = EgtGroup(SheetPartId) + EgtSetName(SheetLayerId, OUTLINE) + local SheetOutlineId = EgtRectangle2P(SheetLayerId, Point3d(0,0,0), Point3d(Material.L_mm, Material.W_mm, 0), GDB_RT.GLOB) + EgtModifyCurveThickness(SheetOutlineId, -Material.T_mm) + EgtSetName(SheetOutlineId, OUTLINE) + + -- ricavo Kerf di questo materiale + local dKerf = 9 + for Index = 1, #Config.Kerf do + if Config.Kerf[Index].MatId == Material.MatId then + dKerf = Config.Kerf[Index].Kerf + end + end + + -- verifico se ultimo grezzo non nullo + local LastMachGroupId = nil + if LastRaw and LastRaw ~= GDB_ID.NULL then + -- recupero Id gruppo di lavoro e lo attivo + LastMachGroupId = EgtGetParent(EgtGetParent(LastRaw)) + -- recupero lista pezzi già presenti nel grezzo + EgtSetCurrMachGroup(LastMachGroupId) + -- recupero PartId dei pezzi + local NestedPartList = {} + local PartId = EgtGetFirstPartInRawPart(LastRaw) + while PartId do + local LayerOutlineId = EgtGetFirstNameInGroup(PartId, OUTLINE) + local OutlineId = EgtGetFirstNameInGroup(LayerOutlineId, OUTLINE) + table.insert(NestedPartList, OutlineId) + PartId = EgtGetNextPartInRawPart(PartId) + end + -- resetto gruppo di lavoro per tornare in modalità disegno a fare il nesting + EgtResetCurrMachGroup() + -- Preparo foglio per nesting + EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, dKerf, 0, 1) -- EgtAutoNestAddSheet( SheetId, OutlineId, dKerf, nPriority, nCount) + -- imposto come difetti i pezzi già presenti + for Index = 1, #NestedPartList do + EgtAutoNestAddDefectToSheet(SheetPartId, NestedPartList[Index]) -- EgtAutoNestAddDefectToSheet( SheetId, DefectId) + end + -- recupero etichetta + local nSheetLabel = EgtGetFirstNameInGroup(LastRaw, SHEETLABEL) + -- la aggiungo come difetto + EgtAutoNestAddDefectToSheet(SheetPartId, nSheetLabel) -- EgtAutoNestAddDefectToSheet( SheetId, DefectId) + else + -- creo etichetta dello sheet + local dLabelW = 50 + local dLabelH = 25 + local dYPos = Material.W_mm + if Material.W_mm > 1465 then + dYPos = 1465 + (dLabelH) + end + local nSheetLabel = EgtRectangle2P(SheetLayerId, Point3d(0, dYPos - dLabelH,0), Point3d(dLabelW, dYPos, 0), GDB_RT.GLOB) + EgtSetName(nSheetLabel, SHEETLABEL) + -- creo foglio per nesting + EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, dKerf, 0, 50) -- EgtAutoNestAddSheet( SheetId, OutlineId, dKerf, nPriority, nCount) + -- aggiungo etichetta come difetto + EgtAutoNestAddDefectToSheet(SheetPartId, nSheetLabel) -- EgtAutoNestAddDefectToSheet( SheetId, DefectId) + end + + -- aggiungo tutti i pezzi al nesting + AddPartListToNesting(PartList, ErrorList, Material) + if #ErrorList > 0 then return end + -- recupero diametro utensile usato per outline + local ToolDiam = 0 + local x = EgtGetCurrMachineName() + if EgtMdbSetCurrMachining(OutlineMachining[2][1]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + end + -- imposto distanza tra i pezzi + if ToolDiam and ToolDiam > 0 then + EgtAutoNestSetInterpartGap(ToolDiam + 1.6) + else + table.insert(ErrorList, {ErrType = "E.9", Uid = "Generic", Description = "Outline tool diameter not found!"}) + end + local nMaxTime = 5 + if IsEstimate then + nMaxTime = Config.nEstimMaxTime + else + nMaxTime = Config.nFinalMaxTime + end + if IsValidation then + nMaxTime = 2 + end + -- imposto tempo di nesting e lo avvio + EgtAutoNestCompute(true, nMaxTime) + + -- Variabili di calcolo + local nNestedParts, nParts, nSheets, nNestings, dTotFillRatio + -- Attesa fine calcolo + local bOk = true + local nTime = 0 + while bOk do + bOk, nStat = EgtAutoNestGetComputationStatus() + if nStat == 2 or nStat == 3 then + nNestedParts, nParts, nSheets, nNestings, dTotFillRatio = EgtAutoNestGetResults() + --EgtOutText( string.format( 'Parts : %d/%d Filling : %.2f%%', nNestedParts, nParts, 100 * dTotFillRatio)) + end + if nStat == 3 then break end + nTime = nTime + 1 + if EgtProcessEvents( nTime / nMaxTime * 100, 995) == 1 then + bOk = EgtAutoNestCancelComputation() + break + end + end + + -- se nesting andato bene + --if false then + if bOk then + -- calcolo gruppi di lavorazione + local FirstMachIndex = #Material.SheetList + LastRaw = CreateMachSheets(LastMachGroupId, SheetPartId, Material, PartList, 1) + if not IsOffline and not IsEstimate and not IsValidation then + LastRaw2 = CreateMachSheets(LastMachGroupId, SheetPartId, Material, PartList, 2, LastRaw, FirstMachIndex) + EgtSetInfo(LastRaw, 'LastRaw2', LastRaw2) + end + -- se impostata seconda macchina, reimposto la prima + local sMachName = EgtGetCurrMachineName() + if sMachName == 'Multiax-NE_Nest02' then + SetMachineByIndex(1) + end + else + table.insert(ErrorList, {ErrType = "E.10", Uid = "Generic", Description = "Error in nesting function!"}) + end + -- ritorno l'ultimo grezzo utilizzato + return LastRaw +end +-- + +-- Funzione che restituisce entità in lavorazione corrente +function GetEntIdFromCurrMachining() + local Geo = EgtGetMachiningGeometry() + if not Geo then return GDB_ID.NULL end + if type( Geo) == 'table' and + type( Geo[1]) == 'table' and type( Geo[1][1]) == 'number' and + type( Geo[#Geo]) == 'table' and type( Geo[#Geo][1]) == 'number' then + return Geo[1][1], Geo[#Geo][1] + else + return GDB_ID.NULL + end +end + +-- funzione che imposta le lavorazioni nelle liste per TSP +local function InitInTSP(MachId, MachList, MachListIndex) + local nStartId, nEndId = GetEntIdFromCurrMachining() + if nStartId ~= GDB_ID.NULL and EgtExistsObj( nStartId) and nEndId ~= GDB_ID.NULL and EgtExistsObj( nEndId) then + local ptStart = EgtSP( nStartId, GDB_ID.ROOT) + local ptEnd = EgtEP( nEndId, GDB_ID.ROOT) + local bInvert = EgtGetMachiningParam( MCH_MP.INVERT) + local dAng = EgtGetMachiningParam( MCH_MP.SIDEANGLE) + if not dAng then dAng = 0 end + if bInvert then + ptStart, ptEnd = ptEnd, ptStart + end + if MachListIndex and MachListIndex > 0 then + table.insert( MachList[MachListIndex], {Id=MachId, Start= ptStart, End = ptEnd, Ang=abs( dAng)}) + else + table.insert( MachList, {Id=MachId, Start= ptStart, End = ptEnd, Ang=abs( dAng)}) + end + end +end +-- + +-- funzione che ordina le lavorazioni con l'algoritmo TSP +local function SortCuts(MachiningList, LastMch) + if MachiningList and #MachiningList > 0 then + -- recupero punto finale ultima lavorazione + EgtSetCurrMachining(LastMch) + local ptEnd = EgtGetMachiningEndPoint() or Point3d( -200, -200, 0) + -- calcolo ordinamento + EgtSpInit() + for i = 1, #MachiningList do + EgtSpAddPoint( MachiningList[i].Start:getX(), MachiningList[i].Start:getY(), 0, 0, MachiningList[i].Ang, + MachiningList[i].End:getX(), MachiningList[i].End:getY(), 0, 0, MachiningList[i].Ang) + end + EgtSpSetOpenBound( true, SHP_OB.NEAR_PNT, ptEnd:getX(), ptEnd:getY()) + local vOutlineOrd = EgtSpCalculate( SHP_TY.OPEN) + EgtSpTerminate() + -- applico ordinamento calcolato + -- parto da LastMch precedente + if vOutlineOrd then + for i = 1, #vOutlineOrd do + EgtRelocateGlob( MachiningList[vOutlineOrd[i]].Id, LastMch, GDB_IN.AFTER) + LastMch = MachiningList[vOutlineOrd[i]].Id + end + end + end + return LastMch +end +-- + +-- funzione che ordina le lavorazioni con l'algoritmo TSP +local function SortParts(PartList, bZigZagSorting) + local nRawId = EgtGetFirstRawPart() + local ptRawCenter = EgtGetRawPartCenter(nRawId) + -- calcolo ordinamento + EgtSpInit() + for i = 1, #PartList do + if bZigZagSorting then + EgtSpAddPoint( PartList[i].BBox:getCenter():getX(), PartList[i].BBox:getCenter():getY()) + else + local dDeltaX = PartList[i].BBox:getCenter():getX() - ptRawCenter:getX() + local dDeltaY = PartList[i].BBox:getCenter():getY() - ptRawCenter:getY() + local dDistXY = sqrt( dDeltaX * dDeltaX + dDeltaY * dDeltaY) + EgtSpAddPoint( PartList[i].BBox:getCenter():getX(), PartList[i].BBox:getCenter():getY(), 10 * dDistXY, 0, 0, + PartList[i].BBox:getCenter():getX(), PartList[i].BBox:getCenter():getY(), 10 * dDistXY, 0, 0) + end + end + EgtSpSetOpenBound( true, SHP_OB.NEAR_PNT, -200, -200, 20000, 0, 0) + local vOutlineOrd + if bZigZagSorting then + -- imposto larghezza colonna zig zag + EgtSpSetZzOwStep(400) + vOutlineOrd = EgtSpCalculate( SHP_TY.ZIGZAG_Y) + else + vOutlineOrd = EgtSpCalculate( SHP_TY.OPEN) + end + EgtSpTerminate() + -- applico ordinamento calcolato + local NewPartList = {} + if vOutlineOrd then + for i = 1, #vOutlineOrd do + table.insert(NewPartList, PartList[vOutlineOrd[i]]) + end + end + return NewPartList +end +-- + +local function ProcessMachinings(HoleList, RampList, PocketingList, IntIntOutlineList, SkinOutlineList, IntExtOutlineList, InternalOutlineList, SmallOutlineList, OutlineList, LastMch) + if not LastMch then + local nPhase = EgtGetCurrPhase() + LastMch = EgtGetPhaseDisposition( nPhase) + end + -- Ordino i tagli esterni ---------- + for HoleMach = 1, #HoleList do + LastMch = SortCuts(HoleList[HoleMach], LastMch) + end + LastMch = SortCuts(RampList, LastMch) + LastMch = SortCuts(PocketingList, LastMch) + LastMch = SortCuts(IntIntOutlineList, LastMch) + LastMch = SortCuts(SkinOutlineList, LastMch) + LastMch = SortCuts(IntExtOutlineList, LastMch) + LastMch = SortCuts(InternalOutlineList, LastMch) + LastMch = SortCuts(SmallOutlineList, LastMch) + LastMch = SortCuts(OutlineList, LastMch) + return LastMch +end + +function NestingLib.VerifyPath(Folder, BatchId, Material, MachId) + local dateNow = os.date("*t") + local Year = dateNow.year + local Month = dateNow.month + local Day = dateNow.day + local CurrPath = Config.sBasePath .. "/" .. Folder + if not UtilityLib.FolderExists(CurrPath) then + EgtCreateDirectory(CurrPath) + end + CurrPath = CurrPath .. "/".. Year + if not UtilityLib.FolderExists(CurrPath) then + EgtCreateDirectory(CurrPath) + end + CurrPath = CurrPath .. "/".. Month + if not UtilityLib.FolderExists(CurrPath) then + EgtCreateDirectory(CurrPath) + end + CurrPath = CurrPath .. "/".. BatchId + if not UtilityLib.FolderExists(CurrPath) then + EgtCreateDirectory(CurrPath) + end + if Material then + CurrPath = CurrPath .. "/".. Material.MatId + if not UtilityLib.FolderExists(CurrPath) then + EgtCreateDirectory(CurrPath) + end + end + -- scelgo nome cartella macchina + if MachId == 0 or MachId == 1 or MachId == 2 then + local MachDirName = '' + if MachId == 0 then + MachDirName = '##REPLACEME##' + elseif MachId == 1 then + MachDirName = 'NE01' + elseif MachId == 2 then + MachDirName = 'NE02' + end + CurrPath = CurrPath .. "/".. MachDirName + if not UtilityLib.FolderExists(CurrPath) then + EgtCreateDirectory(CurrPath) + end + end + return CurrPath +end +-- + +local MACHTYPE = "MachType" -- chiave del tipo di lavorazione per dividerle ed ordinarle +local MACHPATH = "MachPath" -- info per percorso utensile rampa +local SKELETON = "SKELETON" +local PARTCUTSUM = "PartCutSum" +-- funzione che esegue tutte le operazioni post nesting (lavorazioni, stime, svg, ecc) +function NestingLib.PostNestOp(Material, ErrorList, IsEstimate, BatchId, MachId) + -- ciclo sui fogli/gruppi di lavorazione creati + for Sheet = 1, #Material.SheetList do + local PartsArea = 0 + local PartsPriority = {} + local CurrMachGroupId = EgtGetMachGroupId(Material.SheetList[Sheet].MachGroupName) + -- se seconda macchina, imposto gruppo di lavorazione copia + if MachId == 2 then + -- recupero id grezzo originale + local nRawPartId = EgtGetFirstRawPart() + -- cerco gruppo copia con id grezzo originale + local nMachGroupId = EgtGetFirstMachGroup() + while nMachGroupId do + if EgtGetInfo(nMachGroupId, 'OrigSheetId', 'i') == CurrMachGroupId and EgtGetInfo(nMachGroupId, 'MachId', 'i') == 2 then + EgtSetCurrMachGroup(nMachGroupId) + end + nMachGroupId = EgtGetNextMachGroup(nMachGroupId) + end + if not EgtGetCurrMachGroup() then + EgtSetCurrMachGroup(CurrMachGroupId) + end + else + EgtSetCurrMachGroup(CurrMachGroupId) + end + -- imposto SetUp di default + EgtImportSetup() + -- recupero grezzo + local CurrRawPart = EgtGetFirstRawPart() + -- scrivo note materiale per riportarlo sul file cn + EgtSetInfo(CurrRawPart, 'MatId', Material.MatExtCode) + EgtSetInfo(CurrRawPart, 'MatDesc', Material.MatDesc) + -- BBox globale per calcolo remnant + local PartsBBox = BBox3d() + local nSkeletonGroupId = EgtGroup(GDB_ID.ROOT) + EgtSetStatus(nSkeletonGroupId, GDB_ST.OFF) + EgtSetName(nSkeletonGroupId, SKELETON) + local nSkeletonLayerId = EgtGroup(nSkeletonGroupId) + EgtSetStatus(nSkeletonLayerId, GDB_ST.OFF) + EgtSetName(nSkeletonLayerId, SKELETON) + -- creo lavorazioni + if nMachOrderType == 1 then + PartsArea = CreateMachByType(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, 1, ErrorList) + elseif nMachOrderType == 2 then + PartsArea = CreateMachByPart(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, 1, ErrorList) + else + PartsArea = CreateMachByOrderedType(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, ErrorList) + end + if MachId ~= 2 then + -- imposto area totale dei pezzi + Material.SheetList[Sheet].SurfaceWork = PartsArea + -- calcolo area esterna + Material.SheetList[Sheet].SurfaceTotal = Material.L_mm * Material.W_mm + -- assegno al foglio le priorita' + Material.SheetList[Sheet].PriorityList = PartsPriority + end + -- calcolo bbox del grezzo + local SheetBBox = EgtGetRawPartBBox(CurrRawPart) + -- se offline + if IsOffline then + -- calcolo dimensioni area occupata dai pezzi + local CutPartsArea = EgtGetFirstNameInGroup(nSkeletonLayerId, PARTCUTSUM) + local b3Parts = EgtGetBBox(CutPartsArea, GDB_BB.EXACT) + -- scrivo note dimensione area dei pezzi per riportarlo sul file cn + EgtSetInfo(CurrRawPart, 'PartsArea', tostring(math.ceil(b3Parts:getMax():getX() - SheetBBox:getMin():getX())) .. " x " .. + tostring(math.ceil(b3Parts:getMax():getY() - SheetBBox:getMin():getY()))) + end + -- recupero diametro utensile usato taglio di separazione + local ToolDiam = 0 + if EgtMdbSetCurrMachining(OutlineMachining[2][1]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + end + -- verifico se c'è spazio per un multiplo della dimensione minima + local RemnantMultiple = math.floor((SheetBBox:getMax():getX() - PartsBBox:getMax():getX() - ToolDiam) / Config.RemnantMinDimension) + if not IsOffline and RemnantMultiple >= 1 then + -- calcolo posizione in X + local RemnantCutXPos = SheetBBox:getDimX() - (RemnantMultiple * Config.RemnantMinDimension) - ToolDiam + -- creo taglio per remnant + local RemnantCutPart = EgtGroup(GDB_ID.ROOT) + EgtSetName(RemnantCutPart, "REMNANT") + local RemnantCutLayer = EgtGroup(RemnantCutPart) + local RemnantCutLine = EgtLine(RemnantCutLayer, Point3d(0, 0, 0), + Point3d(0, SheetBBox:getDimY(), 0)) + -- lo aggiungo come pezzo al grezzo + EgtAddPartToRawPart(RemnantCutPart, Point3d(RemnantCutXPos, 0, 0), CurrRawPart) + -- lo lavoro + local NewMachId = EgtAddMachining("RemnantSeparationCut", OutlineMachining[2][1]) + -- applico geometria di lavorazione + EgtSetMachiningGeometry(RemnantCutLine) + -- applico la lavorazione + if not EgtApplyMachining() then + table.insert(ErrorList, {ErrType = "E.7", Uid = "Remnant separation cut", Description = "Error in remnant machining!"}) + end + -- salvo dati remnant in sheet + Material.SheetList[Sheet].Remnant = {L_mm = RemnantMultiple * Config.RemnantMinDimension, W_mm = Material.W_mm} + -- lo tolgo dallo skeleton + local nRemnantOutlineId = EgtRectangle2P(RemnantCutLayer, Point3d(SheetBBox:getMax():getX() - (RemnantMultiple * Config.RemnantMinDimension) - ToolDiam, SheetBBox:getMin():getY(), SheetBBox:getMax():getZ()), SheetBBox:getMax(), GDB_RT.GLOB) + local nRemnantSurfId = EgtSurfFlatRegion(RemnantCutLayer, nRemnantOutlineId) + local CutPartsArea = EgtGetFirstNameInGroup(nSkeletonLayerId, PARTCUTSUM) + EgtSurfFrAdd(CutPartsArea, nRemnantSurfId) + EgtSetStatus(nRemnantOutlineId, GDB_ST.OFF) + EgtSetStatus(nRemnantSurfId, GDB_ST.OFF) + end + -- se riduzione dello scheletro attiva + if not IsOffline and Config.bSkeletonReduction then + -- recupero contorno grezzo + local nRawOutlineId = EgtRectangle2P(nSkeletonLayerId, Point3d(SheetBBox:getMin():getX(), SheetBBox:getMin():getY(), SheetBBox:getMax():getZ()), SheetBBox:getMax()) + -- ne creo la superficie + local nRawSurfId = EgtSurfFlatRegion(nSkeletonLayerId, nRawOutlineId) + local CutPartsArea = EgtGetFirstNameInGroup(nSkeletonLayerId, PARTCUTSUM) + EgtSetName(nRawSurfId, SKELETON) + -- calcolo area rimanente per tagli scheletro + EgtSurfFrSubtract(nRawSurfId, CutPartsArea) + -- elimino residui piu' piccoli della minima distanza + -- copio flat region + local nSkeletonFRId = nil + local nCopyRawSurfId =EgtCopy(nRawSurfId, nSkeletonLayerId) + local SkeletonPartId, Count = EgtExplodeSurf(nCopyRawSurfId) + for Index = 0, Count -1 do + local b3SkeletonPart = EgtGetBBoxGlob(SkeletonPartId + Index, GDB_BB.STANDARD + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM) + if b3SkeletonPart:getDimX() > Config.bSRMaxWidth or b3SkeletonPart:getDimY() > Config.bSRMaxHeight then + if not nSkeletonFRId then + nSkeletonFRId = SkeletonPartId + Index + EgtSetName(nSkeletonFRId, "SkeletonSumPart") + else + EgtSurfFrAdd( nSkeletonFRId, SkeletonPartId + Index) + end + end + end + -- se c'e' uno scheletro da tagliare, procedo + if nSkeletonFRId then + -- calcolo griglia + local nSRColumn = math.ceil(SheetBBox:getDimX() / Config.bSRMaxWidth) + local nSRRow = math.ceil(SheetBBox:getDimY() / Config.bSRMaxHeight) + local dSRColumnSP = (SheetBBox:getDimX() - ((nSRColumn - 2) * Config.bSRMaxWidth)) / 2 + local dSRRowSP = (SheetBBox:getDimY() - ((nSRRow - 2) * Config.bSRMaxHeight)) / 2 + -- la disegno + local nSkeletonGridLayerId = EgtGroup(nSkeletonGroupId) + EgtSetStatus(nSkeletonGridLayerId, GDB_ST.OFF) + EgtSetName(nSkeletonGridLayerId, "GRID") + local SkeletonLineList = {} + for CLineIndex = 0, nSRColumn - 2 do + local CLineId = EgtLine(nSkeletonGridLayerId, Point3d(SheetBBox:getMin():getX() + dSRColumnSP + (Config.bSRMaxWidth * CLineIndex), + SheetBBox:getMin():getY(), + SheetBBox:getMax():getZ()), + Point3d(SheetBBox:getMin():getX() + dSRColumnSP + (Config.bSRMaxWidth * CLineIndex), + SheetBBox:getMax():getY(), + SheetBBox:getMax():getZ())) + -- taglio griglia con superficie rimanente + -- int, int EgtTrimCurveWithRegion( int nCrvId, int nRegId, bool bInVsOut, bool bOn) + local nFirstId, nCountId = EgtTrimCurveWithRegion(CLineId, nSkeletonFRId, true, false) + for CountIndex = 0, nCountId - 1 do + local dSkeletonCutLength = math.abs((EgtEP(nFirstId + CountIndex) - EgtSP(nFirstId + CountIndex)):getY()) + local nPartId = EgtGroup(GDB_ID.ROOT) + EgtSetName(nPartId, "SKELETON_".. CLineIndex + 1 .. "_" .. CountIndex + 1) + local nLayerId = EgtGroup(nPartId) + EgtRelocateGlob(nFirstId + CountIndex, nLayerId) + EgtModifyCurveThickness(nFirstId + CountIndex, -SheetBBox:getDimZ()) + table.insert(SkeletonLineList, nPartId) + -- lo aggiungo come pezzo al grezzo + EgtAddPartToRawPart(nPartId, + EgtSP(nFirstId + CountIndex) - Point3d(SheetBBox:getMin():getX(), + SheetBBox:getMin():getY(), + SheetBBox:getMax():getZ()), + CurrRawPart) + -- lo lavoro + local NewMachId = EgtAddMachining("SkeletonCut", OutlineMachining[2][1]) + -- applico geometria di lavorazione + EgtSetMachiningGeometry(nFirstId + CountIndex) + EgtSetMachiningParam(MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) + if ToolDiam < dSkeletonCutLength then + EgtSetMachiningParam(MCH_MP.STARTADDLEN , - (ToolDiam / 2) + Config.dSkeletonCut) + EgtSetMachiningParam(MCH_MP.ENDADDLEN , - (ToolDiam / 2) + Config.dSkeletonCut) + else + EgtSetMachiningParam(MCH_MP.STARTADDLEN , (- dSkeletonCutLength + 1) / 2) + EgtSetMachiningParam(MCH_MP.ENDADDLEN , (- dSkeletonCutLength + 1) / 2) + end + -- applico la lavorazione + if not EgtApplyMachining() then + table.insert(ErrorList, {ErrType = "E.7", Uid = "Skeleton separation cut", Description = "Error in horizontal skeleton machining!"}) + end + -- nascondo il pezzo + EgtSetStatus(nFirstId + CountIndex, GDB_ST.OFF) + end + end + -- se altezza riga minore dell'altezza tavola + if Config.bSRMaxHeight < 80 * 25.4 then + -- calcolo rghe della griglia + for RLineIndex = 0, nSRRow - 2 do + local RLineId = EgtLine(nSkeletonGridLayerId, Point3d(SheetBBox:getMin():getX(), + SheetBBox:getMin():getY() + dSRRowSP + (Config.bSRMaxHeight * RLineIndex), + SheetBBox:getMax():getZ()), + Point3d(SheetBBox:getMax():getX(), + SheetBBox:getMin():getY() + dSRRowSP + (Config.bSRMaxHeight * RLineIndex), + SheetBBox:getMax():getZ())) + -- taglio griglia con superficie rimanente + -- int, int EgtTrimCurveWithRegion( int nCrvId, int nRegId, bool bInVsOut, bool bOn) + local nFirstId, nCountId = EgtTrimCurveWithRegion(RLineId, nSkeletonFRId, true, false) + for CountIndex = 0, nCountId - 1 do + local dSkeletonCutLength = math.abs((EgtEP(nFirstId + CountIndex) - EgtSP(nFirstId + CountIndex)):getY()) + local nPartId = EgtGroup(GDB_ID.ROOT) + EgtSetName(nPartId, "SKELETON_" .. nSRColumn + RLineIndex .. "_" .. CountIndex + 1) + local nLayerId = EgtGroup(nPartId) + EgtRelocateGlob(nFirstId + CountIndex, nLayerId) + EgtModifyCurveThickness(nFirstId + CountIndex, -SheetBBox:getDimZ()) + table.insert(SkeletonLineList, nPartId) + -- lo aggiungo come pezzo al grezzo + EgtAddPartToRawPart(nPartId, + EgtSP(nFirstId + CountIndex) - Point3d(SheetBBox:getMin():getX(), + SheetBBox:getMin():getY(), + SheetBBox:getMax():getZ()), + CurrRawPart) + -- lo lavoro + local NewMachId = EgtAddMachining("SkeletonCut", OutlineMachining[2][1]) + -- applico geometria di lavorazione + EgtSetMachiningGeometry(nFirstId + CountIndex) + EgtSetMachiningParam(MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) + if ToolDiam < dSkeletonCutLength then + EgtSetMachiningParam(MCH_MP.STARTADDLEN , - (ToolDiam / 2) + Config.dSkeletonCut) + EgtSetMachiningParam(MCH_MP.ENDADDLEN , - (ToolDiam / 2) + Config.dSkeletonCut) + else + EgtSetMachiningParam(MCH_MP.STARTADDLEN , (- dSkeletonCutLength + 1) / 2) + EgtSetMachiningParam(MCH_MP.ENDADDLEN , (- dSkeletonCutLength + 1) / 2) + end + -- applico la lavorazione + if not EgtApplyMachining() then + table.insert(ErrorList, {ErrType = "E.7", Uid = "Skeleton separation cut", Description = "Error in vertical skeleton machining!"}) + end + -- nascondo il pezzo + EgtSetStatus(nFirstId + CountIndex, GDB_ST.OFF) + end + end + end + end + end + -- aggiorno lavorazioni dopo spostamenti e calcolo remnant + EgtApplyAllMachinings() + -- aggiorno lavorazione un'altra volta per migliorare posizioni eventuali tab + EgtApplyAllMachinings() + if MachId ~= 2 then + -- ricavo stime + local CurrEstimatePath = NestingLib.VerifyPath("Estimate", BatchId, Material) + if not UtilityLib.FolderExists(CurrEstimatePath) then + EgtCreateDirectory(CurrEstimatePath) + end + CurrEstimatePath = CurrEstimatePath .. "/" .. Material.SheetList[Sheet].MachGroupName .. ".html" + EgtEstimate(CurrEstimatePath) + local EstimatedTime = EgtGetInfo(CurrMachGroupId, "Ttot") + if EstimatedTime then + Material.SheetList[Sheet].EstimatedWorktime = EstimatedTime + else + Material.SheetList[Sheet].EstimatedWorktime = 0 + table.insert(ErrorList, {ErrType = "E.7", Uid = "Generic", Description = "Impossible running estimation!"}) + end + -- salvo materiale su foglio + Material.SheetList[Sheet].MatId = Material.MatId + end + -- se nesting finale + if not IsEstimate or (IsEstimate and IsOffline) then + -- salvo file cnc + local CurrCNCPath = NestingLib.VerifyPath("CNC", BatchId, Material, MachId) + local DBCurrCNCPath = NestingLib.VerifyPath("CNC", BatchId, Material, 0) + if not UtilityLib.FolderExists(CurrCNCPath) then + EgtCreateDirectory(CurrCNCPath) + end + CurrPrintCNCPath = CurrCNCPath .. "/" .. Material.SheetList[Sheet].MachGroupName .. "_2.cnc" + -- creo path con estensione diversa per offline e non + if IsOffline then + CurrCNCPath = CurrCNCPath .. "/" .. Material.SheetList[Sheet].MachGroupName .. ".txt" + else + CurrCNCPath = CurrCNCPath .. "/" .. Material.SheetList[Sheet].MachGroupName .. ".cnc" + end + if MachId == 2 then + Material.SheetList[Sheet].MachiningProgram = DBCurrCNCPath .. "/" .. Material.SheetList[Sheet].MachGroupName .. ".cnc" + else + Material.SheetList[Sheet].MachiningProgram = CurrCNCPath + end + local bOk = EgtGenerate(CurrCNCPath) +-- if not bOk then +-- table.insert(ErrorList, {ErrType = "E.7", Uid = "Program generation", Description = "Error in program generation!"}) +-- return +-- end + -- se non offline, genero file di stampa + if not IsOffline then + -- salvo file cnc print + local CurrPrintPath = NestingLib.VerifyPath("CNC_PRINT", BatchId, Material, MachId) + local DBCurrPrintPath = NestingLib.VerifyPath("CNC_PRINT", BatchId, Material, 0) + if not UtilityLib.FolderExists(CurrPrintPath) then + EgtCreateDirectory(CurrPrintPath) + end + CurrPrintPath = CurrPrintPath .. "/" .. Material.SheetList[Sheet].MachGroupName .. ".cnc" + if MachId == 2 then + Material.SheetList[Sheet].PrintProgram = DBCurrPrintPath .. "/" .. Material.SheetList[Sheet].MachGroupName .. ".cnc" + else + Material.SheetList[Sheet].PrintProgram = CurrPrintPath + end + bOk = EgtCopyFile(CurrPrintCNCPath, CurrPrintPath) + bOk = EgtEraseFile(CurrPrintCNCPath) + end + if MachId ~= 2 then + -- salvo svg del grezzo + local CurrSVGPath = NestingLib.VerifyPath("SVG", BatchId, Material) + if not UtilityLib.FolderExists(CurrSVGPath) then + EgtCreateDirectory(CurrSVGPath) + end + -- salvo disegni tavola + CurrSVGPath = CurrSVGPath .. "/".. Material.SheetList[Sheet].MachGroupName .. ".svg" + -- creo file svg + EgtSetMachineLook( MCH_LOOK.TAB) + bOk = EgtExportSvg( GDB_ID.ROOT, CurrSVGPath, 447) + if bOk then + Material.SheetList[Sheet].Drawing = CurrSVGPath + else + Material.SheetList[Sheet].Drawing = "" + end + -- creo svg per ristampa etichette + CreateSvgForLabelPrint(CurrSVGPath, Material.SheetList[Sheet].MachGroupName, BatchId, Material) + end + end + end +end +-- + +-- funzione che modifica svg inserendo codici qr per ristampa etichette +function CreateSvgForLabelPrint(SVGPath, MachGroupName, BatchId, Material) + -- apertura file con controllo + local fh = io.open( SVGPath, 'r') + if not fh then + -- errore + return + end + -- lettura di tutte le linee del file + local Lines = {} + local OneLine = fh:read( '*l') + while OneLine do + table.insert( Lines, OneLine) + OneLine = fh:read( '*l') + end + fh:close() + -- array delle immagini qr da aggiungere alla fine + local QrList = {} + -- ciclo sulle linee + for i = 1, #Lines do + local _, _, PartDtmx, dX, dY = string.find(Lines[i], "%s*") + if PartDtmx or dX or dY then + table.insert(QrList, " ") + end + local _, _, SVGEnd = string.find(Lines[i], "%s*().*") + if i == 458 then + local x = 0 + end + if SVGEnd then + for i2 = 1, #QrList do + table.insert(Lines, i + i2 - 1, QrList[i2]) + end + end +-- local _, _, PartDtmx, dX, dY = string.find(Lines[i], "%s*") +-- if PartDtmx or dX or dY then +-- Lines[i] = " " +-- end +-- local _, _, BinCartIndex = string.find(Lines[i], "%s*(%a%d*)") +-- if BinCartIndex then +-- Lines[i] = "" +-- end +end + -- creo path in cui salvare csv per etichette + local LabelSVGPath = "" + -- se offline + if IsOffline then + LabelSVGPath = NestingLib.VerifyPath("SVG", BatchId, nil) + -- salvo cartella + Material.OfflineDrawingFolder = LabelSVGPath .. "/" + if not UtilityLib.FolderExists(LabelSVGPath) then + EgtCreateDirectory(LabelSVGPath) + end + LabelSVGPath = LabelSVGPath .. "/" .. Material.MatId .. "_" .. MachGroupName .. "_qr.svg" + else + LabelSVGPath = NestingLib.VerifyPath("SVG", BatchId, Material) + if not UtilityLib.FolderExists(LabelSVGPath) then + EgtCreateDirectory(LabelSVGPath) + end + LabelSVGPath = LabelSVGPath .. "/".. MachGroupName .. "_qr.svg" + end + -- scrittura delle linee modificate + local fh2 = io.open( LabelSVGPath, 'w') + for i = 1, #Lines do + fh2:write( Lines[i] .. '\n') + end + fh2:close() + -- fine +end + +-- funzione che crea le lavorazioni raggruppandole per tipologia ed ordinando i pezzi +function CreateMachByOrderedType(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, ErrorList) + -- chiamo funzione che lavora per tipologia dicendogli di considerare tutte le lavorazioni tranne i contorni + local PartsArea = CreateMachByType(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, 3, ErrorList) + -- chiamo funzione che lavora pezzi ordinati dicendogli di considerare solo i contorni + CreateMachByPart(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, 2, ErrorList) + return PartsArea +end + +-- funzione che crea le lavorazioni raggruppandole per tipologia +function CreateMachByType(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, nMachType, ErrorList) + local PartsArea = 0 + -- liste lavorazioni divise per tipo ed utensile per ottimizzazione algoritmo tsp +-- local OutlineList = {} +-- local SmallOutlineList = {} +-- local IntIntOutlineList = {} +-- local SkinOutlineList = {} +-- local IntExtOutlineList = {} +-- local InternalOutlineList = {} +-- local PocketingList = {} +-- local RampList = {} +-- local HoleList = {} +-- for HoleMach = 1, (#HoleMachining[2] + #Pocketing) do +-- table.insert(HoleList, {}) +-- end + -- Recupero pezzi con possibili pezzi interni e ne calcolo il BBox + local IntPathParts = {} + local CurrPart = EgtGetFirstPartInRawPart(CurrRawPart) + while CurrPart do + if EgtGetInfo(CurrPart, INTPART, "d") == 1 then + local LayerId = EgtGetFirstGroupInGroup(CurrPart) + while LayerId do + local layerName = EgtGetName(LayerId) + local bOutline = false + -- verifico se ha un nome di outline + for Mach = 1, #OutlineMachining[1] do + if layerName == OutlineMachining[1][Mach] then + bOutline = true + end + end + if bOutline then + -- ciclo sui percorsi + local PathId = EgtGetFirstInGroup(LayerId) + while PathId do + -- se è percorso interno con possibili pezzi + if EgtGetInfo(PathId, INTPART, "d") == 1 then + -- ne creo il bbox + local b3IntPathPart = EgtGetBBoxGlob(PathId, 13) + table.insert(IntPathParts, {PartId = CurrPart, PathId = PathId, BBox = b3IntPathPart}) + end + PathId = EgtGetNext(PathId) + end + end + LayerId = EgtGetNextGroup(LayerId) + end + end + -- passo al pezzo successivo + CurrPart = EgtGetNextPartInRawPart(CurrPart) + end + -- applico lavorazioni ai gruppi di lavorazione +-- local CurrRawPart = EgtGetFirstRawPart() +-- local CurrPart = EgtGetFirstPartInRawPart(CurrRawPart) + CurrPart = EgtGetFirstPartInRawPart(CurrRawPart) + local bMachOk = true + local LastMch = GDB_ID.NULL + ResetSPMachList() + while CurrPart do + -- calcolo BBox part e lo aggiungo al globale per calcolo remnant + local CurrPartBBox = EgtGetBBoxGlob(CurrPart, GDB_BB.STANDARD + GDB_BB.ONLY_VISIBLE + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM) + if CurrPartBBox and not CurrPartBBox:isEmpty() then + if not PartsBBox:Add( CurrPartBBox) then + local x = 2 + end + + else + local x = 2 + end + -- calcolo area totale occupata + local CutPartsArea = EgtGetFirstNameInGroup(nSkeletonLayerId, PARTCUTSUM) + local OutlineLayer = EgtGetFirstNameInGroup(CurrPart, OUTLINE) + local nPartSurfId = EgtGetFirstNameInGroup(OutlineLayer, EgtGetName(CurrPart)) + if nPartSurfId ~= GDB_ID.NULL then + if not CutPartsArea or CutPartsArea == GDB_ID.NULL then + CutPartsArea = EgtCopyGlob(nPartSurfId, nSkeletonLayerId) + EgtSetName(CutPartsArea, PARTCUTSUM) + else + if not nPartSurfId then + x = 2 + end + EgtSurfFrAdd(CutPartsArea, nPartSurfId) + end + end + local nTrakSurfId = EgtGetFirstNameInGroup(OutlineLayer, SKELETONTRACK) + while nTrakSurfId and nTrakSurfId ~= GDB_ID.NULL do + if not CutPartsArea or CutPartsArea == GDB_ID.NULL then + CutPartsArea = EgtCopyGlob(nTrakSurfId, nSkeletonLayerId) + EgtSetName(CutPartsArea, PARTCUTSUM) + else + EgtSurfFrAdd(CutPartsArea, nTrakSurfId) + end + nTrakSurfId = EgtGetNextName(nTrakSurfId, SKELETONTRACK) + end + -- lo confronto con bbox percorsi interni per verificare se e' un pezzo interno + local Index = 1 + local bIntPathFound = false + local bInternalPart = false + while Index < #IntPathParts and not bIntPathFound do + if EnclosesXY(IntPathParts[Index].BBox, CurrPartBBox) then + bIntPathFound = true + bInternalPart = true + end + Index = Index + 1 + end + CalcPartMachinings(Material, CurrPart, bInternalPart, LastMch, nMachType, bDoCalc, ErrorList) + -- recupero e sommo aree di tutti i pezzi sul foglio + local CurrArea = EgtGetInfo(CurrPart, AREA) + PartsArea = PartsArea + CurrArea + -- segno priorita' pezzo su lista delle priorita' del foglio + local PartPriority = EgtGetInfo(CurrPart, PRIORITY) + local bFound = false + for PriorityIndex = 0, #PartsPriority do + if PartPriority == PartsPriority[PriorityIndex] then + bFound = true + end + end + if not bFound then + table.insert(PartsPriority, PartPriority) + end + -- passo al pezzo successivo + CurrPart = EgtGetNextPartInRawPart(CurrPart) + end + -- ordino lavorzioni con algoritmo ts + ProcessMachinings(HoleList, RampList, PocketingList, IntIntOutlineList, SkinOutlineList, IntExtOutlineList, InternalOutlineList, SmallOutlineList, OutlineList) + return PartsArea +end + + + +-- funzione che crea le lavorazioni raggruppandole per pezzo +-- nMachType -> 1: All ; 2: only outline ; 3 all away from outline +function CreateMachByPart(Material, CurrRawPart, PartsBBox, nSkeletonLayerId, PartsPriority, nMachType, ErrorList) + local PartsArea = 0 + -- lista pezzi per lavorazioni + local VerySmallMachPartList = {} + local SmallMachPartList = {} + local MediumMachPartList = {} + local MachPartList = {} + -- Recupero pezzi con possibili pezzi interni e ne calcolo il BBox + local CurrPart = EgtGetFirstPartInRawPart(CurrRawPart) + while CurrPart do + if EgtGetInfo(CurrPart, INTPART, "d") == 1 then + local LayerId = EgtGetFirstGroupInGroup(CurrPart) + local bOutline = false + while LayerId and not bOutline do + local layerName = EgtGetName(LayerId) + -- verifico se ha un nome di outline + for Mach = 1, #OutlineMachining[1] do + if layerName == OutlineMachining[1][Mach] then + bOutline = true + end + end + if bOutline then + -- ciclo sui percorsi + local bIntPart = false + local PathId = EgtGetFirstInGroup(LayerId) + while PathId do + -- se è percorso interno con possibili pezzi + if EgtGetInfo(PathId, INTPART, "d") == 1 then + bIntPart = true + -- ne creo il bbox + local b3IntPathPart = EgtGetBBoxGlob(PathId, 13) + if not bIntPart then + table.insert(MachPartList, {PartId = CurrPart, IntPathId = PathId, BBox = b3IntPathPart, bIntParts = true, IntPartList = {}}) + end + end + PathId = EgtGetNext(PathId) + end + end + LayerId = EgtGetNextGroup(LayerId) + end + end + -- recupero e sommo aree di tutti i pezzi sul foglio + local CurrArea = EgtGetInfo(CurrPart, AREA) + PartsArea = PartsArea + CurrArea + -- segno priorita' pezzo su lista delle priorita' del foglio + local PartPriority = EgtGetInfo(CurrPart, PRIORITY) + local bFound = false + for PriorityIndex = 0, #PartsPriority do + if PartPriority == PartsPriority[PriorityIndex] then + bFound = true + end + end + if not bFound then + table.insert(PartsPriority, PartPriority) + end + -- passo al pezzo successivo + CurrPart = EgtGetNextPartInRawPart(CurrPart) + end + -- ciclo sui pezzi per inserirli nella lista + CurrPart = EgtGetFirstPartInRawPart(CurrRawPart) + while CurrPart do + -- calcolo area totale occupata +-- local CutPartsArea = EgtGetFirstNameInGroup(nSkeletonLayerId, PARTCUTSUM) +-- local OutlineLayer = EgtGetFirstNameInGroup(CurrPart, OUTLINE) +-- local nPartSurfId = EgtGetFirstNameInGroup(OutlineLayer, EgtGetName(CurrPart)) +-- local nTrakSurfId = EgtGetFirstNameInGroup(OutlineLayer, TOOLTRACK) +-- if nPartSurfId ~= GDB_ID.NULL then +-- if not CutPartsArea or CutPartsArea == GDB_ID.NULL then +-- CutPartsArea = EgtCopy(nPartSurfId, nSkeletonLayerId) +-- EgtSetName(CutPartsArea, PARTCUTSUM) +-- else +-- EgtSurfFrAdd(CutPartsArea, nPartSurfId) +-- end +-- end +-- if nTrakSurfId ~= GDB_ID.NULL then +-- if not CutPartsArea or CutPartsArea == GDB_ID.NULL then +-- CutPartsArea = EgtCopy(nTrakSurfId, nSkeletonLayerId) +-- EgtSetName(CutPartsArea, PARTCUTSUM) +-- else +-- EgtSurfFrAdd(CutPartsArea, nTrakSurfId) +-- end +-- end + -- calcolo BBox part e lo aggiungo al globale per calcolo remnant + local CurrPartBBox = EgtGetBBoxGlob(CurrPart, GDB_BB.STANDARD + GDB_BB.ONLY_VISIBLE + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM) + -- lo aggiungo a bbox generico per calcolo remnant + PartsBBox:Add( CurrPartBBox) + -- lo confronto con bbox percorsi interni per verificare se e' un pezzo interno + local Index = 1 + local bIntPathFound = false + local bExtPathFound = false + while Index < #MachPartList and not bExtPathFound and not bIntPathFound do + -- se già in lista perchè può contenere interni, lo segno per saltarlo + if MachPartList[Index].PartId == CurrPart then + bExtPathFound = true + end + if MachPartList[Index].bIntParts and EnclosesXY(MachPartList[Index].BBox, CurrPartBBox) then + table.insert(MachPartList[Index].IntPartList, {PartId = CurrPart, BBox = CurrPartBBox}) + bIntPathFound = true + end + Index = Index + 1 + end + -- se non può avere interni e non è interno, lo aggiungo alla lista + if not bExtPathFound and not bIntPathFound then + -- se pezzo piccolo + local dGeomArea = EgtGetInfo(CurrPart, AREA, 'd') + local dMinSideArea = CurrPartBBox:getDimX() + if CurrPartBBox:getDimY() < dMinSideArea then + dMinSideArea = CurrPartBBox:getDimY() + end + if dGeomArea < Config.dVerySmallPartArea then + table.insert(VerySmallMachPartList, {PartId = CurrPart, BBox = CurrPartBBox, bIntParts = false}) + elseif dGeomArea < Config.dSmallPartArea or dMinSideArea < Config.dSmallPartSide then + table.insert(SmallMachPartList, {PartId = CurrPart, BBox = CurrPartBBox, bIntParts = false}) + elseif dGeomArea < Config.dMediumPartArea then + table.insert(MediumMachPartList, {PartId = CurrPart, BBox = CurrPartBBox, bIntParts = false}) + else + table.insert(MachPartList, {PartId = CurrPart, BBox = CurrPartBBox, bIntParts = false}) + end + end + -- passo al pezzo successivo + CurrPart = EgtGetNextPartInRawPart(CurrPart) + end + -- ordino liste pezzi + VerySmallMachPartList = SortParts(VerySmallMachPartList, false) + SmallMachPartList = SortParts(SmallMachPartList, false) + MediumMachPartList = SortParts(MediumMachPartList, true) + MachPartList = SortParts(MachPartList, true) + local LastMch = GDB_ID.NULL + -- lavoro pezzi molto piccoli + for CurrPart = 1, #VerySmallMachPartList do + -- ne calcolo le lavorazioni + LastMch = CalcPartMachinings(Material, VerySmallMachPartList[CurrPart].PartId, false, LastMch, nMachType, true, ErrorList) + end + -- lavoro pezzi piccoli + for CurrPart = 1, #SmallMachPartList do + -- ne calcolo le lavorazioni + LastMch = CalcPartMachinings(Material, SmallMachPartList[CurrPart].PartId, false, LastMch, nMachType, true, ErrorList) + end + -- lavoro pezzi medi + for CurrPart = 1, #MediumMachPartList do + -- ne calcolo le lavorazioni + LastMch = CalcPartMachinings(Material, MediumMachPartList[CurrPart].PartId, false, LastMch, nMachType, true, ErrorList) + end + -- ciclo per ordinare i pezzi interni + for CurrPart = 1, #MachPartList do + -- se ci sono pezzi interni + if MachPartList[CurrPart].bIntParts then + -- li ordino + MachPartList[CurrPart].IntPartList = SortParts(MachPartList[CurrPart].IntPartList, true) + -- ciclo su questi + for CurrIntPart = 1, #MachPartList[CurrPart].IntPartList do + -- ne calcolo le lavorazioni + LastMch = CalcPartMachinings(Material, MachPartList[CurrPart].IntPartList[CurrIntPart].PartId, true, LastMch, nMachType, true, ErrorList) + end + end + -- ne calcolo le lavorazioni + LastMch = CalcPartMachinings(Material, MachPartList[CurrPart].PartId, true, LastMch, nMachType, true, ErrorList) + end + return PartsArea +end + +-- funzione che resetta le liste lavorazioni +function ResetSPMachList() + OutlineList = {} + SmallOutlineList = {} + IntIntOutlineList = {} + SkinOutlineList = {} + IntExtOutlineList = {} + InternalOutlineList = {} + PocketingList = {} + RampList = {} + HoleList = {} + for HoleMach = 1, (#HoleMachining[2] + #Pocketing) do + table.insert(HoleList, {}) + end +end + +-- funzione che crea le lavorazioni raggruppandole per pezzo +-- nMachType -> 1: All ; 2: only outline ; 3 all away from outline +-- bDoCalc -> se vero avvia algoritmo Sp, altrimenti raggruppa solo tutte le lavorazioni presenti nel pezzo +function CalcPartMachinings(Material, CurrPart, bInternalPart, LastMch, nMachType, bDoCalc, ErrorList) + if bDoCalc then + ResetSPMachList() + end + -- cerco tra i nomi di outline + for OutMach = 1, #OutlineMachining[1] do + local CurrLayer = EgtGetFirstNameInGroup(CurrPart, OutlineMachining[1][OutMach]) + -- se ne trovo uno valido + if CurrLayer then + -- aggiungo lavorazioni + local CurrGeom = EgtGetFirstInGroup(CurrLayer) + while CurrGeom do + -- verifico spessore + local Depth = EgtCurveThickness(CurrGeom) +-- if -Depth >= (Material.T_mm - Config.ThicknessTolerance) and -Depth <= (Material.T_mm + Config.ThicknessTolerance) then + if -Depth >= (Material.T_mm - Config.ThicknessTolerance) then + -- verifico se e' outline + local bValidOutlineMach = false + local MachToDo = false + local GeomName = EgtGetName(CurrGeom) + local CurrGeomColor = EgtGetCalcColor(CurrGeom) + if GeomName == OUTLINE then + if nMachType == 1 or nMachType == 2 then + MachToDo = true + for OutlineMachIndex = 1, #OutlineMachining[2] do + if not bValidOutlineMach then + local NewMachId = EgtAddMachining(OutlineMachining[1][OutMach], OutlineMachining[2][OutlineMachIndex]) + EgtSetMachiningGeometry(CurrGeom) + local nOutlineLayerId = EgtGetFirstNameInGroup(CurrPart, OUTLINE) + local nCurrMode = 0 + if EgtGetInfo(nOutlineLayerId, CUTOPT) == "TAB" then + nCurrMode = 2 + elseif EgtGetInfo(nOutlineLayerId, CUTOPT) == "SKIN" then + nCurrMode = 1 + elseif EgtGetInfo(nOutlineLayerId, CUTOPT) == "SKELETON" then + nCurrMode = 3 + elseif EgtGetInfo(nOutlineLayerId, CUTOPT) == "SKELETON&TAB" then + nCurrMode = 4 + end + local dGeomArea = EgtGetInfo(CurrPart, AREA, 'd') + if nCurrMode == 0 and dGeomArea < Config.dSkelSkinTab_MaxArea then + nCurrMode = Config.nSkelSkinTabMode + end + -- se modalità skin + if nCurrMode == 1 then + local SkinMachId = EgtAddMachining(OutlineMachining[1][OutMach], OutlineMachining[2][OutlineMachIndex]) + EgtSetMachiningGeometry(CurrGeom) + -- abilito tab + EgtSetMachiningParam(MCH_MP.DEPTH_STR, "TH-" .. dSkinThickness) + -- applico la lavorazione principale sopraelevata + if EgtApplyMachining() then + InitInTSP(SkinMachId, SkinOutlineList, 0) + end + -- rendo corrente lavorazione principale + EgtSetCurrMachining(NewMachId) + -- se modalità tab o skeleton&tab + elseif nCurrMode == 2 or nCurrMode == 4 then + -- abilito tab + EgtSetMachiningParam(MCH_MP.LEAVETAB, true) + EgtSetMachiningParam(MCH_MP.FEED, 8000) + for CurrMat = 1, #Config.TabParams do + if Config.TabParams[CurrMat].MatExtCode == Material.MatExtCode then + EgtSetMachiningParam(MCH_MP.TABLEN, Config.TabParams[CurrMat].Length) + EgtSetMachiningParam(MCH_MP.TABHEIGHT, Config.TabParams[CurrMat].Height) + EgtSetMachiningParam(MCH_MP.TABANGLE, Config.TabParams[CurrMat].Angle) + EgtSetMachiningParam(MCH_MP.TABDIST, Config.TabParams[CurrMat].Distance) + EgtSetMachiningParam(MCH_MP.TABMAX, Config.TabParams[CurrMat].MaxCount) + EgtSetMachiningParam(MCH_MP.TABMIN, Config.TabParams[CurrMat].MinCount) + end + end +-- if dGeomArea < 32 then -- 3225 then +-- EgtSetMachiningParam(MCH_MP.FEED, 8000) +-- EgtSetMachiningParam(MCH_MP.TABMIN, 2) +-- EgtSetMachiningParam(MCH_MP.TABMAX, 3) +-- EgtSetMachiningParam(MCH_MP.TABDIST, 60) +-- elseif dGeomArea < 11612 then +-- EgtSetMachiningParam(MCH_MP.FEED, 8000) +-- EgtSetMachiningParam(MCH_MP.TABMIN, 0) --2) +-- EgtSetMachiningParam(MCH_MP.TABMAX, 16) --4) +-- EgtSetMachiningParam(MCH_MP.TABDIST, 10000) --100) +-- else +-- EgtSetMachiningParam(MCH_MP.TABMIN, 0) --2) +-- EgtSetMachiningParam(MCH_MP.TABMAX, 16) --4) +-- EgtSetMachiningParam(MCH_MP.TABDIST, 10000) --100) +-- end + else + EgtSetMachiningParam(MCH_MP.LEAVETAB, true) + EgtSetMachiningParam(MCH_MP.TABMIN, 0) + EgtSetMachiningParam(MCH_MP.TABMAX, 16) + EgtSetMachiningParam(MCH_MP.TABDIST, 30000) + end + -- se pezzo piccolo + if Config.bSmallFeedReduce and dGeomArea < 11612 then -- 3225 then + EgtSetMachiningParam(MCH_MP.FEED, Config.dSmallFeed) + end + -- applico la lavorazione + if EgtApplyMachining() then + bValidOutlineMach = true + if bInternalPart then + InitInTSP(NewMachId, IntExtOutlineList, 0) + elseif dGeomArea < Config.dSkelSkinTab_MaxArea then + InitInTSP(NewMachId, SmallOutlineList, 0) + else + InitInTSP(NewMachId, OutlineList, 0) + end + EgtSetMachiningParam(MCH_MP.USERNOTES,'Outline = 1') + else + EgtRemoveOperation(NewMachId) + end + end + end + end + elseif AreSameColor(Config.colPocketingPaths, CurrGeomColor, 10) then -- EgtCurveIsACircle(CurrGeom) then + if nMachType == 1 or nMachType == 3 then + MachToDo = true + for PocketingIndex = 1, #Pocketing do + if not bValidOutlineMach then + local NewMachId = EgtAddMachining(Pocketing[PocketingIndex], Pocketing[PocketingIndex]) + EgtSetMachiningGeometry(CurrGeom) + -- applico la lavorazione + if EgtApplyMachining() then + bValidOutlineMach = true + InitInTSP(NewMachId, PocketingList, 0) + else + EgtRemoveOperation(NewMachId) + end + end + end + end + else + -- percorso interno + if nMachType == 1 or nMachType == 2 then + MachToDo = true + for OutlineMachIndex = 1, #OutlineMachining[2] do + if not bValidOutlineMach then + local NewMachId = EgtAddMachining(OutlineMachining[1][OutMach], OutlineMachining[2][OutlineMachIndex]) + EgtSetMachiningGeometry(CurrGeom) +-- if EgtGetInfo(CurrPart, AREA, 'd') < Config.dSkelSkinTab_MaxArea then + EgtSetMachiningParam(MCH_MP.LEAVETAB, true) + EgtSetMachiningParam(MCH_MP.TABMIN, 0) + EgtSetMachiningParam(MCH_MP.TABMAX, 16) + EgtSetMachiningParam(MCH_MP.TABDIST, 30000) +-- end + -- applico la lavorazione + if EgtApplyMachining() then + bValidOutlineMach = true + if bInternalPart then + InitInTSP(NewMachId, IntIntOutlineList, 0) + else + InitInTSP(NewMachId, InternalOutlineList, 0) + end + else + EgtRemoveOperation(NewMachId) + end + end + end + end + end + if MachToDo and not bValidOutlineMach then + local PartId = EgtGetInfo(CurrPart, PARTID) + if not PartId then PartId = "" end + table.insert(ErrorList, {ErrType = "E.7", Uid = "PartId = " .. PartId, Description = "Error in outline machining!"}) + end + -- se spessore pezzo è maggiore del materiale do errore + if -Depth >= (Material.T_mm + Config.ThicknessTolerance) then + local PartId = EgtGetInfo(CurrPart, PARTID) + if not PartId then PartId = "" end + table.insert(ErrorList, {ErrType = "E.7", Uid = "PartId = " .. PartId, Description = "Error in machining! Part(" .. -Depth .. ") thicker than material(" .. Material.T_mm .. ")"}) + end + else + if nMachType == 1 or nMachType == 3 then + local bValidPocketing = false + for PocketingIndex = 1, #Pocketing do + if not bValidPocketing then + local NewMachId = EgtAddMachining(Pocketing[PocketingIndex], Pocketing[PocketingIndex]) + EgtSetMachiningGeometry(CurrGeom) + -- applico la lavorazione + if EgtApplyMachining() then + bValidPocketing = true + InitInTSP(NewMachId, PocketingList, 0) + else + EgtRemoveOperation(NewMachId) + end + end + end + if not bValidPocketing then + local PartId = EgtGetInfo(CurrPart, PARTID) + if not PartId then PartId = "" end + table.insert(ErrorList, {ErrType = "E.7", Uid = "PartId = " .. PartId, Description = "Error in machining!"}) + end + end + end + CurrGeom = EgtGetNext(CurrGeom) + end + end + end + if nMachType == 1 or nMachType == 3 then + -- cerco layer fori + local HoleLayer = EgtGetFirstNameInGroup(CurrPart, HoleMachining[1]) + -- se lo trovo + if HoleLayer then + -- verifico le geometrie presenti + local CurrGeom = EgtGetFirstInGroup(HoleLayer) + while CurrGeom do + if EgtGetType(CurrGeom) == GDB_TY.CRV_ARC then + local OperationName = "" + local MachName = "" + -- variabile necessaria per differenziare le varie forature e pocketing + local HoleMachIndex = 0 + local CurrRad = EgtArcRadius(CurrGeom) + for HoleMach = 1, #HoleMachining[2] do + if EgtMdbSetCurrMachining(HoleMachining[2][HoleMach]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + local ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + if ToolDiam and ToolDiam > 0 then + if CurrRad * 2 <= ToolDiam + (GEO.EPS_SMALL * 1000 * Config.HoleTolerance) and + CurrRad * 2 >= ToolDiam - (GEO.EPS_SMALL * 1000 * Config.HoleTolerance) then + MachName = HoleMachining[2][HoleMach] + OperationName = HoleMachining[1] + HoleMachIndex = HoleMach + end + end + end + end + -- se non ho trovato una punta per farlo + if MachName == "" and (CurrRad * 2) > 6.35 then +-- -- prendo il pocketing con diametro più grande tra quelli più piccoli del foro +-- local DiamOffset = 100 +-- for PocketingIndex = 1, #Pocketing do +-- if EgtMdbSetCurrMachining(Pocketing[PocketingIndex]) then +-- local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) +-- EgtTdbSetCurrTool(ToolName) +-- local ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) +-- if ToolDiam and ToolDiam > 0 then +-- local CurrOffset = (CurrRad * 2) - ToolDiam +-- if CurrOffset > 0 and CurrOffset < DiamOffset then +-- MachName = Pocketing[PocketingIndex] +-- OperationName = Pocketing[PocketingIndex] +-- HoleMachIndex = #HoleMachining[2] + PocketingIndex +-- DiamOffset = CurrOffset +-- end +-- end +-- end +-- end + -- provo a fare il pocketing con diametro 1/4 + for PocketingIndex = 1, #Pocketing do + if EgtMdbSetCurrMachining(Pocketing[PocketingIndex]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + local ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + if ToolDiam and ToolDiam > 0 and 6.35 <= ToolDiam + (GEO.EPS_SMALL * 10) and 6.35 >= ToolDiam - (GEO.EPS_SMALL * 10) then + MachName = Pocketing[PocketingIndex] + OperationName = Pocketing[PocketingIndex] + HoleMachIndex = #HoleMachining[2] + PocketingIndex + end + end + end + end + -- se non ho trovato nemmeno un pocketing per farlo + if MachName == "" then + -- faccio un foro da 1/8 + for HoleMach = 1, #HoleMachining[2] do + if EgtMdbSetCurrMachining(HoleMachining[2][HoleMach]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + local ToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + if ToolDiam and ToolDiam > 0 and 3.175 <= ToolDiam + (GEO.EPS_SMALL * 10) and 3.175 >= ToolDiam - (GEO.EPS_SMALL * 10) then + MachName = HoleMachining[2][HoleMach] + OperationName = HoleMachining[1] + HoleMachIndex = HoleMach + end + end + end + end + if MachName ~= "" then + local NewMachId = EgtAddMachining(OperationName, MachName) + EgtSetMachiningGeometry(CurrGeom) + -- applico la lavorazione + if not EgtApplyMachining() then + table.insert(ErrorList, {ErrType = "E.7", Uid = "Generic", Description = "Error in hole machining!"}) + else + InitInTSP(NewMachId, HoleList, HoleMachIndex) + end + end + end + CurrGeom = EgtGetNext(CurrGeom) + end + end + -- cerco layer rampe + local RampLayer = EgtGetFirstNameInGroup(CurrPart, RampMachining[1]) + -- se lo trovo + if RampLayer then + -- verifico le geometrie presenti + local CurrGeom = EgtGetFirstInGroup(RampLayer) + while CurrGeom do + -- se non e' gia' percorso di lavorazione + if not EgtGetInfo(CurrGeom, MACHPATH) then + -- se e' curva composita + if EgtGetType(CurrGeom) == GDB_TY.CRV_COMPO then + -- creo percorso di lavorazione + local MachRampGeom = EgtCopyGlob(CurrGeom, RampLayer) + local nMachPath = CreateRampMachPath(MachRampGeom, RampLayer) + local bValidOutlineMach = false + if nMachPath and nMachPath ~= GDB_ID.NULL then + local NewMachId = EgtAddMachining(RampMachining[1], RampMachining[2]) + EgtSetMachiningGeometry(nMachPath) + EgtSetMachiningParam(MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) + EgtSetMachiningParam(MCH_MP.INVERT, false) + -- applico la lavorazione + if EgtApplyMachining() then + bValidOutlineMach = true + InitInTSP(NewMachId, InternalOutlineList, 0) + end + if not bValidOutlineMach then + local PartId = EgtGetInfo(CurrPart, PARTID) + if not PartId then PartId = "" end + table.insert(ErrorList, {ErrType = "E.7", Uid = "PartId = " .. PartId, Description = "Error in ramp machining!"}) + end + end + end + end + CurrGeom = EgtGetNext(CurrGeom) + end + end + end + if bDoCalc then + -- ordino lavorzioni con algoritmo ts + return ProcessMachinings(HoleList, RampList, PocketingList, IntIntOutlineList, SkinOutlineList, IntExtOutlineList, InternalOutlineList, SmallOutlineList, OutlineList, LastMch) + end +end + +-- funzione che crea i percorsi di lavorazione per le rampe +function CreateRampMachPath(CurrGeom, RampLayer) + -- rendo il percorso antiorario + if EgtCurveAreaXY(CurrGeom) < 0 then + EgtInvertCurve(CurrGeom) + end + -- riconosco i vari segmenti + local nFirstLine, nLines = EgtExplodeCurveCompo(CurrGeom) + local nTopBorder = 0 + local dTopZ = 0 + local nBottomBorder = 0 + local nLeftBorder = 0 + local nRightBorder = 0 + for LineIndex = 0, nLines - 1 do + local dDeltaZ = EgtEP(nFirstLine + LineIndex):getZ() - EgtSP(nFirstLine + LineIndex):getZ() + if abs(dDeltaZ) < 10 * GEO.EPS_SMALL then + if nTopBorder == 0 then + nTopBorder = nFirstLine + LineIndex + dTopZ = EgtEP(nFirstLine + LineIndex):getZ() + elseif EgtEP(nFirstLine + LineIndex):getZ() > dTopZ then + nBottomBorder = nTopBorder + nTopBorder = nFirstLine + LineIndex + else + nBottomBorder = nFirstLine + LineIndex + end + elseif dDeltaZ < 0 then + nLeftBorder = nFirstLine + LineIndex + elseif dDeltaZ > 0 then + nRightBorder = nFirstLine + LineIndex + end + end + -- recupero diametro utensile di lavorazione + local dToolDiam = 0 + if EgtMdbSetCurrMachining(RampMachining[2]) then + local ToolName = EgtMdbGetCurrMachiningParam(MCH_MP.TOOL) + EgtTdbSetCurrTool(ToolName) + dToolDiam = EgtTdbGetCurrToolParam(MCH_TP.DIAM) + end + -- verifico quante passate servono + local nDiamInLength = EgtCurveLength(nTopBorder) / (dToolDiam - (10 * GEO.EPS_SMALL)) + local nMachinePaths = 0 + if nDiamInLength >= 1 then + nMachinePaths = math.ceil(EgtCurveLength(nTopBorder) / (dToolDiam - (10 * GEO.EPS_SMALL))) + end + local dDeltaPaths = 0 + if nMachinePaths > 1 then + dDeltaPaths = (EgtCurveLength(nTopBorder) - dToolDiam) / (nMachinePaths - 1) + end + -- creo le passate aggiuntive come copie e le posiziono + local vtDirection = (EgtEP(nRightBorder) - EgtSP(nLeftBorder)) + vtDirection:normalize() + local ptLast + local nCompoPath = 0 + if nMachinePaths >=1 then + for PathIndex = 0, nMachinePaths - 1 do + if PathIndex % 2 == 0 then + if PathIndex == 0 then + local nPath = EgtCopy(nLeftBorder, nLeftBorder, GDB_IN.AFTER) + EgtMove(nPath, vtDirection * dToolDiam / 2) + -- creo curva composita + nCompoPath = EgtCurveCompo(RampLayer, nPath) + ptLast = EgtEP(nPath) + else + local nPath = EgtCopy(nLeftBorder, nLeftBorder, GDB_IN.AFTER) + EgtMove(nPath, (vtDirection * dToolDiam / 2) + (vtDirection * dDeltaPaths * PathIndex / 2)) + -- creo collegamento e lo aggiungo a composita + local nLinkPath = EgtLine(RampLayer, ptLast, EgtSP(nPath)) + -- fisso punto finale per prossimo collegamento + ptLast = EgtEP(nPath) + EgtAddCurveCompoCurve(nCompoPath, nLinkPath) + EgtAddCurveCompoCurve(nCompoPath, nPath) + end + else + if PathIndex == 1 then + local nPath = EgtCopy(nRightBorder, nRightBorder, GDB_IN.AFTER) + EgtMove(nPath, -vtDirection * dToolDiam / 2) + -- creo collegamento e lo aggiungo a composita + local nLinkPath = EgtLine(RampLayer, ptLast, EgtSP(nPath)) + -- fisso punto finale per prossimo collegamento + ptLast = EgtEP(nPath) + EgtAddCurveCompoCurve(nCompoPath, nLinkPath) + EgtAddCurveCompoCurve(nCompoPath, nPath) + else + local nPath = EgtCopy(nRightBorder, nRightBorder, GDB_IN.AFTER) + EgtMove(nPath, -((vtDirection * dToolDiam / 2) + (vtDirection * dDeltaPaths * (PathIndex - 1) / 2))) + -- creo collegamento e lo aggiungo a composita + local nLinkPath = EgtLine(RampLayer, ptLast, EgtSP(nPath)) + -- fisso punto finale per prossimo collegamento + ptLast = EgtEP(nPath) + EgtAddCurveCompoCurve(nCompoPath, nLinkPath) + EgtAddCurveCompoCurve(nCompoPath, nPath) + end + end + end + else + return GDB_ID.NULL + end + -- scrivo info per lavorazione + EgtSetInfo(nCompoPath, MACHPATH, 1) + + return nCompoPath +end +-- + +-- funzione che salva immagine per etichetta verniciati +function NestingLib.ManageMachine(CurrIsOffline) + -- svuoto tutto + OutlineMachining = {} + HoleMachining = {} + RampMachining = {} + Pocketing = {} + IsOffline = false + -- aggiungo liste nomi layer in prima posizione + table.insert(OutlineMachining, 1, Config.OutlineMachName) +-- table.insert(HoleMachining, 1, Config.HoleMachName) +-- table.insert(RampMachining, 1, Config.RampMachName) + HoleMachining[1] = Config.HoleMachName[1] + RampMachining[1] = Config.RampMachName[1] + -- se offline imposto lavorazioni macchina NorthWood + if CurrIsOffline then + sCurrMachName = "Northwood-RHD" + EgtSetCurrMachine(sCurrMachName) + table.insert(OutlineMachining, 2, Config.NWOutlineMachTools) + table.insert(HoleMachining, 2, Config.NWHoleMachTools) + table.insert(RampMachining, 2, Config.NWRampMachTools[1]) + Pocketing = Config.NWPocketingTools + IsOffline = true + else + sCurrMachName = "Multiax-NE_Nest01" + EgtSetCurrMachine(sCurrMachName) + table.insert(OutlineMachining, 2, Config.MXOutlineMachTools) + table.insert(HoleMachining, 2, Config.MXHoleMachTools) + table.insert(RampMachining, 2, Config.MXRampMachTools[1]) + Pocketing = Config.MXPocketingTools + IsOffline = false + end +end +-- + +--------------------------------------------------------------------- +return NestingLib diff --git a/RESTLib.lua b/RESTLib.lua new file mode 100644 index 0000000..a197092 --- /dev/null +++ b/RESTLib.lua @@ -0,0 +1,62 @@ +-- +-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT +-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEEEEEEEE GGGGGGGGGG TTTT +-- EEEEEEEEEE GGGGGG TTTT +-- +-- by EgalTech s.r.l. +-- Libreria delle funzioni REST by EgalTech s.r.l. 2020/08/13 + +-- Tabella per definizione modulo +local RESTLib = {} + +-- Include +require( 'EgtBase') +ltn12 = require( 'ltn12') +http = require( 'socket.http') +JSON = require( 'JSON') + +-- funzione get di chiamata REST +function RESTLib.get(path) + local resp = {} + -- Get info from website + --answ, status, body = http.request{url = path, content_type = 'application/json', sink = ltn12.sink.file(io.stdout)} + local body, code, headers = http.request{url = path, content_type = 'application/json', sink = ltn12.sink.table(resp)} + -- Verify errors + if code == 200 then + -- concateno le stringhe ricevute + local TempData = table.concat(resp) + -- e le decodifico da JSON a tabella lua + return JSON:decode(TempData) -- decode example + else + print("Error: ".. (code or '') ) + return {} + end +end +-- + +-- funzione set di chiamata REST +function RESTLib.set(path, value) + local resp = JSON:encode(value) + -- Get info from website + local body, code, headers = http.request{url = path, content_type = 'application/json', source = ltn12.source.string(resp), method = "POST", + headers = {["Content-Type"] = "application/json", + ["content-length"] = string.len(resp)}} + -- Verify errors + if code == 200 then + return true + else + print("Error: ".. (code or '') ) + return false + end +end +-- + +--------------------------------------------------------------------- +return RESTLib diff --git a/UtilityLib.lua b/UtilityLib.lua new file mode 100644 index 0000000..7529435 --- /dev/null +++ b/UtilityLib.lua @@ -0,0 +1,250 @@ +-- +-- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT +-- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEEEEE GGGG GGGGGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEE GGGG GGGG TTTT +-- EEEEEEEEEE GGGGGGGGGG TTTT +-- EEEEEEEEEE GGGGGG TTTT +-- +-- by EgalTech s.r.l. +-- Libreria delle funzioni ausiliarie by EgalTech s.r.l. 2020/08/13 + +-- Tabella per definizione modulo +local UtilityLib = {} + +-- Include +require( 'EgtBase') +local Config = require( 'Config') + +-- path di salvataggio dati +local PNGPath = Config.sBasePath .. "/PNG" + +-- list of all png created codes +local PNGIdList = {} + +-- Check if folder exists -- +function UtilityLib.FolderExists(strFolderName) + if EgtExistsDirectory(strFolderName:gsub("\\$",""),"mode") then + return true + else + return false + end +end +-- + +local OUTLINE = "Outline" +-- Colore del grezzo +local ColA = Color3d( 255, 165, 0, 30) + +local SHEETLABEL = "SheetLabel" +-- funzione che crea il grezzo +function UtilityLib.RawPartCreation(SheetPartId, vtOffs, IsOffLine) + local Pz = SheetPartId + local Ls = EgtGetFirstNameInGroup( Pz, OUTLINE) + local Er = EgtGetFirstNameInGroup( Ls, OUTLINE) + local SheetLabel = EgtGetFirstNameInGroup( Ls, SHEETLABEL) + local b3Part = EgtGetBBoxGlob( Pz or GDB_ID.NULL, GDB_BB.STANDARD) + local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) + -- se pezzo non definito, non devo fare alcunchè + if not Pz then + DISP.ERR = 0 + return + end + -- se pezzo vuoto, non devo fare alcunchè + if b3Part:isEmpty() then + DISP.ERR = 2 + return + end + -- Definizione e posizionamento del grezzo + local nRaw + if Er then + nRaw = EgtAddRawPartWithPart( Pz, Er, 0, ColA) + EgtRemovePartFromRawPart(Pz) + EgtSetStatus( Er, GDB_ST.ON) + else + nRaw = EgtAddRawPartWithPart( Pz, GDB_ID.NULL, dOverMat, ColA) + EgtRemovePartFromRawPart(Pz) + end + if not nRaw then + EgtOutLog( 'InitDisp for NE_nest : error defining raw part') + DISP.ERR = 3 + return + end + local b3Raw = EgtGetBBoxGlob(nRaw, GDB_BB.STANDARD) + local b3Label = EgtGetBBoxGlob(SheetLabel, GDB_BB.STANDARD) + local nRawLabel = EgtCopyGlob(SheetLabel, nRaw) + local dYPos = b3Raw:getMax():getY() + if b3Raw:getDimY() > 1465 then + dYPos = b3Raw:getMin():getY() + 1465 + (b3Label:getDimY()) + end + EgtMove(nRawLabel, Point3d(b3Raw:getMin():getX(), dYPos - b3Label:getDimY(), b3Raw:getMin():getZ()) - b3Label:getMin(), GDB_RT.GLOB) + -- se Northwood posiziono a sinistra, altrimenti a destra + local nTableRefPoint = MCH_CR.BR + if IsOffLine then + nTableRefPoint = MCH_CR.BL + end + if not EgtMoveToCornerRawPart( nRaw, vtOffs, nTableRefPoint) then + EgtOutLog( 'InitDisp for NE_nest : error positioning raw part on table') +-- DISP.ERR = 4 + return + end + return nRaw +end +-- + + +-- funzione che imposta tavola macchina +function UtilityLib.SetupMachineTable(IsOffline) + -- Scelta della tavola + local sTab = 'Tab' + EgtSetTable( sTab) + -- Dimensioni tavola + local b3Tab = EgtGetTableArea() + -- Richiesta posizione rispetto allo Zero tavola + local vtOffs = Vector3d( b3Tab:getDimX(), 0, 0) + -- se NorthWood cambio offset + if IsOffline then + vtOffs = Vector3d(0,0,0) + end + return vtOffs +end +-- + +local MATERIAL = {"MATERIAL FLAG"} +local PAINT = {"PAINT FLAG"} +local ASSEMBLY = {"TO BE ASSEMBLED","AssemblyCell"} +local TNUT = {"T-NUT FLAG","TNutFlag"} +local ROUND = {"ROUND EDGE","RoundEdge"} +local TAB = {"CHOP AT TAB","ChopAtTab"} +local PDF = {"PDF LINK"} +local CUTOPT = {"CUT OPT", "CutOpt"} +local LABEL = {"LABEL", "Label"} +local NAME = {"NAME", "Name"} + +local DXFFlags = {MATERIAL, PAINT, ASSEMBLY, TNUT, ROUND, TAB, PDF, CUTOPT, LABEL, NAME} + +-- funzione che legge i dxf +-- valore di ritorno numero 5 e' ErrorType: +-- 1) File not found +-- 2) Material layer not found +function UtilityLib.readDXF(DXFpath, PartExtCode, IsEstimation) + -- elimino doppie barre dalla path + DXFpath = string.gsub(DXFpath, "\\", '/') + local errorType = 0 + local material = nil + local pdfPath = "" + local paint = false + local flags = {} + local revision = "" + -- apro DXF + EgtNewFile() + EgtOutLog(DXFpath) + local res = EgtImportDxf(DXFpath) + if not res then + errorType = 1 + EgtOutLog("DXF file not found :" .. DXFpath) + return material, pdfPath, paint, flags, errorType + end -- GESTIRE ERRORE!! + -- trovo pezzo + local part = EgtGetFirstInGroup(GDB_ID.ROOT) + -- cerco i layer + for Flag = 1, #DXFFlags do + local flagLayer = EgtGetFirstNameInGroup(part, DXFFlags[Flag][1]) + if flagLayer then + local textObject = EgtGetFirstInGroup(flagLayer) + -- leggo il testo + local flagText = EgtTextContent(textObject) + -- verifico se il flag e' material + if DXFFlags[Flag][1] == MATERIAL[1] then + -- ritaglio valore + local _, _, valueText = string.find(flagText, ".*:%s*(%d+)") + material = tonumber(valueText) + elseif DXFFlags[Flag][1] == PDF[1] then + -- ritaglio valore + local _, _, valueText = string.find(flagText, ".*:%s*\"(.+)\"") + pdfPath = valueText + elseif DXFFlags[Flag][1] == PAINT[1] then + -- ritaglio valore + local _, _, valueText = string.find(flagText, ".*:%s*(%a+)") + local PaintVal = string.lower(valueText) + if PaintVal == "yes" then + paint = true + else + paint = false + end + elseif DXFFlags[Flag][1] == NAME[1] then + revision = flagText + else + -- ritaglio valore + local _, _, valueText = string.find(flagText, ".*:%s*(%w+[&]*%w*)") + flags[DXFFlags[Flag][2]] = valueText + end + else + if Flag < 8 then + errorType = 2 + EgtOutLog(DXFFlags[Flag][1] .. " layer not found :" .. DXFpath) + return material, pdfPath, paint, flags, errorType + end + end + end + if IsEstimation and paint then + -- verifico se gia' processato + local Index = 1 + local bFound = false + while not bFound and Index <= #PNGIdList do + if PartExtCode == PNGIdList[Index] then + bFound = true + end + Index = Index + 1 + end + if not bFound then + SavePartImage(revision) + table.insert(PNGIdList, PartExtCode) + end + end + return material, pdfPath, paint, flags, errorType, revision +end +-- + +-- funzione che salva immagine per etichetta verniciati +function SavePartImage(PartExtCode) + local nPartId = EgtGetFirstInGroup(GDB_ID.ROOT) + local nLayerId = EgtGetFirstLayer( nPartId) + while nLayerId and nLayerId ~= GDB_ID.NULL do + -- nascondo tutti i layer tranne i contorni, i buchi e le rampe + local sLayerName = EgtGetName(nLayerId) + local bOutlineLayer = false + for Index = 1, #Config.OutlineMachining[1] do + if sLayerName == Config.OutlineMachining[1][Index] then + bOutlineLayer = true + end + end + if bOutlineLayer == true or sLayerName == Config.HoleMachining[1] or sLayerName == Config.RampMachining[1] then + -- coloro i contorni di nero + local nGeomId = EgtGetFirstInGroup(nLayerId) + while nGeomId and nGeomId ~= GDB_ID.NULL do + EgtSetColor(nGeomId, BLACK()) + nGeomId = EgtGetNext(nGeomId) + end + else + -- disattivo tutti gli altri layer + EgtSetStatus(nLayerId, GDB_ST.OFF) + end + nLayerId = EgtGetNextLayer(nLayerId) + end +-- -- calcolo bbox pezzo +-- local b3PartId = EgtGetBBox(nPartId, GDB_BB.STANDARD + GDB_BB.ONLY_VISIBLE + GDB_BB.IGNORE_TEXT + GDB_BB.IGNORE_DIM) +-- -- lo sposto +-- EgtMove(nPartId, Vector3d(- (b3PartId:getDimX() / 2), - (b3PartId:getDimY() / 2), 0)) + EgtZoom(SCE_ZM.ALL) + EgtGetImage( SCE_SM.SH, WHITE(), WHITE(), 1600, 1000, PNGPath .. "/" .. PartExtCode .. ".png") +-- EgtSaveFile(PNGPath .. "/" .. PartExtCode .. ".nge") +end +-- + +--------------------------------------------------------------------- +return UtilityLib