From 7f7d75c113d45d07f078a8535cdbf7ec98c0f286 Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Mon, 23 Feb 2026 16:24:43 +0100 Subject: [PATCH 1/4] =?UTF-8?q?-=20BatchProcess=20non=20calcola=20pi=C3=B9?= =?UTF-8?q?=20le=20prerotazioni=20-=20Modifiche=20varie=20per=20nuova=20ge?= =?UTF-8?q?stione=20pre-rotazioni=20-=20Nuovo=20script=20FlipRot=20(per=20?= =?UTF-8?q?ora=20copiata=20da=20BatchProcess,=20poi=20dovr=C3=A0=20ruotare?= =?UTF-8?q?=20i=20pezzi=20e=20posizionarli=20in=20base=20alla=20migliore?= =?UTF-8?q?=20posizione=20di=20lavoro)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BatchProcessNew.lua | 11 +- FlipRot.lua | 940 ++++++++++++++++++++++++++++++ LuaLibs/BeamExec.lua | 47 +- Strategies/GeneralParameters.json | 25 +- 4 files changed, 988 insertions(+), 35 deletions(-) create mode 100644 FlipRot.lua diff --git a/BatchProcessNew.lua b/BatchProcessNew.lua index 312d3d8..5a0947c 100644 --- a/BatchProcessNew.lua +++ b/BatchProcessNew.lua @@ -214,9 +214,6 @@ end local sLog = 'BatchProcess : ' .. BEAM.FILE .. ', ' .. ( BEAM.MACHINE or EgtGetCurrMachineName()) .. ', ' .. sFlag EgtOutLog( sLog) --- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta -local bCalcBestPieceUnloadPosition = true or BEAM.FLAG == 10 - -- Dati dei file -- TODO spostare a quando flag ~= 6 e 9 local sDir, sTitle = EgtSplitPath( BEAM.FILE) @@ -551,7 +548,7 @@ if bToProcess then end -- Sistemo le travi nel grezzo - local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, bCalcBestPieceUnloadPosition) + local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, false) if not bPbOk then BEAM.ERR = 18 BEAM.MSG = sPbErr @@ -640,7 +637,7 @@ if bToProcess then BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig) PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON) TIMER:stopElapsed('Json') - PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition) + PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], false) -- sovramateriale in testa al pezzo local dDeltaS = max( PARTS[i].dPosX - ( dBarLen - dLen), 0) @@ -693,8 +690,8 @@ if bToProcess then -- TODO gestire errori e messaggi di ritorno in questo caso if not GetDataConfig() then return end - BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) - BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) + BeamExec.GetProcessings( PARTS, false) + BeamExec.GetCombinationMatrix( PARTS, false) BeamExec.ProcessMachinings( PARTS) -- si cancella gruppo temporaneo contenente entità da cancellare diff --git a/FlipRot.lua b/FlipRot.lua new file mode 100644 index 0000000..312d3d8 --- /dev/null +++ b/FlipRot.lua @@ -0,0 +1,940 @@ +-- 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) + +-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta +local bCalcBestPieceUnloadPosition = true or BEAM.FLAG == 10 + +-- 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.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, bCalcBestPieceUnloadPosition) + 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') + PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition) + + -- 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, bCalcBestPieceUnloadPosition) + BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) + BeamExec.ProcessMachinings( PARTS) + + -- si cancella gruppo temporaneo contenente entità da cancellare + EgtErase( idTempGroup) + + 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 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 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 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 + + -- 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') diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 870d833..6b7d246 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -251,28 +251,28 @@ function BeamExec.GetStrategiesFromJSONinBD( sAISetupConfigName) end end +-- TODO prevedere parametri per preferire carico del pezzo verticale oppure orizzontale? ------------------------------------------------------------------------------------------------------------- -- funzione che controlla validità delle combinazioni proposte -local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection, GeneralParameters, bCalcBestPieceUnloadPosition) +local function IsCombinationAvailable( sCombination, nUnloadPos, GeneralParameters, bIsFlipRot) -- PREROTATION : flip-rot, si considerano tutte le posizioni possibili, a meno che non si voglia come da BTL - if bCalcBestPieceUnloadPosition and GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' then + if bIsFlipRot and GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' then local nRotation90 = EgtIf( nUnloadPos + 1 > 4, nUnloadPos + 1 - 4, nUnloadPos + 1) local nRotation180 = EgtIf( nUnloadPos + 2 > 4, nUnloadPos + 2 - 4, nUnloadPos + 2) local nExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3) - if not bSquareSection and ( nUnloadPos == 2 or nUnloadPos == 4) then + -- se fase di unload disabilitata e soluzioni con terza rotazione sempre disabilitate + if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, nExtraRotation, nExtraRotation) == '1' then + return false + elseif GeneralParameters.GEN_sPiecesLoadingPosition == 'STD_PRE_ROTATION' and ( nUnloadPos == 2 or nUnloadPos == 4) then return false else - if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, nExtraRotation, nExtraRotation) == '1' then + if ( not BeamData.ROT90 or GeneralParameters.GEN_sPiecesLoadingPosition == 'STD_PRE_ROTATION') and string.sub( sCombination, nRotation90, nRotation90) == '1' then + return false + elseif not BeamData.ROT180 and string.sub( sCombination, nRotation180, nRotation180) == '1' then return false else - if not BeamData.ROT90 and string.sub( sCombination, nRotation90, nRotation90) == '1' then - return false - elseif not BeamData.ROT180 and string.sub( sCombination, nRotation180, nRotation180) == '1' then - return false - else - return true - end + return true end end -- se invece si è nel caso standard di calcolo @@ -286,7 +286,7 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection, end -- STANDARD : posizione di scarico come posizionamento iniziale else - local ExtraRotation = nUnloadPos + 3 + local ExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3) if nUnloadPos ~= 1 then return false elseif string.sub( sCombination, nUnloadPos, nUnloadPos) == '1' and string.sub( sCombination, ExtraRotation, ExtraRotation) == '0' then @@ -305,12 +305,16 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection, end ------------------------------------------------------------------------------------------------------------- -function BeamExec.GetAvailableCombinations( PartInfo, bCalcBestPieceUnloadPosition) +function BeamExec.GetAvailableCombinations( PartInfo, bIsFlipRot) local CombinationList = {} CombinationList.Rotations = {0, 0, 0, 0} -- indice rotazione attiva, per calcolo collect feature + local nCycles = 1 + + -- se si sta calcolando il migliore posizionamento del pezzo, verifico se sono ammesse le combinazioni con pezzo invertito + if bIsFlipRot and PartInfo.GeneralParameters.GEN_bAllowPieceInversion then + nCycles = 2 + end - -- se sto effettivamente calcolando, il pezzo è già in posizione e non può essere invertito. Se sono in preverifica, allora devo considerare anche eventuali inversioni del pezzo - local nCycles = EgtIf( bCalcBestPieceUnloadPosition and PartInfo.GeneralParameters.GEN_sPiecesLoadingPosition == 'BEST_POSITION', 2, 1) -- verifico tutte le combinazioni che possono essere considerate for nInvertIndex = 1, nCycles do for nUnloadPos = 1, 4 do @@ -318,7 +322,7 @@ function BeamExec.GetAvailableCombinations( PartInfo, bCalcBestPieceUnloadPositi local nBitIndexCombination = BeamLib.DecimalToBinary( i) local sBitIndexCombination = BeamLib.CalculateStringBinaryFormat( nBitIndexCombination, 4) -- si calcolano le combinazioni all'inizio, ottimizzando calcolo della collect solo nelle rotazioni che possono essere considerate - if IsCombinationAvailable( sBitIndexCombination, nUnloadPos, PartInfo.bSquareSection, PartInfo.GeneralParameters, bCalcBestPieceUnloadPosition) then + if IsCombinationAvailable( sBitIndexCombination, nUnloadPos, PartInfo.GeneralParameters, bIsFlipRot) then local Combination = {} Combination.sBitIndexCombination = sBitIndexCombination Combination.nUnloadPos = nUnloadPos @@ -354,7 +358,7 @@ end ------------------------------------------------------------------------------------------------------------- -- *** funzioni posizionamento pezzi all'interno della barra *** ------------------------------------------------------------------------------------------------------------- -function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bCalcBestPieceUnloadPosition) +function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bIsFlipRot) -- gruppo per geometrie temporanee local idTempGroup = BeamLib.GetTempGroup() @@ -504,7 +508,7 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, b BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig) PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON) TIMER:stopElapsed('Json') - PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition) + PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bIsFlipRot) PARTS[i].idTempGroup = idTempGroup else @@ -1554,10 +1558,10 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bRePro end ------------------------------------------------------------------------------------------------------------- -function BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) +function BeamExec.GetCombinationMatrix( PARTS, bIsFlipRot) -- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni for nPart = 1, #PARTS do - local nCycles = EgtIf( bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION', 2, 1) + local nCycles = EgtIf( bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion, 2, 1) -- per ogni inversione for nInvertIndex = 1, nCycles do -- calcolo della migliore strategia per ogni rotazione del pezzo @@ -1574,7 +1578,8 @@ function BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw) PARTS[nPart].b3Part = EgtGetBBoxGlob( PARTS[nPart].idBoxTm, GDB_BB.STANDARD) end - if bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' then + -- se bisogna invertire + if bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then -- inversione del pezzo testa-coda BeamLib.InvertRawPart( PARTS[nPart], 2) -- aggiorno info pezzo diff --git a/Strategies/GeneralParameters.json b/Strategies/GeneralParameters.json index 077696b..d727430 100644 --- a/Strategies/GeneralParameters.json +++ b/Strategies/GeneralParameters.json @@ -1,10 +1,10 @@ [ { - "nGroup": "MACHINE", + "nGroup": "PIECE LOADING", "sName": "GEN_sPiecesLoadingPosition", "sNameNge": "GEN_PIECES_LOADING", - "sValue": "BEST_POSITION", + "sValue": "BTL_POSITION", "sDescriptionShort": "Part loading position", "sDescriptionLong": "", "sType": "combo", @@ -12,24 +12,35 @@ "Choices": [ { "sValue": "BTL_POSITION", - "sDescriptionShort": "Last piece position as BTL", + "sDescriptionShort": "Loading position from BTL, no pre-rotation", "sDescriptionLong": "", "sMessageId": "" }, { - "sValue": "BEST_ROTATION", - "sDescriptionShort": "Allow piece rotations", + "sValue": "STD_PRE_ROTATION", + "sDescriptionShort": "Get Best loading position from 0° and 180°", "sDescriptionLong": "", "sMessageId": "" }, { - "sValue": "BEST_POSITION", - "sDescriptionShort": "Allow piece rotation and inversion", + "sValue": "FULL_PRE_ROTATION", + "sDescriptionShort": "Get Best loading position in each piece rotation", "sDescriptionLong": "", "sMessageId": "" } ] }, + { + "nGroup": "PIECE LOADING", + "sName": "GEN_bAllowPieceInversion", + "sNameNge": "ADMIT_INVERSION", + "sValue": "true", + "sDescriptionShort": "Allow piece inversion", + "sDescriptionLong": "", + "sType": "b", + "sMessageId": " ", + "sMinUserLevel": "1" + }, { "nGroup": "MACHINE", "sName": "GEN_sPieceRotation", From 02390c2e9b5940bd9bf923beaee1c9334c156e58 Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Tue, 24 Feb 2026 16:50:48 +0100 Subject: [PATCH 2/4] - Tolte pre-rotazioni dalla Process - FlipRot modificata, ora ereditata dalla Process --- FlipRot.lua | 1028 ++++++++++-------------------------------- LuaLibs/BeamExec.lua | 1 - Process.lua | 9 +- 3 files changed, 239 insertions(+), 799 deletions(-) diff --git a/FlipRot.lua b/FlipRot.lua index 312d3d8..631e53e 100644 --- a/FlipRot.lua +++ b/FlipRot.lua @@ -1,9 +1,13 @@ --- BatchProcessNew.lua by Egalware s.r.l. 2025/04/24 +-- Process.lua by Egalware s.r.l. 2024/04/02 +-- Gestione calcolo disposizione e lavorazioni per Travi +-- Si opera sulla macchina corrente +-- 2024/04/02 PRIMA VERSIONE + -- Intestazioni require( 'EgtBase') _ENV = EgtProtectGlobal() -EgtEnableDebug( false) +EgtEnableDebug( true) -- Imposto direttorio libreria specializzata per Travi EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua') @@ -11,22 +15,7 @@ EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua') 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 +-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi local sMachDir = EgtGetCurrMachineDir() if not sMachDir then EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR') @@ -34,10 +23,6 @@ if not sMachDir then 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 @@ -96,16 +81,75 @@ 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 +-- *** Recupero le travi selezionate *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessInputData() + -- Recupero le travi selezionate + local nId = EgtGetFirstPart() + while nId do + table.insert( PARTS, { nInd = #PARTS + 1, id = nId, sName = ( EgtGetName( nId) or ( 'Id=' .. tonumber( nId)))}) + nId = EgtGetNextPart( nId) + end + if #PARTS == 0 then + EgtOutBox( 'Non sono state selezionate travi', 'Lavora Travi', 'ERROR') + return false + else + local sOut = '' + for i = 1, #PARTS do + sOut = sOut .. PARTS[i].sName .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Travi selezionate : ' .. sOut, 1) + end + + -- Ne recupero e verifico 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 + EgtOutBox( 'Box non definito per la trave ' .. PARTS[i].sName, 'Lavora Travi', 'ERROR') + return false + else + PARTS[i].b3PartOriginal = b3Solid + end + end + dRawW = PARTS[1].b3PartOriginal:getDimY() + dRawH = PARTS[1].b3PartOriginal:getDimZ() + local vBeamErr = {} + for i = 2, #PARTS do + local dDimW = PARTS[i].b3PartOriginal:getDimY() + local dDimH = PARTS[i].b3PartOriginal:getDimZ() + if ( abs( dDimW - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL) and + ( abs( dDimH - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 10 * 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' + EgtDeselectPartObjs( PARTS[vBeamErr[i]].id) + table.remove( PARTS, vBeamErr[i]) + end + EgtOutLog( sOut, 1) + EgtOutBox( sOut, 'Lavora Travi', 'INFO') + EgtDraw() + return false + end + EgtDeselectAll() + + return true +end + + +------------------------------------------------------------------------------------------------------------- local function GetDataConfig() -- recupero utensili dal magazzino BeamExec.GetToolsFromDB() @@ -113,604 +157,149 @@ local function GetDataConfig() 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 +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle travi nel grezzo *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessBeams() + -- Determinazione minimo grezzo scaricabile + BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) -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') + -- Lunghezza totale delle travi + local dTotLen = 0 + for i = 1, #PARTS - 1 do + dTotLen = dTotLen + PARTS[i].b3PartOriginal:getDimX() end -end + dTotLen = dTotLen + max( PARTS[#PARTS].b3PartOriginal:getDimX(), BeamData.dMinRaw) + local dAddLen = BeamData.OVM_HEAD + ( #PARTS - 1) * BeamData.OVM_MID + EgtOutLog( 'Ltot : '..EgtNumToString( dTotLen, 1) .. ' Lagg : '..EgtNumToString( dAddLen, 1)..' MinUnloadRaw : '.. EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 1), 1) -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') + -- Richiedo lunghezza del grezzo, sovramateriale di testa, forzatura verticale e ordinamento automatico secondo la lunghezza + local vsVal = EgtDialogBox( 'Lavora Travi' .. ' (Ltot='..EgtNumToString( dTotLen + dAddLen + 0.5, 0).. + ', Lmax='..EgtNumToString( BeamData.MAX_RAW, 0)..',MinUlr='..EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 0)..')', + --{'Lunghezza grezzo', EgtNumToString( BeamData.STD_RAW, 0)}, -- TODO RIPRISTINARE + {'Lunghezza grezzo', EgtNumToString( 0)}, + {'Sovramateriale di testa', EgtNumToString( BeamData.OVM_HEAD, 0)}, + {'Offset intermedio', EgtNumToString( BeamData.OVM_MID, 0)}, + {'Forza sezione verticale', ' CB:true,*false'}, + {'Ordina per lunghezza', ' CB:true,*false'}, + {'Calcolo Lavorazioni', ' CB:*Da progetto,Ricalcolo standard,Ricalcolo IA'}) + if not vsVal then + EgtDraw() + return 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') + local dRawL = EgtEvalNumExpr( vsVal[1]) + if not dRawL then + local sOut = 'Lunghezza grezzo errata : ' .. vsVal[1] + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + if dRawL < GEO.EPS_SMALL then dRawL = dTotLen + dAddLen + 0.5 end + dRawL = min( dRawL, BeamData.MAX_RAW) + local dOvmHead = EgtEvalNumExpr( vsVal[2]) + if not dOvmHead then + local sOut = 'Sovramateriale di testa errato : ' .. vsVal[2] + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + local dOvmMid = EgtEvalNumExpr( vsVal[3]) + if not dOvmMid then + local sOut = 'Offset intermedio : ' .. vsVal[3] + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + + -- Sistemo sezione barra con travi + local bVert = ( vsVal[4] == 'true') + if bVert then + if dRawW > dRawH then dRawW, dRawH = dRawH, dRawW end + end + EgtOutLog( 'Lraw : ' .. EgtNumToString( dRawL, 1) .. ' Lovm : '.. EgtNumToString( dOvmHead, 1), 1) + + -- 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 + 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) .. ') ' + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + 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 + 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) .. ')' + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + 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 + 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) .. ')' + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + + -- Se richiesto, ordino le travi in senso di lunghezza crescente + local bOrd = ( vsVal[5] == 'true') + if bOrd then + table.sort( PARTS, function( B1, B2) + if abs( B1.b3PartOriginal:getDimX() - B2.b3PartOriginal:getDimX()) < 1 then + return B1.nInd < B2.nInd + else + return B1.b3PartOriginal:getDimX() < B2.b3PartOriginal:getDimX() + end + end) + end + do + local sOut = '' + for i = 1, #PARTS do + sOut = sOut .. PARTS[i].sName .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Travi ordinate : ' .. sOut, 1) + end + + -- Sistemo le travi nel grezzo + local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, false) + if not bOk then + EgtOutLog( sErr) + EgtOutBox( sErr, 'Lavora Travi', 'ERROR') return false end - DestFh:write( sData) - DestFh:close() return true end ------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle lavorazioni nelle travi *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessFeatures() --- 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) - --- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta -local bCalcBestPieceUnloadPosition = true or BEAM.FLAG == 10 - --- 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.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, bCalcBestPieceUnloadPosition) - 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') - PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition) - - -- 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, bCalcBestPieceUnloadPosition) - BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) + BeamExec.GetProcessings( PARTS, false) + BeamExec.GetCombinationMatrix( PARTS, false) BeamExec.ProcessMachinings( PARTS) - - -- si cancella gruppo temporaneo contenente entità da cancellare - EgtErase( idTempGroup) - + local nErrCnt = 0 + local nWarnCnt = 0 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 + sMsg = RESULT[i].ChosenStrategy.sInfo elseif RESULT[i].sType == 'Part' then sMsg = RESULT[i].sMsg end @@ -718,17 +307,8 @@ if bToProcess then 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 or 1) + 1 - BEAM.CUTID = RESULT[i].idCut - BEAM.TASKID = RESULT[i].idTask - WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) + sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg or '') + -- trovata almeno una strategia ma nessuna applicabile oppure non trovata alcuna strategia elseif RESULT[i].sType == 'Feature' and ( ( RESULT[i].ChosenStrategy.sStatus == 'Not-Applicable') @@ -739,202 +319,66 @@ if bToProcess 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 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 + -- nulla da segnalare + -- feature incompleta e altro elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then nWarnCnt = nWarnCnt + 1 + sMsg = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg 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 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 - -- TODO: se scarico a caduta (-101, -102) le lavorazioni dopo separazione vanno disattivate. Scrivere info feature incompleta su quelle feature + -- cancello gruppo temporaneo + local idTempGroup = BeamLib.GetTempGroup() + EgtErase( idTempGroup) - -- 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) + EgtOutBox( sOutput, 'Lavora Travi', 'ERRORS') + return false elseif nWarnCnt > 0 then - PostWarnView( 19, sOutput) + EgtOutBox( sOutput, 'Lavora Travi', 'WARNINGS') + return true 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 + return true end +------------------------------------------------------------------------------------------------------------- +-- *** Esecuzione *** +------------------------------------------------------------------------------------------------------------- + +-- calcolo tempo esecuzione +TIMER:start() +EgtOutLog( ' Execution timer started') + +-- script principale + +if not MyProcessInputData() then return 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 +BeamLib.CreateTempGroup() + +if not MyProcessBeams() then return end + +if not GetDataConfig() then return end + +-- Abilito Vmill +EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1') + +MyProcessFeatures() + -- 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') diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 6b7d246..e9a66fc 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -970,7 +970,6 @@ local function CalculateStrategies( vProcSingleRot, Part) -- eseguo file config con i parametri di default local CurrentStrategy = {} CurrentStrategy = RunStrategyLibraries( Proc.AvailableStrategies[nIndexCurrentStrategy].sStrategyId) - -- TODO in caso di ulteriore ciclo dovuto a errori imprevisti, controllare se questa strategia è quella che ha dato errore e disabilitarla senza calcolare nulla -- controllo che le librerie siano state effettivamente caricate if CurrentStrategy.Config and CurrentStrategy.Script then -- eseguo la strategia solo come calcolo fattibilità e voto. Non si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati diff --git a/Process.lua b/Process.lua index 1ef58aa..344415e 100644 --- a/Process.lua +++ b/Process.lua @@ -15,9 +15,6 @@ EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua') EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua') EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua') --- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta -local bCalcBestPieceUnloadPosition = true - -- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi local sMachDir = EgtGetCurrMachineDir() if not sMachDir then @@ -290,7 +287,7 @@ local function MyProcessBeams() end -- Sistemo le travi nel grezzo - local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, bCalcBestPieceUnloadPosition) + local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, false) if not bOk then EgtOutLog( sErr) EgtOutBox( sErr, 'Lavora Travi', 'ERROR') @@ -305,8 +302,8 @@ end ------------------------------------------------------------------------------------------------------------- local function MyProcessFeatures() - BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) - BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) + BeamExec.GetProcessings( PARTS, false) + BeamExec.GetCombinationMatrix( PARTS, false) BeamExec.ProcessMachinings( PARTS) local nErrCnt = 0 local nWarnCnt = 0 From c6ced91b149c900ecb1eab5a81bf1e84da934f54 Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Mon, 2 Mar 2026 12:35:12 +0100 Subject: [PATCH 3/4] =?UTF-8?q?-=20Aggiunti=20parametri=20configurabili=20?= =?UTF-8?q?GEN=5FbTestAlternative=20e=20GEN=5FbGetAlternativesNesting2D=20?= =?UTF-8?q?per=20testare=20altre=20alternative=20valide=20-=20Aggiunta=20f?= =?UTF-8?q?unzione=20dedicata=20alla=20creazione=20del=20gruppo=20ausiliar?= =?UTF-8?q?io=20al=20MachGroup=20-=20Alla=20funzione=20BeamExec.GetCombina?= =?UTF-8?q?tionListFromMatrix=20si=20pu=C3=B2=20passare=20una=20lista=20co?= =?UTF-8?q?n=20le=20sole=20combinazioni=20da=20provare=20-=20Nella=20BeamE?= =?UTF-8?q?xec=20aggiunta=20funzione=20ProcessAlternatives=20solo=20per=20?= =?UTF-8?q?provare=20le=20alternative=20(simile=20alla=20ProcessFeatures,?= =?UTF-8?q?=20ma=20completamente=20slegata).=20La=20ProcessFeature=20decid?= =?UTF-8?q?e=20il=20posizionamento=20iniziale,=20la=20ProcessAlternatives?= =?UTF-8?q?=20verifica=20solamente=20le=20alternative.=20-=20FlipRot=20ade?= =?UTF-8?q?guata=20a=20nuovo=20funzionamento=20-=20Altre=20piccole=20migli?= =?UTF-8?q?orie=20varie=20-=20TODO=20:=20=20=20=201)=20manca=20la=20parte?= =?UTF-8?q?=20per=20settare=20nelle=20info=20pezzo=20la=20rotazione=20iniz?= =?UTF-8?q?iale=20(per=20vista=20in=20Aedifica)=20e=20le=20altre=20alterna?= =?UTF-8?q?tive=20(per=20ottimizzazione=20in=20nesting)=20=20=20=202)=20In?= =?UTF-8?q?=20FlipRot=20gestire=20interazione=20con=20Aedifica,=20dato=20c?= =?UTF-8?q?he=20verr=C3=A0=20lanciato=20direttamente=20dal=20programma=20(?= =?UTF-8?q?per=20ora=20funziona=20lanciato=20come=20la=20Process)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FlipRot.lua | 188 ++-------- LuaLibs/BeamExec.lua | 568 +++++++++++++++++++++++++----- LuaLibs/BeamLib.lua | 27 +- LuaLibs/MachiningLib.lua | 4 +- Strategies/GeneralParameters.json | 22 ++ 5 files changed, 536 insertions(+), 273 deletions(-) diff --git a/FlipRot.lua b/FlipRot.lua index 631e53e..ff24e16 100644 --- a/FlipRot.lua +++ b/FlipRot.lua @@ -7,7 +7,7 @@ -- Intestazioni require( 'EgtBase') _ENV = EgtProtectGlobal() -EgtEnableDebug( true) +EgtEnableDebug( false) -- Imposto direttorio libreria specializzata per Travi EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua') @@ -82,73 +82,27 @@ local BeamData = require( 'BeamDataNew') local BeamExec = require( 'BeamExec') local BeamLib = require( 'BeamLib') --- Variabili di modulo -local dRawW -local dRawH - ------------------------------------------------------------------------------------------------------------- --- *** Recupero le travi selezionate *** +-- *** Recupero trave (E' SEMPRE E SOLO UNA) *** ------------------------------------------------------------------------------------------------------------- local function MyProcessInputData() - - -- Recupero le travi selezionate + -- Recupero il pezzo e i suoi dati local nId = EgtGetFirstPart() - while nId do + if nId then table.insert( PARTS, { nInd = #PARTS + 1, id = nId, sName = ( EgtGetName( nId) or ( 'Id=' .. tonumber( nId)))}) - nId = EgtGetNextPart( nId) - end - if #PARTS == 0 then - EgtOutBox( 'Non sono state selezionate travi', 'Lavora Travi', 'ERROR') - return false - else - local sOut = '' - for i = 1, #PARTS do - sOut = sOut .. PARTS[i].sName .. ', ' - end - sOut = sOut:sub( 1, -3) - EgtOutLog( 'Travi selezionate : ' .. sOut, 1) - end - - -- Ne recupero e verifico le dimensioni - for i = 1, #PARTS do - local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box') + local Ls = EgtGetFirstNameInGroup( PARTS[1].id, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then - EgtOutBox( 'Box non definito per la trave ' .. PARTS[i].sName, 'Lavora Travi', 'ERROR') return false - else - PARTS[i].b3PartOriginal = b3Solid end - end - dRawW = PARTS[1].b3PartOriginal:getDimY() - dRawH = PARTS[1].b3PartOriginal:getDimZ() - local vBeamErr = {} - for i = 2, #PARTS do - local dDimW = PARTS[i].b3PartOriginal:getDimY() - local dDimH = PARTS[i].b3PartOriginal:getDimZ() - if ( abs( dDimW - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL) and - ( abs( dDimH - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 10 * 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' - EgtDeselectPartObjs( PARTS[vBeamErr[i]].id) - table.remove( PARTS, vBeamErr[i]) - end - EgtOutLog( sOut, 1) - EgtOutBox( sOut, 'Lavora Travi', 'INFO') - EgtDraw() + PARTS[1].b3PartOriginal = b3Solid + else return false end - EgtDeselectAll() return true end - ------------------------------------------------------------------------------------------------------------- local function GetDataConfig() -- recupero utensili dal magazzino @@ -161,124 +115,23 @@ end -- *** Inserimento delle travi nel grezzo *** ------------------------------------------------------------------------------------------------------------- local function MyProcessBeams() + -- Lunghezza totale delle travi + local dLen = PARTS[1].b3PartOriginal:getDimX() + local dRawW = PARTS[1].b3PartOriginal:getDimY() + local dRawH = PARTS[1].b3PartOriginal:getDimZ() + -- Determinazione minimo grezzo scaricabile BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) - -- Lunghezza totale delle travi - local dTotLen = 0 - for i = 1, #PARTS - 1 do - dTotLen = dTotLen + PARTS[i].b3PartOriginal:getDimX() - end - dTotLen = dTotLen + max( PARTS[#PARTS].b3PartOriginal:getDimX(), BeamData.dMinRaw) - local dAddLen = BeamData.OVM_HEAD + ( #PARTS - 1) * BeamData.OVM_MID - EgtOutLog( 'Ltot : '..EgtNumToString( dTotLen, 1) .. ' Lagg : '..EgtNumToString( dAddLen, 1)..' MinUnloadRaw : '.. EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 1), 1) + local dOvmHead = BeamData.OVM_HEAD or 10 + local dOvmMid = BeamData.OVM_MID or 10 - -- Richiedo lunghezza del grezzo, sovramateriale di testa, forzatura verticale e ordinamento automatico secondo la lunghezza - local vsVal = EgtDialogBox( 'Lavora Travi' .. ' (Ltot='..EgtNumToString( dTotLen + dAddLen + 0.5, 0).. - ', Lmax='..EgtNumToString( BeamData.MAX_RAW, 0)..',MinUlr='..EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 0)..')', - --{'Lunghezza grezzo', EgtNumToString( BeamData.STD_RAW, 0)}, -- TODO RIPRISTINARE - {'Lunghezza grezzo', EgtNumToString( 0)}, - {'Sovramateriale di testa', EgtNumToString( BeamData.OVM_HEAD, 0)}, - {'Offset intermedio', EgtNumToString( BeamData.OVM_MID, 0)}, - {'Forza sezione verticale', ' CB:true,*false'}, - {'Ordina per lunghezza', ' CB:true,*false'}, - {'Calcolo Lavorazioni', ' CB:*Da progetto,Ricalcolo standard,Ricalcolo IA'}) - if not vsVal then - EgtDraw() - return - end - local dRawL = EgtEvalNumExpr( vsVal[1]) - if not dRawL then - local sOut = 'Lunghezza grezzo errata : ' .. vsVal[1] - EgtOutLog( sOut) - EgtOutBox( sOut, 'Lavora Travi', 'WARNING') - EgtDraw() - return false - end - if dRawL < GEO.EPS_SMALL then dRawL = dTotLen + dAddLen + 0.5 end - dRawL = min( dRawL, BeamData.MAX_RAW) - local dOvmHead = EgtEvalNumExpr( vsVal[2]) - if not dOvmHead then - local sOut = 'Sovramateriale di testa errato : ' .. vsVal[2] - EgtOutLog( sOut) - EgtOutBox( sOut, 'Lavora Travi', 'WARNING') - EgtDraw() - return false - end - local dOvmMid = EgtEvalNumExpr( vsVal[3]) - if not dOvmMid then - local sOut = 'Offset intermedio : ' .. vsVal[3] - EgtOutLog( sOut) - EgtOutBox( sOut, 'Lavora Travi', 'WARNING') - EgtDraw() - return false - end + local dRawL = max( dLen + dOvmHead + dOvmMid, BeamData.dMinRaw) - -- Sistemo sezione barra con travi - local bVert = ( vsVal[4] == 'true') - if bVert then - if dRawW > dRawH then dRawW, dRawH = dRawH, dRawW end - end - EgtOutLog( 'Lraw : ' .. EgtNumToString( dRawL, 1) .. ' Lovm : '.. EgtNumToString( dOvmHead, 1), 1) - - -- 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 - 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) .. ') ' - EgtOutLog( sOut) - EgtOutBox( sOut, 'Lavora Travi', 'WARNING') - EgtDraw() - return false - 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 - 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) .. ')' - EgtOutLog( sOut) - EgtOutBox( sOut, 'Lavora Travi', 'WARNING') - EgtDraw() - return false - 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 - 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) .. ')' - EgtOutLog( sOut) - EgtOutBox( sOut, 'Lavora Travi', 'WARNING') - EgtDraw() - return false - end - - -- Se richiesto, ordino le travi in senso di lunghezza crescente - local bOrd = ( vsVal[5] == 'true') - if bOrd then - table.sort( PARTS, function( B1, B2) - if abs( B1.b3PartOriginal:getDimX() - B2.b3PartOriginal:getDimX()) < 1 then - return B1.nInd < B2.nInd - else - return B1.b3PartOriginal:getDimX() < B2.b3PartOriginal:getDimX() - end - end) - end - do - local sOut = '' - for i = 1, #PARTS do - sOut = sOut .. PARTS[i].sName .. ', ' - end - sOut = sOut:sub( 1, -3) - EgtOutLog( 'Travi ordinate : ' .. sOut, 1) - end - - -- Sistemo le travi nel grezzo - local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, false) + -- Recupero info pezzi + local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, true) if not bOk then EgtOutLog( sErr) - EgtOutBox( sErr, 'Lavora Travi', 'ERROR') return false end @@ -290,8 +143,8 @@ end ------------------------------------------------------------------------------------------------------------- local function MyProcessFeatures() - BeamExec.GetProcessings( PARTS, false) - BeamExec.GetCombinationMatrix( PARTS, false) + BeamExec.GetProcessings( PARTS, true) + BeamExec.GetCombinationMatrix( PARTS, true) BeamExec.ProcessMachinings( PARTS) local nErrCnt = 0 local nWarnCnt = 0 @@ -334,6 +187,9 @@ local function MyProcessFeatures() end end + -- si calcolano alternative + BeamExec.ProcessAlternatives( PARTS) + -- cancello gruppo temporaneo local idTempGroup = BeamLib.GetTempGroup() EgtErase( idTempGroup) diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index e9a66fc..6cae827 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -1227,8 +1227,8 @@ local function PrintFeatures( vProc, Part) end ------------------------------------------------------------------------------------------------------------- -function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) - -- recupero tutti i processing di tutti i pezzi in tutte le rotazioni +-- funzione che recupera tutti i processing di tutti i pezzi in tutte le rotazioni +function BeamExec.GetProcessings( PARTS, bIsFlipRot) -- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola EgtSetTableAreaOffset( 2000, 2000, 2000, 2000) @@ -1238,7 +1238,8 @@ function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) local vProcRot = {} -- se è prerotazione, oltre al ciclo normale, si devono verificare anche invertiti - local nCycles = EgtIf( bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION', 2, 1) + local bCalcInverted = bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion + local nCycles = EgtIf( bCalcInverted, 2, 1) -- per ogni inversione for nInvertIndex = 1, nCycles do -- per ogni rotazione @@ -1249,7 +1250,7 @@ function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) if PARTS[nPart].CombinationList.Rotations[nRotIndex] == 1 then -- recupero le feature di lavorazione della trave table.insert( vProcRot, CollectFeatures( PARTS[nPart], nIndex)) - + -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse -- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no vProcRot[nIndex] = GetFeatureInfoAndDependency( vProcRot[nIndex], PARTS[nPart]) @@ -1263,7 +1264,8 @@ function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw) PARTS[nPart].b3Part = EgtGetBBoxGlob( PARTS[nPart].idBoxTm, GDB_BB.STANDARD) end - if bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' then + -- se si devono calcolare anche gli invertiti + if bCalcInverted then -- inversione pezzo testa-coda BeamLib.InvertRawPart( PARTS[nPart], 2) -- aggiorno info pezzo @@ -1439,115 +1441,130 @@ end ------------------------------------------------------------------------------------------------------------- -- funzione che calcola le combinazioni di rotazione per lavorare la trave e sceglie la migliore -local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bReProcessEmptyChosenStrategy) +local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bReProcessEmptyChosenStrategy, BitCombinationListToReprocess) local CombinationsList = { dAllCombinationsTotalTime = 0} -- calcolo per tutte le combinazioni disponibili precedentemente verificate for i = 1, #PartInfo.CombinationList do - local bRot90, bRot180 - local SingleCombination = {} - local nUnloadPos = PartInfo.CombinationList[i].nUnloadPos - SingleCombination.nRotations = 0 - SingleCombination.dTotalTimeToMachine = 0 - SingleCombination.dTotalQuality = 0 - SingleCombination.dTotalCompletionIndex = 0 - SingleCombination.nComplete = 0 - SingleCombination.nNotComplete = 0 - SingleCombination.nNotExecute = 0 - SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination - -- TODO se pezzo invertito bisogna considerare le rotazioni nell'array dalla 5 alla 8 - SingleCombination.bPartInCombiIsInverted = PartInfo.CombinationList[i].bPartInCombiIsInverted - SingleCombination.nUnloadPos = nUnloadPos - -- creo liste dei proc suddivisi per rotazione - SingleCombination.Rot0 = {} - SingleCombination.Rot90 = {} - SingleCombination.Rot180 = {} + local bToProcess = false + -- controllo se debbano essere ricalcolate solo alcune soluzioni + if BitCombinationListToReprocess and #BitCombinationListToReprocess > 0 then + for c = 1, #BitCombinationListToReprocess do + if PartInfo.CombinationList[i].sBitIndexCombination == BitCombinationListToReprocess[c].sBitIndexCombination and + PartInfo.CombinationList[i].bPartInCombiIsInverted == BitCombinationListToReprocess[c].bPartInCombiIsInverted then + bToProcess = true + end + end + else + bToProcess = true + end + -- si riprocessano tutte a meno che non sia indicata una specifica da riprovare + if bToProcess then + local bRot90, bRot180 + local SingleCombination = {} + local nUnloadPos = PartInfo.CombinationList[i].nUnloadPos + SingleCombination.nRotations = 0 + SingleCombination.dTotalTimeToMachine = 0 + SingleCombination.dTotalQuality = 0 + SingleCombination.dTotalCompletionIndex = 0 + SingleCombination.nComplete = 0 + SingleCombination.nNotComplete = 0 + SingleCombination.nNotExecute = 0 + SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination + -- TODO se pezzo invertito bisogna considerare le rotazioni nell'array dalla 5 alla 8 + SingleCombination.bPartInCombiIsInverted = PartInfo.CombinationList[i].bPartInCombiIsInverted + SingleCombination.nUnloadPos = nUnloadPos + -- creo liste dei proc suddivisi per rotazione + SingleCombination.Rot0 = {} + SingleCombination.Rot90 = {} + SingleCombination.Rot180 = {} - -- ciclo su tutte le feature, ad eccezione dei tagli testa/coda che dipendono dal risultato delle altre - -- tagli testa e coda vengono aggiunti sempre alla fine - for nProc = 1, #ProcessingsOnPart.Rotation[1] do - -- Si controlla sempre la rotazione 1 perchè la dipendenza di una feature da un'altra non dipende dalla rotazione - -- se feature disattivata perchè eseguita da master a lei associata dichiaro comunque eseguita - if ProcessingsOnPart.Rotation[1][nProc].nFlg == 0 and ProcessingsOnPart.Rotation[1][nProc].nIndexMasterProc then - ProcessingsOnPart.Rotation[1][nProc].nIndexRotation = nUnloadPos - table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[1][nProc]) - SingleCombination.nComplete = SingleCombination.nComplete + 1 - else - if not ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) and not ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then - -- ciclo sulle rotazioni - local nNextRot = nUnloadPos + -- ciclo su tutte le feature, ad eccezione dei tagli testa/coda che dipendono dal risultato delle altre + -- tagli testa e coda vengono aggiunti sempre alla fine + for nProc = 1, #ProcessingsOnPart.Rotation[1] do + -- Si controlla sempre la rotazione 1 perchè la dipendenza di una feature da un'altra non dipende dalla rotazione + -- se feature disattivata perchè eseguita da master a lei associata dichiaro comunque eseguita + if ProcessingsOnPart.Rotation[1][nProc].nFlg == 0 and ProcessingsOnPart.Rotation[1][nProc].nIndexMasterProc then + ProcessingsOnPart.Rotation[1][nProc].nIndexRotation = nUnloadPos + table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[1][nProc]) + SingleCombination.nComplete = SingleCombination.nComplete + 1 + else local nOffsetIndex = EgtIf( SingleCombination.bPartInCombiIsInverted, 4, 0) - local ResultsList = {} - for nRotation = 1, 3 do - -- se rotazione abilitata da combinazione - if string.sub( PartInfo.CombinationList[i].sBitIndexCombination, nNextRot, nNextRot) == '1' then - local CurrProc = ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc] - -- se è ultima rotazione oppure se feature non impatta su misura laser, allora è valida e può essere effettivamente considerata - if nNextRot == nUnloadPos or not( CurrProc.bHindersLaserMeasure) then - -- se non è settata la ChosenStrtegy, provo a cercare comunque tra quelle disponibili - if not CurrProc.ChosenStrategy and bReProcessEmptyChosenStrategy then - CurrProc = GetFeatureBestStrategy( CurrProc, PartInfo) - end - -- controllo se è stata scelta una strategia - if CurrProc.ChosenStrategy then - local Proc = {} - Proc.nRotation = nNextRot - table.insert( Proc, CurrProc) - table.insert( ResultsList, Proc) + if not ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) and not ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then + -- ciclo sulle rotazioni + local nNextRot = nUnloadPos + local ResultsList = {} + for nRotation = 1, 3 do + -- se rotazione abilitata da combinazione + if string.sub( PartInfo.CombinationList[i].sBitIndexCombination, nNextRot, nNextRot) == '1' then + local CurrProc = ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc] + -- se è ultima rotazione oppure se feature non impatta su misura laser, allora è valida e può essere effettivamente considerata + if nNextRot == nUnloadPos or not( CurrProc.bHindersLaserMeasure) then + -- se non è settata la ChosenStrtegy, provo a cercare comunque tra quelle disponibili + if not CurrProc.ChosenStrategy and bReProcessEmptyChosenStrategy then + CurrProc = GetFeatureBestStrategy( CurrProc, PartInfo) + end + -- controllo se è stata scelta una strategia + if CurrProc.ChosenStrategy then + local Proc = {} + Proc.nRotation = nNextRot + table.insert( Proc, CurrProc) + table.insert( ResultsList, Proc) + end end end + nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1) end - nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1) - end - -- se la feature può essere lavorata in almeno una rotazione - if #ResultsList > 0 then - local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo) - Proc.nIndexRotation = Data.nIndexRotation - -- inserisco la Proc nell'apposita lista - if Data.nIndexRotation == nUnloadPos then - table.insert( SingleCombination.Rot0, Proc) - elseif Data.nIndexRotation == nUnloadPos + 1 then - table.insert( SingleCombination.Rot90, Proc) - bRot90 = true + -- se la feature può essere lavorata in almeno una rotazione + if #ResultsList > 0 then + local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo) + Proc.nIndexRotation = Data.nIndexRotation + -- inserisco la Proc nell'apposita lista + if Data.nIndexRotation == nUnloadPos then + table.insert( SingleCombination.Rot0, Proc) + elseif Data.nIndexRotation == nUnloadPos + 1 then + table.insert( SingleCombination.Rot90, Proc) + bRot90 = true + else + table.insert( SingleCombination.Rot180, Proc) + bRot180 = true + end + + SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + Data.dTimeToMachine + SingleCombination.dTotalQuality = SingleCombination.dTotalQuality + Data.dQuality + SingleCombination.dTotalCompletionIndex = SingleCombination.dTotalCompletionIndex + Data.dCompletionIndex + SingleCombination.nComplete = SingleCombination.nComplete + EgtIf( Data.bComplete, 1, 0) + SingleCombination.nNotComplete = SingleCombination.nNotComplete + EgtIf( Data.bNotComplete, 1, 0) + SingleCombination.nNotExecute = SingleCombination.nNotExecute + EgtIf( Data.bNotApplicable, 1, 0) + SingleCombination.nIndexInCombinationList = i + SingleCombination.nIndexRotation = nUnloadPos else - table.insert( SingleCombination.Rot180, Proc) - bRot180 = true + ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nIndexRotation = nUnloadPos + ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nFlg = 0 + table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc]) + SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1 end - - SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + Data.dTimeToMachine - SingleCombination.dTotalQuality = SingleCombination.dTotalQuality + Data.dQuality - SingleCombination.dTotalCompletionIndex = SingleCombination.dTotalCompletionIndex + Data.dCompletionIndex - SingleCombination.nComplete = SingleCombination.nComplete + EgtIf( Data.bComplete, 1, 0) - SingleCombination.nNotComplete = SingleCombination.nNotComplete + EgtIf( Data.bNotComplete, 1, 0) - SingleCombination.nNotExecute = SingleCombination.nNotExecute + EgtIf( Data.bNotApplicable, 1, 0) - SingleCombination.nIndexInCombinationList = i - SingleCombination.nIndexRotation = nUnloadPos else - ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nIndexRotation = nUnloadPos - ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nFlg = 0 - table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc]) - SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1 - end - else - if ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) then - SingleCombination.nIndexHeadCutInVProc = nProc - elseif ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then - SingleCombination.nIndexTailCutInVProc = nProc + if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then + SingleCombination.nIndexHeadCutInVProc = nProc + elseif ID.IsTailCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then + SingleCombination.nIndexTailCutInVProc = nProc + end end end end + -- aggiungo rotazioni + SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0) + + -- aggiungo tempo totale considerando le rotazioni -- TODO per il momento la rotazione impiega 1 minuto. Serve configurare? + SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + ( SingleCombination.nRotations * 1) + + -- aggiungo la combinazione all'elenco delle combinazioni disponibili + table.insert( CombinationsList, SingleCombination) + -- aggiorno tempo totale di tutte le combinazioni + CombinationsList.dAllCombinationsTotalTime = CombinationsList.dAllCombinationsTotalTime + SingleCombination.dTotalTimeToMachine end - -- aggiungo rotazioni - SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0) - - -- aggiungo tempo totale considerando le rotazioni -- TODO per il momento la rotazione impiega 1 minuto. Serve configurare? - SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + ( SingleCombination.nRotations * 1) - - -- aggiungo la combinazione all'elenco delle combinazioni disponibili - table.insert( CombinationsList, SingleCombination) - -- aggiorno tempo totale di tutte le combinazioni - CombinationsList.dAllCombinationsTotalTime = CombinationsList.dAllCombinationsTotalTime + SingleCombination.dTotalTimeToMachine end -- si calsola il total rating @@ -1903,5 +1920,362 @@ function BeamExec.ProcessMachinings( PARTS) return ( nTotErr == 0), RESULT end +------------------------------------------------------------------------------------------------------------- +function BeamExec.ProcessAlternatives( PARTS) + -- ciclo sui pezzi + local nTotErr = 0 + local Stats = {} + local BestCombination = {} + local nPart = 1 + local nOrd = 1 + local nMaxReProcessCycles = EgtClamp( PARTS[nPart].GeneralParameters.GEN_nMaxReProcessCycles, 1, 3) + local bTryToReProcess = false + + -- se non serve trovare altre soluzioni, si esce subito + if not PARTS[nPart].GeneralParameters.GEN_bTestAlternative or not PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then + return + end + + -- si analizzano le alternative solo del primo pezzo (la FlipRot viene chiamata sempre con un solo pezzo) + local nCycles = 1 + + -- si copia il MachGroup originale + local nOriginalMachGroup = EgtGetCurrMachGroup() + local sMachGroupName = EgtGetMachGroupName( nOriginalMachGroup) + local sTempMachGroupName = sMachGroupName .. '_A' + + local nTempMachGroupName = EgtCopyMachGroup( sMachGroupName, sTempMachGroupName) + EgtSetCurrMachGroup( nTempMachGroupName) + EgtRemoveAllOperations() + BeamLib.CreateAddGroup( PARTS[nPart].id, sTempMachGroupName) + -- si aggiorna il raw dopo averlo copiato + PARTS[nPart].idRaw = EgtGetFirstRawPart() + + -- si riporta pezzo in posizione iniziale + -- se combinazione prevedeva inversione, si rigira il pezzo + if PARTS[nPart].bPartInCombiIsInverted then + BeamLib.InvertRawPart( PARTS[nPart], -2) + end + -- si ribalta il pezzo in posizione iniziale + BeamLib.RotateRawPart( PARTS[nPart], 1 - PARTS[nPart].nInitialPosition) + + local TotalCombiToTest = {} + -- se serve calcolare soluzione alternativa ruotata di 90° + if PARTS[nPart].GeneralParameters.GEN_bTestAlternative and not PARTS[nPart].bSquareSection then + local CombinationListToCheck = {} + for i = 1, #PARTS[nPart].CombinationList do + local nUnloadPos = PARTS[nPart].nInitialPosition + local nOtherSimilarUnloadPos = EgtIf( nUnloadPos + 2 > 4, nUnloadPos + 2 - 4, nUnloadPos + 2) + -- restano abilitate soluzioni ruotate di 90° o 270° rispetto alla migliore soluzione trovata nella prima analisi + if PARTS[nPart].CombinationList[i].nUnloadPos ~= nUnloadPos and PARTS[nPart].CombinationList[i].nUnloadPos ~= nOtherSimilarUnloadPos then + table.insert( CombinationListToCheck, { sBitIndexCombination = PARTS[nPart].CombinationList[i].sBitIndexCombination, + bPartInCombiIsInverted = PARTS[nPart].CombinationList[i].bPartInCombiIsInverted}) + end + end + -- se c'è almeno una combinazione da testare + if #CombinationListToCheck > 0 then + table.insert( TotalCombiToTest, CombinationListToCheck) + end + end + + -- se serve calcolare posizione per ottimizzazione tagli in nesting (le soluzioni non possono avere ribaltamenti) + if PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then + -- POSIZIONE 0 (e invertito) + local sCombinationToCheck = BeamLib.StringReplaceChar( '0000', PARTS[nPart].nInitialPosition, "1") + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}}) + if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}}) + end + + -- POSIZIONE 180 (e invertito) + if PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition == 'STD_PRE_ROTATION' then + local nOtherPosition = EgtIf( PARTS[nPart].nInitialPosition + 2 > 4, PARTS[nPart].nInitialPosition + 2 - 4, PARTS[nPart].nInitialPosition + 2) + sCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1") + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}}) + if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}}) + end + end + -- POSIZIONE 90/270 (e invertito) + if PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition == 'FULL_PRE_ROTATION' then + local nOtherPosition = EgtIf( PARTS[nPart].nInitialPosition + 1 > 4, PARTS[nPart].nInitialPosition + 1 - 4, PARTS[nPart].nInitialPosition + 1) + sCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1") + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}}) + if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}}) + end + nOtherPosition = EgtIf( PARTS[nPart].nInitialPosition + 3 > 4, PARTS[nPart].nInitialPosition + 3 - 4, PARTS[nPart].nInitialPosition + 3) + sCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1") + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}}) + if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}}) + end + end + end + + -- fino a che ci sono soluzioni da testare + for z = 1, #TotalCombiToTest do + + -- si svuota il machgroup e si resettano le variabili + EgtRemoveAllOperations() + MACHININGS = {} + MACHININGS.Info = {} + nOrd = 1 + + local bCombinationFound = true + -- la parte di applicazione lavorazioni può essere lanciata più volte in caso della presenza di errori + local bProcess = true + while bProcess do + bProcess = false + + -- si ricavano tutte le combinazioni possibili + local CombinationListFromMatrix = GetCombinationListFromMatrix( PROCESSINGS[nPart], PARTS[nPart], nCycles > 1, TotalCombiToTest[z]) + -- se ci sono soluzioni possibili + if #CombinationListFromMatrix > 0 then + BestCombination = GetBestCombination( CombinationListFromMatrix, PARTS[nPart]) + -- se la soluzione alternativa migliore è completa, allora la verifico, altrimenti si tiene la migliore in assoluto + if BestCombination.nNotComplete == 0 and BestCombination.nNotExecute == 0 then + + -- compilazione della vProc finale contenente le feature da lavorare nella giusta rotazione + local vProc, MatrixResult = GetProcessingListFromCombination( BestCombination) + + -- si mette subito il pezzo nella fase + EgtSetCurrPhase( 1) + + -- si sposta il pezzo nella posizione originale, di quando è stata fatta la collect. In questo modo tutti i dati calcolati nella collect restano validi. + -- Altrimenti bisognava ricalcolare tutto, aumentando tempo di calcolo. + local vtRawOffsetPos = PARTS[nPart].b3Raw:getMin() - EgtGetRawPartBBox( PARTS[nPart].idRaw):getMin() + local nRawId = PARTS[nPart].idRaw + while nRawId and abs( vtRawOffsetPos:len()) > 0 do + EgtKeepRawPart( nRawId) + EgtMoveRawPart( nRawId, vtRawOffsetPos) + nRawId = EgtGetNextRawPart( nRawId) + end + + if BestCombination.bPartInCombiIsInverted then + BeamLib.InvertRawPart( PARTS[nPart], 2) + end + + -- se la posizione iniziale non è calcolata, significa che non ci sono feature da eseguire. Solo taglio testa/coda + if not MatrixResult.nInitialPosition then + MatrixResult.nInitialPosition = 1 + MACHININGS.Info.nHeadCutRotation = 1 + MACHININGS.Info.nSplitCutRotation = 1 + -- altrimenti si fanno tutti i calcoli + else + -- TODO serve ancora ordinare le feature con nuovo metodo di calcolo ottimizzazione lavorazioni? + -- ordinamento di base delle feature + vProc = OrderFeatures( vProc) + + -- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale + MACHININGS = CalculateMachinings( vProc, PARTS[nPart], MatrixResult.nInitialPosition) + -- se non sono sono settate le rotazioni di lavorazione di testa e coda, significa che le feature da eseguire non sono state eseguite per qualche problema. Si forza rotazione 1 + if not MACHININGS.Info.nHeadCutRotation or not MACHININGS.Info.nSplitCutRotation then + MACHININGS.Info.nHeadCutRotation = 1 + MACHININGS.Info.nSplitCutRotation = 1 + end + end + + local nOffsetIndex = EgtIf( BestCombination.bPartInCombiIsInverted, 4, 0) + -- aggiunge tagli testa e coda in fasi opportune + local nRotHeadCut = MatrixResult.nInitialPosition + MACHININGS.Info.nHeadCutRotation - 1 + if nRotHeadCut > 4 then + nRotHeadCut = nRotHeadCut - 4 + end + nRotHeadCut = nRotHeadCut + nOffsetIndex + local nRotSplitCut = MatrixResult.nInitialPosition + MACHININGS.Info.nSplitCutRotation - 1 + if nRotSplitCut > 4 then + nRotSplitCut = nRotSplitCut - 4 + end + nRotSplitCut = nRotSplitCut + nOffsetIndex + -- setto nella Proc l'indice rotazione nella quale deve essere lavorata + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].nIndexRotation = nRotHeadCut + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].nIndexRotation = nRotSplitCut + + -- si imposta flag rotazione per taglio di testa + if MACHININGS.Info.nHeadCutRotation == 2 then + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = nil + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bSide = true + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bStd = nil + elseif MACHININGS.Info.nHeadCutRotation == 3 then + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = true + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bSide = nil + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bStd = nil + else + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = nil + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bSide = nil + PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bStd = true + end + -- si imposta flag rotazione per taglio di coda + if MACHININGS.Info.nSplitCutRotation == 2 then + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = nil + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = true + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bStd = nil + elseif MACHININGS.Info.nSplitCutRotation == 3 then + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = true + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = nil + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bStd = nil + else + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = nil + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = nil + PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bStd = true + end + + local vProcHeadTail = {} + table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc]) + table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc]) + + MACHININGS = CalculateMachinings( vProcHeadTail, PARTS[nPart], MatrixResult.nInitialPosition) + + -- finiti i calcoli di applicazione delle lavorazioni, si riporta il pezzo nello zero della fase + nRawId = PARTS[nPart].idRaw + while nRawId and abs( vtRawOffsetPos:len()) > 0 do + EgtKeepRawPart( nRawId) + EgtMoveRawPart( nRawId, -vtRawOffsetPos) + nRawId = EgtGetNextRawPart( nRawId) + end + + local bAreAllMachiningApplyOk + local sErr + local bSplitAlreadyExecuted = false + local bSplitExecutedOnRot = false + local nPhase = EgtGetCurrPhase() + local idDisp = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( idDisp, 'TYPE', 'START') + EgtSetInfo( idDisp, 'ORD', nOrd) + + -- creazione effettiva delle lavorazioni + MACHININGS.Info = {} + local nCurrPosition = 1 + local nInitialPosition = MatrixResult.nInitialPosition + BestCombination.nInitialPosition = MatrixResult.nInitialPosition + + -- se c'è almeno una lavorazione in posizionamento con trave ribaltata + if MatrixResult.bSomeFeatureDown then + local nRotation = EgtIf( nInitialPosition + 2 > 4, nInitialPosition + 2 - 4, nInitialPosition + 2) + BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition) + nCurrPosition = nRotation + EgtSetInfo( idDisp, 'ROT', -2) + bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'DOWN') + bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot + bProcess = bProcess or bTryToReProcess + end + + -- se c'è almeno una lavorazione in posizionamento con trave ruotata + if MatrixResult.bSomeFeatureSide then + -- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima + if MatrixResult.bSomeFeatureDown then + BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0)) + nPhase = EgtGetCurrPhase() + idDisp = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( idDisp, 'ORD', nOrd) + -- se c'è già stata separazione + if bSplitAlreadyExecuted then + EgtSetInfo( idDisp, 'TYPE', 'MID2') + else + EgtSetInfo( idDisp, 'TYPE', 'MID') + end + -- se combinazione prevede inversione, si gira il pezzo + if BestCombination.bPartInCombiIsInverted and not PARTS[nPart].bIsInverted then + BeamLib.InvertRawPart( PARTS[nPart], 2) + end + end + local nRotation = EgtIf( nInitialPosition + 1 > 4, nInitialPosition + 1 - 4, nInitialPosition + 1) + BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition) + nCurrPosition = nRotation + EgtSetInfo( idDisp, 'ROT', -1) + bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'SIDE') + bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot + bProcess = bProcess or bTryToReProcess + end + + -- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima + if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then + BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0)) + nPhase = EgtGetCurrPhase() + idDisp = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( idDisp, 'ORD', nOrd) + -- se c'è già stata separazione + if bSplitAlreadyExecuted then + EgtSetInfo( idDisp, 'TYPE', 'END2') + else + EgtSetInfo( idDisp, 'TYPE', 'MID') + end + -- se combinazione prevede inversione, si gira il pezzo + if BestCombination.bPartInCombiIsInverted and not PARTS[nPart].bIsInverted then + BeamLib.InvertRawPart( PARTS[nPart], 2) + end + end + + BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1) + + -- aggiunta lavorazioni in ultima fase + _, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD') + bProcess = bProcess or bTryToReProcess + + -- se bisogna riprocessare, si annulla tutto + nCycles = nCycles + 1 + if bProcess and nCycles <= nMaxReProcessCycles then + -- azzero liste + MACHININGS = {} + MACHININGS.Info = {} + RESULT = {} + EgtRemoveAllOperations() + -- si riporta pezzo in posizione iniziale + -- se combinazione prevedeva inversione, si rigira il pezzo + if BestCombination.bPartInCombiIsInverted then + BeamLib.InvertRawPart( PARTS[nPart], -2) + end + -- si ribalta il pezzo in posizione iniziale + BeamLib.RotateRawPart( PARTS[nPart], 1 - nInitialPosition) + else + bProcess = false + end + else + bCombinationFound = false + end + else + bCombinationFound = false + end + end + nOrd = nOrd + 1 + -- se ho trovato almeno una combinazione possibile + if bCombinationFound then + -- ===== finiti i pezzi, si scarica il restante ===== + local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw) + if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then + BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0) + local nPhase = EgtGetCurrPhase() + local idDisp = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( idDisp, 'TYPE', 'REST') + EgtSetInfo( idDisp, 'ORD', nOrd) + end + -- Aggiornamento finale di tutto + EgtSetCurrPhase( 1) + local bApplOk, _, _ = EgtApplyAllMachinings() + -- se non ci sono errori, soluzione alternativa valida + if bApplOk then + -- TODO scrivere info su pezzo! + end + + -- se ultima combinazione, si esce e non si riporta in posizione inizale. Verrà infatti cancellata + if z == #TotalCombiToTest then break end + + -- si riporta pezzo in posizione iniziale + -- se combinazione prevedeva inversione, si rigira il pezzo + if BestCombination.bPartInCombiIsInverted then + BeamLib.InvertRawPart( PARTS[nPart], -2) + end + -- si ribalta il pezzo in posizione iniziale + BeamLib.RotateRawPart( PARTS[nPart], 1 - BestCombination.nInitialPosition) + end + + end + + -- si cancella eventuale mach group creato per le alternative + EgtRemoveMachGroup( nTempMachGroupName) + +end + ------------------------------------------------------------------------------------------------------------- return BeamExec diff --git a/LuaLibs/BeamLib.lua b/LuaLibs/BeamLib.lua index 34baa4c..ab8d022 100644 --- a/LuaLibs/BeamLib.lua +++ b/LuaLibs/BeamLib.lua @@ -328,6 +328,18 @@ function BeamLib.RotateRawPart( Part, nNumberOfRotations) end end +------------------------------------------------------------------------------------------------------------- +function BeamLib.CreateAddGroup( PartId, sGroupName) + AddGrpId = EgtGroup( PartId or GDB_ID.NULL) + if not AddGrpId then + return false + end + -- assegno nome, flag di layer per gruppo di lavoro e colore + EgtSetName( AddGrpId, sGroupName) + EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup()) + EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25)) +end + ------------------------------------------------------------------------------------------------------------- function BeamLib.CreateOrEmptyAddGroup( PartId) -- recupero i dati del gruppo aggiuntivo @@ -341,15 +353,9 @@ function BeamLib.CreateOrEmptyAddGroup( PartId) EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup()) return EgtEmptyGroup( AddGrpId) end + -- altrimenti lo creo - AddGrpId = EgtGroup( PartId or GDB_ID.NULL) - if not AddGrpId then - return false - end - -- assegno nome, flag di layer per gruppo di lavoro e colore - EgtSetName( AddGrpId, sMchGrp) - EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup()) - EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25)) + BeamLib.CreateAddGroup( PartId, sMchGrp) return true end @@ -769,6 +775,11 @@ function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut) return '' end +------------------------------------------------------------------------------------------------------------- +function BeamLib.StringReplaceChar( sOriginal, nPosition, sChar) + return sOriginal:sub( 1, nPosition-1) .. sChar .. sOriginal:sub( nPosition+1) +end + ------------------------------------------------------------------------------------------------------------- function BeamLib.BinaryToDecimal( dNumber) local sNumberToConvert = tostring( dNumber) diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index 76e1306..d8e8ea2 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -1420,9 +1420,9 @@ function MachiningLib.AddOperations( MACHININGS, Part, sRotation) bSplitExecuted = true MACHININGS.Info.bSplitExecuted = true - BeamLib.AddPhaseWithRawParts( MACHININGS[i].Proc.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET) + BeamLib.AddPhaseWithRawParts( Part.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET) -- se grezzo successivo senza pezzi e finale, va tolto - local nNextRawId = EgtGetNextRawPart( MACHININGS[i].Proc.idRaw) + local nNextRawId = EgtGetNextRawPart( Part.idRaw) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end diff --git a/Strategies/GeneralParameters.json b/Strategies/GeneralParameters.json index d727430..8e24c17 100644 --- a/Strategies/GeneralParameters.json +++ b/Strategies/GeneralParameters.json @@ -41,6 +41,28 @@ "sMessageId": " ", "sMinUserLevel": "1" }, + { + "nGroup": "PIECE LOADING", + "sName": "GEN_bTestAlternative", + "sNameNge": "TEST_ALTERNATIVE", + "sValue": "true", + "sDescriptionShort": "Enable the possibility to load the piece 90° turned", + "sDescriptionLong": "", + "sType": "b", + "sMessageId": " ", + "sMinUserLevel": "1" + }, + { + "nGroup": "PIECE LOADING", + "sName": "GEN_bGetAlternativesNesting2D", + "sNameNge": "GET_ALTERNATIVES_NEST2D", + "sValue": "true", + "sDescriptionShort": "Enable material optimization function in nesting", + "sDescriptionLong": "", + "sType": "b", + "sMessageId": " ", + "sMinUserLevel": "1" + }, { "nGroup": "MACHINE", "sName": "GEN_sPieceRotation", From 37e08e3f42a8162221e76b596d185e77a18dbbed Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Mon, 2 Mar 2026 13:23:28 +0100 Subject: [PATCH 4/4] =?UTF-8?q?-=20Aggiunto=20tempo=20di=20calcolo=20delle?= =?UTF-8?q?=20alternative=20-=20Di=20default=20la=20ricerca=20delle=20alte?= =?UTF-8?q?rnative=20=C3=A8=20disattiva=20-=20Piccole=20migliorie=20varie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FlipRot.lua | 2 ++ LuaLibs/BeamExec.lua | 9 ++------- Strategies/GeneralParameters.json | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/FlipRot.lua b/FlipRot.lua index ff24e16..f8e670a 100644 --- a/FlipRot.lua +++ b/FlipRot.lua @@ -188,7 +188,9 @@ local function MyProcessFeatures() end -- si calcolano alternative + TIMER:startElapsed('Alternatives') BeamExec.ProcessAlternatives( PARTS) + TIMER:stopElapsed('Alternatives') -- cancello gruppo temporaneo local idTempGroup = BeamLib.GetTempGroup() diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 6cae827..da8fe19 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -1923,8 +1923,6 @@ end ------------------------------------------------------------------------------------------------------------- function BeamExec.ProcessAlternatives( PARTS) -- ciclo sui pezzi - local nTotErr = 0 - local Stats = {} local BestCombination = {} local nPart = 1 local nOrd = 1 @@ -1932,13 +1930,10 @@ function BeamExec.ProcessAlternatives( PARTS) local bTryToReProcess = false -- se non serve trovare altre soluzioni, si esce subito - if not PARTS[nPart].GeneralParameters.GEN_bTestAlternative or not PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then + if not ( PARTS[nPart].GeneralParameters.GEN_bTestAlternative and not PARTS[nPart].bSquareSection) or not PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then return end - -- si analizzano le alternative solo del primo pezzo (la FlipRot viene chiamata sempre con un solo pezzo) - local nCycles = 1 - -- si copia il MachGroup originale local nOriginalMachGroup = EgtGetCurrMachGroup() local sMachGroupName = EgtGetMachGroupName( nOriginalMachGroup) @@ -2015,12 +2010,12 @@ function BeamExec.ProcessAlternatives( PARTS) -- fino a che ci sono soluzioni da testare for z = 1, #TotalCombiToTest do - -- si svuota il machgroup e si resettano le variabili EgtRemoveAllOperations() MACHININGS = {} MACHININGS.Info = {} nOrd = 1 + local nCycles = 1 local bCombinationFound = true -- la parte di applicazione lavorazioni può essere lanciata più volte in caso della presenza di errori diff --git a/Strategies/GeneralParameters.json b/Strategies/GeneralParameters.json index 8e24c17..8e918ce 100644 --- a/Strategies/GeneralParameters.json +++ b/Strategies/GeneralParameters.json @@ -34,7 +34,7 @@ "nGroup": "PIECE LOADING", "sName": "GEN_bAllowPieceInversion", "sNameNge": "ADMIT_INVERSION", - "sValue": "true", + "sValue": "false", "sDescriptionShort": "Allow piece inversion", "sDescriptionLong": "", "sType": "b", @@ -45,7 +45,7 @@ "nGroup": "PIECE LOADING", "sName": "GEN_bTestAlternative", "sNameNge": "TEST_ALTERNATIVE", - "sValue": "true", + "sValue": "false", "sDescriptionShort": "Enable the possibility to load the piece 90° turned", "sDescriptionLong": "", "sType": "b", @@ -56,7 +56,7 @@ "nGroup": "PIECE LOADING", "sName": "GEN_bGetAlternativesNesting2D", "sNameNge": "GET_ALTERNATIVES_NEST2D", - "sValue": "true", + "sValue": "false", "sDescriptionShort": "Enable material optimization function in nesting", "sDescriptionLong": "", "sType": "b",