-- BatchProcessNew.lua by Egalware s.r.l. 2025/04/24 -- Intestazioni require( 'EgtBase') _ENV = EgtProtectGlobal() EgtEnableDebug( false) -- Imposto direttorio libreria specializzata per Travi EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua') -- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua') EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua') -- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi e carico log txt local sMachine = BEAM.MACHINE local sTxtLogFile if ( BEAM.FLAG ~= 6) and ( BEAM.FLAG ~= 9) then EgtResetCurrMachGroup() if not EgtSetCurrMachine( sMachine) then BEAM.ERR = 11 BEAM.MSG = 'Error selecting machine : ' .. sMachine WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) return end end if BEAM.FLAG ~= 9 then sTxtLogFile = EgtChangePathExtension( BEAM.FILE, '.txt') end local sMachDir = EgtGetCurrMachineDir() if not sMachDir then EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR') return end if not EgtExistsFile( sMachDir .. '\\Beam\\BeamDataNew.lua') then EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR') BEAM.ERR = 12 BEAM.MSG = 'Error not configured for beams machine : ' .. sMachine WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) return end -- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie EgtRemoveBaseMachineDirFromPackagePath() EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua') -- Segnalazione avvio EgtOutLog( '*** Beam Process Start ***', 1) -- Carico le librerie _G.package.loaded.BasicCustomerStrategies = nil _G.package.loaded.BeamExec = nil _G.package.loaded.BeamLib = nil _G.package.loaded.DiceCut = nil _G.package.loaded.FaceData = nil _G.package.loaded.FeatureLib = nil _G.package.loaded.Identity = nil _G.package.loaded.Logs = nil _G.package.loaded.MachiningLib = nil _G.package.loaded.PreSimulationLib = nil _G.package.loaded.LeadInOutLib = nil -- strategie di base sempre presenti _G.package.loaded['HEADCUT\\HEADCUT'] = nil _G.package.loaded['TAILCUT\\TAILCUT'] = nil -- libreria macchina _G.package.loaded.BeamDataNew = nil -- libreria calcolo tempo esecuzione _G.package.loaded.TimeLib = nil -- TODO controllare se c'è un modo migliore per resettare librerie delle strategie caricate precedentemente -- Per ottimizzare potremmo anche ciclare solo fino al numero di strategie raggiunto per il momento. -- Infatti difficile ci siano 9999 strategie. -- reset strategie caricate come librerie for i = 1, 9999 do local idSTRTemp = EgtReplaceString( EgtNumToString( i/10000, -4), '0.', '') local sLibraryToReload = "STR" .. idSTRTemp .. "\\STR" .. idSTRTemp if _G.package.loaded[sLibraryToReload] then _G.package.loaded[sLibraryToReload] = nil end end local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\StrategyLibs\\*.lua') for i = 1, #vtCoreStrategiesNames do local sCurrentName = EgtSplitString( vtCoreStrategiesNames[i], '.')[1] if _G.package.loaded[sCurrentName] then _G.package.loaded[sCurrentName] = nil end end -- Variabili globali PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo -- Carico i dati globali local BeamData = require( 'BeamDataNew') -- carico librerie local BeamExec = require( 'BeamExec') local BeamLib = require( 'BeamLib') local FeatureLib = require( 'FeatureLib') local JSON = require( 'JSON') -- Variabili di modulo local dRawW local dRawH ------------------------------------------------------------------------------------------------------------- -- Funzioni di supporto local function GetDataConfig() -- recupero utensili dal magazzino BeamExec.GetToolsFromDB() -- TODO da gestire eventuali errori bloccanti return true end local function WriteErrToLogFile( nErr, sMsg, nRot, idCut, idTask) local hFile = io.open( sTxtLogFile, 'a') hFile:write( 'ERR=' .. tostring( nErr) .. '\n') hFile:write( sMsg .. '\n') hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n') hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n') hFile:write( 'TASKID=' .. tostring( idTask or 0) .. '\n') hFile:close() end local function WriteFallToLogFile( nErr, sMsg, idCut, nFall) local hFile = io.open( sTxtLogFile, 'a') hFile:write( 'ERR=' .. tostring( nErr) .. '\n') hFile:write( sMsg .. '\n') hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n') hFile:write( 'FALL=' .. tostring( nFall or 0) .. '\n') hFile:close() end local function WriteTimeToLogFile( dTime) local hFile = io.open( sTxtLogFile, 'a') hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n') hFile:close() end -- Funzioni per gestire visualizzazione dopo errore e dopo warning local function PostErrView( nErr, sMsg) if nErr ~= 0 and ( BEAM.FLAG == 1 or BEAM.FLAG == 2) then EgtSetView( SCE_VD.ISO_SW, false) EgtZoom( SCE_ZM.ALL) EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS') end end local function PostWarnView( nWarn, sMsg) if nWarn ~= 0 and ( BEAM.FLAG == 1 or BEAM.FLAG == 2) then EgtSetView( SCE_VD.ISO_SW, false) EgtZoom( SCE_ZM.ALL) EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS') end end -- Funzione di reset gruppo di lavoro in caso di impossibilità di inserire i pezzi local function ResetMachGroup( PARTS) for i = 1, #PARTS do EgtErase( PARTS[i].id) end EgtRemoveMachGroup( EgtGetCurrMachGroup() or GDB_ID.NULL) end -- scrittura JSON risultati -- TODO da migliorare/completare local function WriteResultToJson( RESULT) local sData = JSON:encode_pretty( RESULT) -- Salvataggio e visualizzazione tabella local sOutFile = EgtChangePathExtension( BEAM.FILE, '.json') local DestFh = io.open( sOutFile, 'w+') if not DestFh then EgtOutBox( 'Error opening ' .. sOutFile, 'TestJson', 'ERROR') return false end DestFh:write( sData) DestFh:close() return true end ------------------------------------------------------------------------------------------------------------- -- calcolo tempo esecuzione TIMER:start() EgtOutLog( ' Execution timer started') -- script principale local sFlag = '' if BEAM.FLAG == 0 then sFlag = 'GENERATE' elseif BEAM.FLAG == 1 then sFlag = 'MODIFY' elseif BEAM.FLAG == 2 then sFlag = 'SIMULATE' elseif BEAM.FLAG == 3 then sFlag = 'CHECK' elseif BEAM.FLAG == 4 then sFlag = 'CHECK+GENERATE' elseif BEAM.FLAG == 6 then sFlag = 'CREATE_BAR' elseif BEAM.FLAG == 8 then sFlag = 'CHECK_NOSIM' elseif BEAM.FLAG == 9 then sFlag = 'GET_TOPOLOGY' elseif BEAM.FLAG == 10 then sFlag = 'FLIP_ROT' else sFlag = 'FLAG='..tostring( BEAM.FLAG) end local sLog = 'BatchProcess : ' .. BEAM.FILE .. ', ' .. ( BEAM.MACHINE or EgtGetCurrMachineName()) .. ', ' .. sFlag EgtOutLog( sLog) -- Dati dei file -- TODO spostare a quando flag ~= 6 e 9 local sDir, sTitle = EgtSplitPath( BEAM.FILE) local sOriFile = sDir..sTitle..'.ori.bwe' local sNgeFile = sDir..sTitle..'.bwe' -- cancellazione file log txt precedente -- in caso sia richiesta generazione senza check, verifico prima che il file log specifico non contenga errori: se sì, forzo il check -- TODO serve ancora?? forzare sempre il check e simulazione? if BEAM.FLAG == 0 then local hLogFile = io.open( sTxtLogFile, 'r') if hLogFile then for line in hLogFile:lines() do if EgtStartsWith( line, 'ERR') and tonumber( EgtSplitString( line, '=')[2] or 0) > 0 then BEAM.FLAG = 4 break end end hLogFile:close() end -- restituisce all'interfaccia il nome della topologia della feature di id passato -- TODO valutare se fare script separato elseif BEAM.FLAG == 9 then if type( BEAM.FEATUREID) == 'number' then -- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella local idTempGroup = BeamLib.CreateTempGroup() local Part = {} Part.id = EgtGetParent( EgtGetParent( BEAM.FEATUREID)) Part.idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( Part.id, 'Box') or GDB_ID.NULL) Part.b3Part = EgtGetBBoxGlob( Part.idBoxTm, GDB_BB.STANDARD) Part.idTempGroup = idTempGroup local Proc = FeatureLib.GetProcFromTrimesh( BEAM.FEATUREID, Part) Proc.nGrp = EgtGetInfo( Proc.id, 'GRP', 'i') Proc.nPrc = EgtGetInfo( Proc.id, 'PRC', 'i') Proc.nParts = EgtSurfTmPartCount( Proc.id) or 1 Proc.Topology = {} if FeatureLib.NeedTopologyFeature( Proc, Part) then Proc.Topology = FeatureLib.ClassifyTopology( Proc, Part) else Proc = FeatureLib.GetAdditionalInfo( Proc, Part) Proc.Topology = FeatureLib.GetTopologyFromFeature( Proc, Part) end if Proc.Topology and Proc.Topology.sName then BEAM.TOPOLOGY = Proc.Topology.sName else BEAM.TOPOLOGY = 'NOT_IMPLEMENTED' end -- si cancella gruppo temporaneo contenente entità da cancellare EgtErase( idTempGroup) end return end -- Cancello file di log specifico EgtEraseFile( sTxtLogFile) -- In generale va completamente riprocessato local bToProcess = true local bToRecalc = false -- se BTL, barra ed esiste già il corrispondente progetto Nge if EgtExistsFile( sOriFile) then bToProcess = false EgtCopyFile( sOriFile, sNgeFile) -- se cambiata configurazione macchina da ultima elaborazione, devo aggiornare if EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Beam\\TS3Data.lua') == -1 or EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Tools\\Tools.data') == -1 or EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\' .. sMachine ..'.mlde') == -1 then bToRecalc = true end end -- Inizializzo contatori errori e avvisi local nErrCnt = 0 local nWarnCnt = 0 -- Se da elaborare if bToProcess then EgtOutLog( ' +++ Processing Parts >>>') -- Flag di barra da creare local bCreateBar -- Lunghezza della barra ed elenco travi local dBarLen -- Se necessario, apro il file Bwe if BEAM.FLAG ~= 6 then if not EgtOpenFile( BEAM.FILE) then BEAM.ERR = 13 BEAM.MSG = 'Error opening BWE file : ' .. BEAM.FILE WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end -- Faccio copia del file originale EgtCopyFile( BEAM.FILE, sOriFile) -- Se già presente un gruppo di lavoro if EgtGetFirstMachGroup() then -- Barra già presente bCreateBar = false -- Rendo corrente il gruppo di lavoro EgtSetCurrMachGroup() -- Area tavola local b3Tab = EgtGetTableArea() -- Sezione del grezzo local nRawId = EgtGetFirstRawPart() if not nRawId then BEAM.ERR = 14 BEAM.MSG = 'Error no Raw Parts in the file : ' .. BEAM.FILE WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end local b3Raw = EgtGetRawPartBBox( nRawId) -- Calcolo posizione estremo TR o BR della tavola rispetto a sua origine in BL local dPosY = EgtIf( BeamData.CENTER_BEAM, ( b3Tab:getDimY() + b3Raw:getDimY() * EgtIf( BeamData.RIGHT_LOAD, -1, 1)) / 2, EgtIf( BeamData.RIGHT_LOAD, 0, b3Tab:getDimY())) BeamData.ptOriXR = Point3d( b3Tab:getDimX(), dPosY, 0) BeamData.dPosXR = EgtIf( BeamData.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR) -- Calcolo minimo grezzo scaricabile BeamExec.CalcMinUnloadableRaw( b3Raw:getDimY(), b3Raw:getDimZ()) -- altrimenti devo recuperare i pezzi per creare la barra else -- Barra da creare bCreateBar = true -- Recupero l'elenco ordinato delle travi local nPartId = EgtGetFirstPart() while nPartId do table.insert( PARTS, { id = nPartId, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) nPartId = EgtGetNextPart( nPartId) end if #PARTS == 0 then BEAM.ERR = 14 BEAM.MSG = 'Error no beams in the file : ' .. BEAM.FILE WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return else local sOut = '' for i = 1, #PARTS do sOut = sOut .. PARTS[i].sName .. ', ' end sOut = sOut:sub( 1, -3) EgtOutLog( 'Travi trovate : ' .. sOut, 1) end -- Ne recupero le dimensioni for i = 1, #PARTS do local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then BEAM.ERR = 15 BEAM.MSG = 'Box undefined for beam ' .. PARTS[i].sName WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return else PARTS[i].b3PartOriginal = b3Solid end end -- Assegno lunghezza della barra dBarLen = PARTS[1].b3PartOriginal:getDimX() + 10 if dBarLen < 2200 then dBarLen = dBarLen + 1800 end -- Assegno posizione prima ed unica trave PARTS[1].dPosX = 10 end -- Altrimenti, opero sul progetto corrente else -- Recupero l'identificativo del gruppo di lavoro corrente local nMGrpId = EgtGetCurrMachGroup() -- Barra da creare bCreateBar = true -- Lunghezza della barra dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd') -- Recupero l'elenco ordinato delle travi da inserire nella barra for i = 1, 100 do local sKey = 'PART'..tostring( i) local sVal = EgtGetInfo( nMGrpId, sKey) local vVal = EgtSplitString( sVal or '') if not vVal or #vVal < 2 then break end local nPartId = tonumber( vVal[1]) local dPosX = tonumber( vVal[2]) table.insert( PARTS, { id = nPartId, dPosX = dPosX, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) end if #PARTS == 0 then BEAM.ERR = 14 BEAM.MSG = 'Error : no beams in the project' WriteErrToLogFile( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return else local sOut = '' for i = 1, #PARTS do sOut = sOut .. PARTS[i].sName .. ', ' end sOut = sOut:sub( 1, -3) EgtOutLog( 'Travi trovate : ' .. sOut, 1) end -- Ne recupero le dimensioni for i = 1, #PARTS do local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then BEAM.ERR = 15 BEAM.MSG = 'Box undefined for beam ' .. PARTS[i].sName WriteErrToLogFile( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return else PARTS[i].b3PartOriginal = b3Solid end end end -- recupero parametri generali da progetto BeamExec.GetGeneralParameters() -- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella local idTempGroup = BeamLib.CreateTempGroup() -- Se devo creare la barra if bCreateBar then if #PARTS == 0 then -- Recupero l'identificativo del gruppo di lavoro corrente local nMGrpId = EgtGetCurrMachGroup() -- Recupero le dimensioni della barra dRawW = EgtGetInfo(nMGrpId, 'BARWIDTH', 'd') dRawH = EgtGetInfo(nMGrpId, 'BARHEIGHT', 'd') else -- Ne verifico le dimensioni dRawW = PARTS[1].b3PartOriginal:getDimY() dRawH = PARTS[1].b3PartOriginal:getDimZ() end local vBeamErr = {} for i = 2, #PARTS do local dDimW = PARTS[i].b3PartOriginal:getDimY() local dDimH = PARTS[i].b3PartOriginal:getDimZ() if ( abs( dDimW - dRawW) > 100 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 100 * GEO.EPS_SMALL) and ( abs( dDimH - dRawW) > 100 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 100 * GEO.EPS_SMALL) then table.insert( vBeamErr, i) end end if #vBeamErr > 0 then local sOut = 'Rimosse travi con sezioni diverse dalla prima :\n' for i = #vBeamErr, 1, -1 do sOut = sOut .. PARTS[vBeamErr[i]].sName .. '\n' table.remove( PARTS, vBeamErr[i]) end ResetMachGroup( PARTS) BEAM.ERR = 16 BEAM.MSG = sOut WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) return end -- Verifico sezione barra non troppo grande if not BeamData.MAX_WIDTH2 or not BeamData.MAX_HEIGHT2 then if ( dRawW > BeamData.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT + 10 * GEO.EPS_SMALL) then ResetMachGroup( PARTS) local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. 'oltre i limiti della macchina (' .. EgtNumToString( BeamData.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT, 2) .. ') ' BEAM.ERR = 17 BEAM.MSG = sOut WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end else if ( dRawW > BeamData.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT + 10 * GEO.EPS_SMALL) and ( dRawW > BeamData.MAX_WIDTH2 + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT2 + 10 * GEO.EPS_SMALL) then ResetMachGroup( PARTS) local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. 'oltre i limiti della macchina (' .. EgtNumToString( BeamData.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT, 2) .. ') ' .. 'e (' .. EgtNumToString( BeamData.MAX_WIDTH2, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT2, 2) .. ')' BEAM.ERR = 17 BEAM.MSG = sOut WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end end -- Verifico sezione barra non troppo piccola if dRawW < BeamData.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < BeamData.MIN_HEIGHT - 10 * GEO.EPS_SMALL then ResetMachGroup( PARTS) local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. 'sotto i limiti della macchina (' .. EgtNumToString( BeamData.MIN_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MIN_HEIGHT, 2) .. ')' BEAM.ERR = 17 BEAM.MSG = sOut WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end -- Lunghezza della barra local dRawL = dBarLen + 0.1 -- Sovramateriale di testa local dOvmHead = 0 if #PARTS > 0 then dOvmHead = PARTS[1].dPosX or 0 end -- Sistemo le travi nel grezzo local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, BEAM.FLAG == 10) if not bPbOk then BEAM.ERR = 18 BEAM.MSG = sPbErr WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return else -- Scrivo altezza e larghezza barra nel gruppo di lavoro corrente local nMGrpId = EgtGetCurrMachGroup() EgtSetInfo(nMGrpId, 'BARHEIGHT', dRawH) EgtSetInfo(nMGrpId, 'BARWIDTH', dRawW) end -- sistemazioni per pezzi nella barra else -- ciclo sui grezzi local nRawId = EgtGetFirstRawPart() while nRawId do -- massimo un pezzo per grezzo local nPartId = EgtGetFirstPartInRawPart( nRawId) -- box del pezzo local Ls = EgtGetFirstNameInGroup( nPartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) -- se nel grezzo c'è un pezzo if nPartId then -- creo o pulisco gruppo geometrie aggiuntive BeamLib.CreateOrEmptyAddGroup( nPartId) -- aggiungo faccia per taglio iniziale al pezzo BeamLib.AddPartStartFace( nPartId, b3Solid) -- aggiungo faccia per taglio finale al pezzo BeamLib.AddPartEndFace( nPartId, b3Solid) end -- passo al successivo grezzo nRawId = EgtGetNextRawPart( nRawId) end -- elimino le lavorazioni EgtRemoveAllOperations() -- Recupero l'identificativo del gruppo di lavoro corrente local nMGrpId = EgtGetCurrMachGroup() -- Recupero l'elenco ordinato delle travi da inserire nella barra for i = 1, 100 do local sKey = 'PART'..tostring( i) local sVal = EgtGetInfo( nMGrpId, sKey) local vVal = EgtSplitString( sVal or '') if not vVal or #vVal < 2 then break end local nPartId = tonumber( vVal[1]) local dPosX = tonumber( vVal[2]) table.insert( PARTS, { nInd = #PARTS + 1, id = nPartId, dPosX = dPosX, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) end -- se lunghezza barra non settata, la leggo ora if not dBarLen then dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd') end -- Recupero tutte le informazioni dei pezzi local dLen = dBarLen for i = 1, #PARTS do -- aggiorno grezzo precedente PARTS[i].idRaw = EgtGetRawPartFromPart( PARTS[i].id) PARTS[i].bIsLastPart = ( i == #PARTS) -- dimensioni del grezzo ( comprende sovramateriale di testa e lavorazione di coda per separazione) PARTS[i].b3Raw = EgtGetRawPartBBox( PARTS[i].idRaw) PARTS[i].dRawLength = PARTS[i].b3Raw:getDimX() PARTS[i].dRawWidth = PARTS[i].b3Raw:getDimY() PARTS[i].dRawHeight = PARTS[i].b3Raw:getDimZ() -- dimensione pezzo finito PARTS[i].idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL) PARTS[i].b3Part = EgtGetBBoxGlob( PARTS[i].idBoxTm, GDB_BB.STANDARD) PARTS[i].dLength = PARTS[i].b3Part:getDimX() PARTS[i].dWidth = PARTS[i].b3Part:getDimY() PARTS[i].dHeight = PARTS[i].b3Part:getDimZ() PARTS[i].bSquareSection = abs( PARTS[i].dWidth - PARTS[i].dHeight) < 100 * GEO.EPS_SMALL PARTS[i].nIndexInParts = i PARTS[i].SplittingPoints = BeamLib.GetPartSplittingPoints( PARTS[i]) PARTS[i].NotClampableLength = { STD = { dHead = 0, dTail = 0}, SIDE = { dHead = 0, dTail = 0}, DOWN = { dHead = 0, dTail = 0}} PARTS[i].sBTLInfo = EgtGetInfo( PARTS[i].id, 'PROJ', 's') or nil PARTS[i].idTempGroup = idTempGroup PARTS[i].sAISetupConfig = EgtGetInfo( PARTS[i].id, 'AISETUP', 's') or ( GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo] and GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo].sAISetupConfig) or -- i parametri BTL potrebbero non esistere GENERAL_PARAMETERS.PROJECT.sAISetupConfig or nil -- si carica configurazione lavorazioni TIMER:startElapsed('Json') BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig) PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON) TIMER:stopElapsed('Json') -- parametro FlipRot sempre a false perchè a barra già creata non si possono più ruotare i pezzi PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], false) -- sovramateriale in testa al pezzo local dDeltaS = max( PARTS[i].dPosX - ( dBarLen - dLen), 0) PARTS[i].dHeadOverMaterial = dDeltaS -- lunghezza grezzo (comprende sovramateriale di testa e mm tagliati in coda dalla lavorazione, tipicamente 5.4mm dello spessore lama) local dCrawLen = PARTS[i].dRawLength -- materiale tolto in coda dalla lavorazione di separazione local dDeltaE = dCrawLen - PARTS[i].dLength - dDeltaS local dDeltaNextPiece if PARTS[i+1] then dDeltaNextPiece = PARTS[i+1].dPosX - ( dBarLen - dLen) - dCrawLen + dDeltaE else dDeltaNextPiece = 10000 end PARTS[i].dDistanceToNextPiece = dDeltaNextPiece -- aggiorno la lunghezza residua della barra dLen = dLen - dCrawLen PARTS[i].dRestLength = dLen end end -- Se richiesta solo barra, esco if BEAM.FLAG == 6 then -- Completamento senza errori e avvisi if nWarnCnt == 0 then BEAM.ERR = 0 BEAM.MSG = '---' WriteErrToLogFile( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) end EgtOutLog( ' +++ BatchProcess completed') return end -- Imposto Nome file CN local _, sName, _ = EgtSplitPath( BEAM.FILE) EgtSetInfo( EgtGetCurrMachGroup(), 'NcName', sName .. '.cnc') -- Abilito Vmill EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1') -- Aggiorno Setup utensili EgtImportSetup() -- Lavoro le features -- TODO gestire errori e messaggi di ritorno in questo caso if not GetDataConfig() then return end BeamExec.GetProcessings( PARTS, BEAM.FLAG == 10) BeamExec.GetCombinationMatrix( PARTS, BEAM.FLAG == 10) BeamExec.ProcessMachinings( PARTS, BEAM.FLAG == 10) local sOutput = '' -- scrittura txt risultati for i = 1, #RESULT do local sMsg = '' if RESULT[i].sType == 'Feature' then if RESULT[i].ChosenStrategy.bIsApplyOk then sMsg = RESULT[i].ChosenStrategy.sInfo else sMsg = RESULT[i].ChosenStrategy.sApplyInfo end elseif RESULT[i].sType == 'Part' then sMsg = RESULT[i].sMsg end sMsg = string.gsub( sMsg or '', '\n', ' ', 10) sMsg = string.gsub( sMsg or '', '\r', ' ', 10) -- trovata almeno una strategia e feature lavorata completamente if RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Completed' then if #EgtTrim( sMsg) > 0 then BEAM.ERR = -19 BEAM.MSG = sMsg else BEAM.ERR = 0 BEAM.MSG = '---' end BEAM.ROT = -( ( RESULT[i].nRotation - ( BEAM.PREROTATE90 or 0)) or 1) + 1 BEAM.CUTID = RESULT[i].idCut BEAM.TASKID = RESULT[i].idTask WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) -- trovata almeno una strategia ma nessuna applicabile oppure non trovata alcuna strategia elseif RESULT[i].sType == 'Feature' and ( ( RESULT[i].ChosenStrategy.sStatus == 'Not-Applicable') or ( not RESULT[i].ChosenStrategy.sStrategyName)) then nErrCnt = nErrCnt + 1 if #sMsg == 0 then sMsg = 'No applicable strategy found' end sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg) BEAM.ERR = 19 BEAM.MSG = sMsg BEAM.ROT = -( ( RESULT[i].nRotation - ( BEAM.PREROTATE90 or 0)) or 1) + 1 BEAM.CUTID = RESULT[i].idCut BEAM.TASKID = RESULT[i].idTask WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) else -- segnalazione scarico pezzo standard, incompleto o a caduta if RESULT[i].sType == 'Part' and ( RESULT[i].nErr == -100 or RESULT[i].nErr == -101 or RESULT[i].nErr == -102) then BEAM.ERR = 0 BEAM.MSG = sMsg BEAM.CUTID = RESULT[i].idCut BEAM.FALL = abs( RESULT[i].nErr + 100) WriteFallToLogFile( BEAM.ERR, BEAM.MSG, BEAM.CUTID, BEAM.FALL) -- errore da post apply, al momento non specifico elseif RESULT[i].sType == 'Part' and RESULT[i].nErr > 0 then nErrCnt = nErrCnt + 1 sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg) BEAM.ERR = 19 BEAM.MSG = 'Clamp impossible' WriteErrToLogFile( BEAM.ERR, BEAM.MSG) return -- feature incompleta e altro elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then nWarnCnt = nWarnCnt + 1 sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg) BEAM.ERR = -19 BEAM.MSG = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg BEAM.ROT = -( ( RESULT[i].nRotation - ( BEAM.PREROTATE90 or 0)) or 1) + 1 BEAM.CUTID = RESULT[i].idCut BEAM.TASKID = RESULT[i].idTask WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) end end end -- calcolo alternative (scrive già le variabili globali per interfaccia) if BEAM.FLAG == 10 then TIMER:startElapsed('Alternatives') BeamExec.ProcessAlternatives( PARTS) TIMER:stopElapsed('Alternatives') end -- si cancella gruppo temporaneo contenente entità da cancellare EgtErase( idTempGroup) -- TODO: se scarico a caduta (-101, -102) le lavorazioni dopo separazione vanno disattivate. Scrivere info feature incompleta su quelle feature -- Salvo il progetto EgtSaveFile( sNgeFile) -- copio come originale (per dichiarare progetto ricalcolato) EgtCopyFile( sNgeFile, sOriFile) -- Visualizzazione avvisi o errori if #sOutput > 0 then EgtOutLog( sOutput) end if nErrCnt > 0 then PostErrView( 19, sOutput) elseif nWarnCnt > 0 then PostWarnView( 19, sOutput) end -- Altrimenti carico il progetto salvato e dichiaro nessun errore else EgtOutLog( ' +++ Loading Project already processed >>>') -- Carico il progetto già fatto EgtOpenFile( sNgeFile) -- Passo in modalità lavora EgtSetCurrMachGroup( EgtGetLastMachGroup()) -- Se necessario eseguo aggiornamento con setup corrente e ricalcolo delle lavorazioni if bToRecalc or BEAM.FLAG == 3 or BEAM.FLAG == 4 or BEAM.FLAG == 8 then EgtOutLog( ' +++ Recalculating all dispositions and machinings >>>') EgtImportSetup() EgtApplyAllMachinings() -- Salvo il progetto EgtSaveFile( sNgeFile) -- copio come originale (per dichiarare progetto ricalcolato) EgtCopyFile( sNgeFile, sOriFile) end end -- log tempi di esecuzione if EgtGetDebugLevel() >= 3 then TIMER:logAllElapsed() end -- *** Eseguo simulazione con verifica collisione in cieco *** if ( BEAM.FLAG == 0 and ( bToProcess or bToRecalc)) or BEAM.FLAG == 3 or BEAM.FLAG == 4 then EgtOutLog( ' +++ Simulating with collision check >>>') -- verifico setup local bSetUpOk, SetUpErrors = EgtVerifyCurrSetup() if not bSetUpOk then local sToolsList = "" for ToolIndex = 1, #SetUpErrors do sToolsList = sToolsList .. SetUpErrors[ToolIndex] if ToolIndex ~= #SetUpErrors then sToolsList = sToolsList .. ", " end end BEAM.ERR = 19 BEAM.MSG = 'Error in setup: tool/s ' .. sToolsList .. ' not found' WriteErrToLogFile( BEAM.ERR, BEAM.MSG, 0, 0, 0) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end -- lancio simulazione local bSimOk, nErr, sErr = EgtSimulate() if not bSimOk then if nErr == MCH_SHE.INIT then BEAM.ERR = 19 BEAM.MSG = 'Error starting simulation' elseif nErr == MCH_SHE.COLLISION then BEAM.ERR = 22 BEAM.MSG = 'Head-part collision' elseif nErr == MCH_SHE.OUTSTROKE then BEAM.ERR = 23 BEAM.MSG = 'Axis outstroke ' .. sErr elseif nErr == MCH_SHE.SPECIAL then BEAM.ERR = 24 BEAM.MSG = 'Special error ' .. sErr else BEAM.ERR = 25 BEAM.MSG = 'General failure (contact supplier)' end BEAM.ROT = 0 BEAM.CUTID = 0 BEAM.TASKID = 0 local vItem = EgtSplitString( sErr, ';') or {} for i = 1, #vItem do vItem[i] = EgtTrim( vItem[i] or '') if string.find( vItem[i], 'CUTID', 1, true) then BEAM.CUTID = EgtGetVal( vItem[i], 'CUTID', 'i') or 0 elseif string.find( vItem[i], 'TASKID', 1, true) then BEAM.TASKID = EgtGetVal( vItem[i], 'TASKID', 'i') or 0 end end WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) -- TODO gestire collisione su feature specifica!!!!!!!!!!!!!!!!!!!!!!!!!!!! BeamExec.AddApplyResultToGlobalList( BEAM.ERR, BEAM.CUTID, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end end -- *** Genero programma CN *** ( se richiesto) local bIsGenerationEnabled = ( EgtVerifyKeyOption( 110) == false) if bIsGenerationEnabled and ( BEAM.FLAG == 0 or BEAM.FLAG == 4) then EgtOutLog( ' +++ Generating NC part program >>>') local sInfo = 'EgtCAM5' .. EgtIf( EgtIs64bit(), ' 64bit', '') if EgtGetExeVersion then sInfo = sInfo .. ' ver.' .. EgtGetExeVersion() end sInfo = sInfo .. ' - ' if not EgtGenerate( '', sInfo .. sNgeFile) then BEAM.ERR = 20 local _, sName, _ = EgtSplitPath( BEAM.FILE) BEAM.MSG = 'Error generating NC part program : ' .. sName WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end end -- *** Eseguo stima tempi *** EgtOutLog( ' +++ Estimating T&L >>>') if not EgtEstimate( '', 'EgtCAM5 - ' .. sNgeFile) then BEAM.ERR = 21 local _, sName, _ = EgtSplitPath( BEAM.FILE) BEAM.MSG = 'Error estimating production time : ' .. sName WriteErrToLogFile( BEAM.ERR, BEAM.MSG) PostErrView( BEAM.ERR, BEAM.MSG) BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) WriteResultToJson( RESULT) return end local Ttot = EgtGetInfo( EgtGetCurrMachGroup(), 'Ttot', 'd') local sTime = 'Total Time = ' .. EgtNumToString( Ttot, 1) EgtOutLog( sTime) -- Se modifica o simula, imposto la vista ISO 3d opportuna if BEAM.FLAG == 1 or BEAM.FLAG == 2 then local vView = { SCE_VD.ISO_NW, SCE_VD.ISO_SW, SCE_VD.ISO_NE, SCE_VD.ISO_SE} local nV = min( max( BeamData.SIMUL_VIEW_DIR or 2, 1), 4) EgtSetView( vView[nV], false) end -- Completamento senza errori e avvisi if nWarnCnt == 0 then BEAM.ERR = 0 BEAM.MSG = '---' WriteErrToLogFile( BEAM.ERR, BEAM.MSG) end -- Scrittura tempo totale stimato di lavorazione WriteTimeToLogFile( Ttot) RESULT[#RESULT+1] = { dTime = Ttot, sType = 'Time'} -- Riporto risultati in tabella globale BEAM BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) -- Scrittura json risultati WriteResultToJson( RESULT) EgtOutLog( ' +++ BatchProcess completed')