From fc047c23509569c069353b9cd362ece921be457d Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Thu, 14 Nov 2024 10:23:58 +0100 Subject: [PATCH] =?UTF-8?q?Ottimizzazione=20collect.=20Si=20calcola=20solo?= =?UTF-8?q?=20se=20la=20rotazione=20=C3=A8=20abilitata,=20in=20base=20alle?= =?UTF-8?q?=20combinazioni=20disponibili?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LuaLibs/BeamExec.lua | 253 ++++++++++++++++++++++++++----------------- 1 file changed, 156 insertions(+), 97 deletions(-) diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index d541c35..c2b92de 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -215,6 +215,111 @@ function BeamExec.GetStrategiesFromJSONinBD() end end +------------------------------------------------------------------------------------------------------------- +-- funzione che controlla validità delle combinazioni proposte +local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection) + -- se non utilizzo BEAMWALL, forzo comportamento BASIC + if not BEAM.BeamWall or not BEAM.Rotation then + BEAM.Rotation = {} + BEAM.Rotation.Basic = true + end + + +-------------------------------------------------------------------------- +-- TODO scelta combinazione forzato DA RIMUOVERE!! Serve modifica al BEAM. + BEAM.BeamWall = true + BEAM.Rotation = {} + BEAM.Rotation.bBasic = true + BEAM.Rotation.bNoRotation = false + BEAM.Rotation.bAdvanced = false +-------------------------------------------------------------------------- + + -- BASIC : posizione di scarico come posizionamento iniziale + if not BEAM.BeamWall or BEAM.Rotation.bBasic then + local ExtraRotation = nUnloadPos + 3 + if nUnloadPos ~= 1 then + return false + elseif string.sub( sCombination, nUnloadPos, nUnloadPos) == '1' and string.sub( sCombination, ExtraRotation, ExtraRotation) == '0' then + if not BeamData.ROT90 and string.sub( sCombination, nUnloadPos+1, nUnloadPos+1) == '1' then + return false + elseif not BeamData.ROT180 and string.sub( sCombination, nUnloadPos+2, nUnloadPos+2) == '1' then + return false + else + return true + end + else + return false + end + -- NO ROTATION : solo posizione di partenza + elseif BEAM.Rotation.bNoRotation then + if sCombination == '1000' and nUnloadPos == 1 then + return true + else + return false + end + -- ADVANCED : come BASIC ma ammesse anche le prerotazioni (posizione di scarico può essere diversa da posizione iniziale) + elseif BEAM.Rotation.bAdvanced then + local Rotation90 = EgtIf( nUnloadPos + 1 > 4, nUnloadPos + 1 - 4, nUnloadPos + 1) + local Rotation180 = EgtIf( nUnloadPos + 2 > 4, nUnloadPos + 2 - 4, nUnloadPos + 2) + local ExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3) + + if not bSquareSection and ( nUnloadPos == 2 or nUnloadPos == 4) then + return false + else + if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, ExtraRotation, ExtraRotation) == '1' then + return false + else + if not BeamData.ROT90 and string.sub( sCombination, Rotation90, Rotation90) == '1' then + return false + elseif not BeamData.ROT180 and string.sub( sCombination, Rotation180, Rotation180) == '1' then + return false + else + return true + end + end + end + end +end + +------------------------------------------------------------------------------------------------------------- +local function GetAvailableCombinations( PartInfo) + local CombinationList = {} + CombinationList.Rotations = {0, 0, 0, 0} -- indice rotazione attiva, per calcolo collect feature + + -- verifico tutte le combinazioni che possono essere considerate + for nUnloadPos = 1, 4 do + for i = 1, BeamLib.BinaryToDecimal( 1111) do + 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) then + local Combination = {} + Combination.sBitIndexCombination = sBitIndexCombination + Combination.nUnloadPos = nUnloadPos + table.insert( CombinationList, Combination) + + -- se posizionamento iniziale attivo + if string.sub( sBitIndexCombination, 1, 1) == '1' then + CombinationList.Rotations[1] = 1 + end + -- se attiva rotazione 90 + if string.sub( sBitIndexCombination, 2, 2) == '1' then + CombinationList.Rotations[2] = 1 + end + -- se attiva rotazione 180 + if string.sub( sBitIndexCombination, 3, 3) == '1' then + CombinationList.Rotations[3] = 1 + end + -- se attiva rotazione 270 + if string.sub( sBitIndexCombination, 4, 4) == '1' then + CombinationList.Rotations[4] = 1 + end + end + end + end + return CombinationList +end + ------------------------------------------------------------------------------------------------------------- -- *** funzioni posizionamento pezzi all'interno della barra *** ------------------------------------------------------------------------------------------------------------- @@ -342,8 +447,10 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS) PARTS[i].dLength = PARTS[i].b3Raw:getDimX() PARTS[i].dWidth = PARTS[i].b3Raw:getDimY() PARTS[i].dHeight = PARTS[i].b3Raw:getDimZ() + PARTS[i].bSquareSection = abs( PARTS[i].dWidth - PARTS[i].dHeight) < 100 * GEO.EPS_SMALL PARTS[i].b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) PARTS[i].nIndexInParts = i + PARTS[i].CombinationList = GetAvailableCombinations( PARTS[i]) else local sOut = 'Error: part L(' .. EgtNumToString( dPartLen, 1) .. ') too big for raw part L(' .. EgtNumToString( dLen - 0.1, 1) .. ')' return false, sOut @@ -887,17 +994,23 @@ function BeamExec.GetProcessings( PROCESSINGS, PARTS) for nPart = 1, #PARTS do if not PARTS[nPart].id and PARTS[nPart].b3Raw:getDimX() < BeamData.dMinRaw then break end local vProcRot = {} - -- TODO Il numero di rotazioni da calcolare deve dipendere dalle impostazionei del cliente. Per adesso si calcolano tutte e 4, ma può essere ottimizzato - for dRotIndex = 1, 4 do - -- recupero le feature di lavorazione della trave - table.insert( vProcRot, CollectFeatures( PARTS[nPart])) - - -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse - -- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no - vProcRot[dRotIndex] = GetFeatureInfoAndDependency( vProcRot[dRotIndex], PARTS[nPart]) - -- calcola le strategie applicabili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies) - vProcRot[dRotIndex] = CalculateStrategies( vProcRot[dRotIndex], PARTS[nPart]) + for dRotIndex = 1, 4 do + -- si calcolano le feature solo se la rotazione può essere presa in considerazione + if PARTS[nPart].CombinationList.Rotations[dRotIndex] == 1 then + -- recupero le feature di lavorazione della trave + table.insert( vProcRot, CollectFeatures( PARTS[nPart])) + + -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse + -- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no + vProcRot[dRotIndex] = GetFeatureInfoAndDependency( vProcRot[dRotIndex], PARTS[nPart]) + + -- calcola le strategie applicabili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies) + vProcRot[dRotIndex] = CalculateStrategies( vProcRot[dRotIndex], PARTS[nPart]) + else + -- inserisco una tabella vuota + table.insert( vProcRot, {}) + end -- ruoto il grezzo per calcolare la fattibilità delle lavorazioni nella prossima rotazione -- vettore movimento grezzi per rotazione di 90deg ogni step @@ -924,71 +1037,6 @@ function BeamExec.GetProcessings( PROCESSINGS, PARTS) return PROCESSINGS end -------------------------------------------------------------------------------------------------------------- --- funzione che controlla validità delle combinazioni proposte -local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection) - -- se non utilizzo BEAMWALL, forzo comportamento BASIC - if not BEAM.BeamWall or not BEAM.Rotation then - BEAM.Rotation = {} - BEAM.Rotation.Basic = true - end - - - -- TODO scelta combinazione forzato DA RIMUOVERE!! Serve modifica al BEAM. - BEAM.BeamWall = true - BEAM.Rotation = {} - BEAM.Rotation.bBasic = true - BEAM.Rotation.bNoRotation = false - BEAM.Rotation.bAdvanced = false - - - -- BASIC : posizione di scarico come posizionamento iniziale - if not BEAM.BeamWall or BEAM.Rotation.bBasic then - local ExtraRotation = nUnloadPos + 3 - if nUnloadPos ~= 1 then - return false - elseif string.sub( sCombination, nUnloadPos, nUnloadPos) == '1' and string.sub( sCombination, ExtraRotation, ExtraRotation) == '0' then - if not BeamData.ROT90 and string.sub( sCombination, nUnloadPos+1, nUnloadPos+1) == '1' then - return false - elseif not BeamData.ROT180 and string.sub( sCombination, nUnloadPos+2, nUnloadPos+2) == '1' then - return false - else - return true - end - else - return false - end - -- NO ROTATION : solo posizione di partenza - elseif BEAM.Rotation.bNoRotation then - if sCombination == '1000' and nUnloadPos == 1 then - return true - else - return false - end - -- ADVANCED : come BASIC ma ammesse anche le prerotazioni (posizione di scarico può essere diversa da posizione iniziale) - elseif BEAM.Rotation.bAdvanced then - local Rotation90 = EgtIf( nUnloadPos + 1 > 4, nUnloadPos + 1 - 4, nUnloadPos + 1) - local Rotation180 = EgtIf( nUnloadPos + 2 > 4, nUnloadPos + 2 - 4, nUnloadPos + 2) - local ExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3) - - if not bSquareSection and ( nUnloadPos == 2 or nUnloadPos == 4) then - return false - else - if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, ExtraRotation, ExtraRotation) == '1' then - return false - else - if not BeamData.ROT90 and string.sub( sCombination, Rotation90, Rotation90) == '1' then - return false - elseif not BeamData.ROT180 and string.sub( sCombination, Rotation180, Rotation180) == '1' then - return false - else - return true - end - end - end - end -end - ------------------------------------------------------------------------------------------------------------- -- funzione che decide la migliore tra le combinazioni di rotazione disponibili local function GetBestCombination( ListToCompare) @@ -1102,27 +1150,42 @@ local function GetProcBestMachRotationFromList( ListToCompare) end ------------------------------------------------------------------------------------------------------------- -local function WriteMatrixLog( ProcessingsOnPart) +local function WriteMatrixLog( ProcessingsOnPart, PartInfo) EgtOutLog( ' === === === === === === === === === === ROTATION MATRIX === === === === === === === === === === === === ===') EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |') EgtOutLog( '----------------------------------------------------------------------------------------------------------') - for ProcLog = 1, #ProcessingsOnPart.Rotation[1] do - local sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[1][ProcLog].id) + local nProcessingsNumber + local nFirstAvailableRotation + -- ricerco prima rotazione effettivamente calcolata. In genere è sempre la prima + for i = 1, 4 do + if PartInfo.CombinationList.Rotations[i] == 1 then + nProcessingsNumber = #ProcessingsOnPart.Rotation[i] + nFirstAvailableRotation = i + break + end + end + + for ProcLog = 1, nProcessingsNumber do + local sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[nFirstAvailableRotation][ProcLog].id) while string.len( sLogLine) <= 20 do sLogLine = sLogLine .. ' ' end sLogLine = sLogLine .. '|' for nRotLog = 1, 4 do - if ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy then - local sLogLineProc = tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.dCompositeRating) .. - ' (' .. tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.sStrategyId) .. ') |' - while string.len( sLogLineProc) <= 20 do - sLogLineProc = ' ' .. sLogLineProc + if PartInfo.CombinationList.Rotations[nRotLog] == 1 then + if ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy then + local sLogLineProc = tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.dCompositeRating) .. + ' (' .. tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.sStrategyId) .. ') |' + while string.len( sLogLineProc) <= 20 do + sLogLineProc = ' ' .. sLogLineProc + end + sLogLine = sLogLine .. sLogLineProc + else + sLogLine = sLogLine .. ' 0 (STR----) |' end - sLogLine = sLogLine .. sLogLineProc else - sLogLine = sLogLine .. ' 0 (STR----) |' + sLogLine = sLogLine .. ' NOT NEEDED |' end end EgtOutLog( sLogLine) @@ -1178,24 +1241,20 @@ end ------------------------------------------------------------------------------------------------------------- -- funzione che calcola le combinazioni di rotazione per lavorare la trave e sceglie la migliore local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo) - -- TODO funzione da sviluppare completamente local BestCombination = {} local CombinationsList = {} - local bSquareSection = abs( PartInfo.dWidth - PartInfo.dHeight) < 100 * GEO.EPS_SMALL -- scrittura nel log della matrice delle rotazioni if EgtGetDebugLevel() >= 3 then - WriteMatrixLog( ProcessingsOnPart) + WriteMatrixLog( ProcessingsOnPart, PartInfo) end -- per ogni posizione di scarico for nUnloadPos = 1, 4 do - -- verifico tutte le combinazioni che possono essere considerate - for i = 1, BeamLib.BinaryToDecimal( 1111) do - local nBitIndexCombination = BeamLib.DecimalToBinary( i) - local sBitIndexCombination = BeamLib.CalculateStringBinaryFormat( nBitIndexCombination, 4) - -- TODO si potrebbero calcolare le combinazioni all'inizio, e ottimizzare facendo la collect solo nelle rotazioni che possono essere considerate - if IsCombinationAvailable( sBitIndexCombination, nUnloadPos, bSquareSection) then + -- calcolo per tutte le combinazioni disponibili precedentemente verificate + for i = 1, #PartInfo.CombinationList do + -- controllo che la combinazione abbia ultima fase come quella calcolata in fase di definizione combinazioni + if PartInfo.CombinationList[i].nUnloadPos == nUnloadPos then local bRot90, bRot180 local SingleCombination = {} SingleCombination.nRotations = 0 @@ -1203,7 +1262,7 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo) SingleCombination.nComplete = 0 SingleCombination.nNotComplete = 0 SingleCombination.nNotExecute = 0 - SingleCombination.sBitIndexCombination = sBitIndexCombination + SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination SingleCombination.nUnloadPos = nUnloadPos -- creo liste dei proc suddivisi per rotazione SingleCombination.Rot0 = {} @@ -1217,7 +1276,7 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo) local ResultsList = {} for nRotation = 1, 3 do -- se rotazione abilitata da combinazione - if string.sub( sBitIndexCombination, nNextRot, nNextRot) == '1' then + if string.sub( PartInfo.CombinationList[i].sBitIndexCombination, nNextRot, nNextRot) == '1' then -- controllo se è stata scelta una strategia if ProcessingsOnPart.Rotation[nNextRot][nProc].ChosenStrategy then local Proc = {} @@ -1265,7 +1324,7 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo) error( 'UNEXPECTED ERROR: NO combinations available') end BestCombination = GetBestCombination( CombinationsList) - + -- scrittura nel log delle combinazioni possibili if EgtGetDebugLevel() >= 3 then WriteCombinationLog( CombinationsList, BestCombination)