diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index c187ad6..a039856 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -1705,10 +1705,12 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, Part, bReProcess for i = 1, #Part.CombinationList do local bToProcess = false -- controllo se debbano essere ricalcolate solo alcune soluzioni + local nSingleCombinationToReprocessIndex if BitCombinationListToReprocess and #BitCombinationListToReprocess > 0 then for c = 1, #BitCombinationListToReprocess do - if Part.CombinationList[i].sBitIndexCombination == BitCombinationListToReprocess[c].sBitIndexCombination and + if Part.CombinationList[i].sBitIndexCombination == BitCombinationListToReprocess[c].sBitIndexCombination and Part.CombinationList[i].bPartInCombiIsInverted == BitCombinationListToReprocess[c].bPartInCombiIsInverted then + nSingleCombinationToReprocessIndex = c bToProcess = true end end @@ -1728,6 +1730,9 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, Part, bReProcess SingleCombination.nNotComplete = 0 SingleCombination.nNotExecute = 0 SingleCombination.sBitIndexCombination = Part.CombinationList[i].sBitIndexCombination + if nSingleCombinationToReprocessIndex then + SingleCombination.sBitIndexCombinationToNest = BitCombinationListToReprocess[nSingleCombinationToReprocessIndex].sBitIndexCombinationToNest + end -- TODO se pezzo invertito bisogna considerare le rotazioni nell'array dalla 5 alla 8 SingleCombination.bPartInCombiIsInverted = Part.CombinationList[i].bPartInCombiIsInverted SingleCombination.nUnloadPos = nUnloadPos @@ -2298,36 +2303,47 @@ function BeamExec.ProcessAlternatives( PARTS) end -- se serve calcolare posizione per ottimizzazione tagli in nesting (le soluzioni non possono avere ribaltamenti) + -- il pezzo è il posizione 0 in questo momento, ma l'automatismo ha già fatto la prerotazione, se abilitata + -- le combinazioni vanno testate considerando come 0 la posizione preruotata + -- allo stesso modo, le alternative devono considerare come 0 quello preruotato 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}, bIsNesting2D = true}) + local sBitIndexCombinationToCheck = BeamLib.StringReplaceChar( '0000', PARTS[nPart].nInitialPosition, "1") + local sBitIndexCombinationToNest = '1000' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = true}) if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then - table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}, bIsNesting2D = true}) + sBitIndexCombinationToNest = '1000_INV' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = not PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = 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}, bIsNesting2D = true}) + sBitIndexCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1") + sBitIndexCombinationToNest = '0010' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = true}) if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then - table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}, bIsNesting2D = true}) + sBitIndexCombinationToNest = '0010_INV' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = not PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = 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}, bIsNesting2D = true}) + sBitIndexCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1") + sBitIndexCombinationToNest = '0100' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = true}) if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then - table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}, bIsNesting2D = true}) + sBitIndexCombinationToNest = '0100_INV' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = not PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = 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}, bIsNesting2D = true}) + sBitIndexCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1") + sBitIndexCombinationToNest = '0001' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = true}) if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then - table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}, bIsNesting2D = true}) + sBitIndexCombinationToNest = '0001_INV' + table.insert( TotalCombiToTest, {{ sBitIndexCombination = sBitIndexCombinationToCheck, sBitIndexCombinationToNest = sBitIndexCombinationToNest, bPartInCombiIsInverted = not PARTS[nPart].bPartInCombiIsInverted}, bIsNesting2D = true}) end end end @@ -2455,13 +2471,12 @@ function BeamExec.ProcessAlternatives( PARTS) -- aggiornamento info testa/coda per Nesting local nRotation = BeamLib.ConvertBitIndexToRotationIndex( BestCombination.sBitIndexCombination) - local sBitIndexCombinationWithInvert = BestCombination.sBitIndexCombination .. EgtIf( BestCombination.bPartInCombiIsInverted, '_INV', '') local HeadcutInfo, TailcutInfo = GetHeadTailInfoForNesting( HeadCutOnFirstRotation, TailCutOnFirstRotation, PARTS[nPart]) if HeadcutInfo then -- offset e vettori vanno adeguati alla rotazione attuale (inversione è già corretta) BeamLib.RotateTableFromIndexInPlace( HeadcutInfo.OffsetX, nRotation) HeadcutInfo.vtN:rotate( X_AX(), ( nRotation - 1) * 90) - PARTS[nPart].HeadcutInfo[sBitIndexCombinationWithInvert] = { + PARTS[nPart].HeadcutInfo[BestCombination.sBitIndexCombinationToNest] = { OffsetX = HeadcutInfo.OffsetX, vtN = HeadcutInfo.vtN } @@ -2470,7 +2485,7 @@ function BeamExec.ProcessAlternatives( PARTS) -- offset e vettori vanno adeguati alla rotazione attuale (inversione è già corretta) BeamLib.RotateTableFromIndexInPlace( TailcutInfo.OffsetX, nRotation) TailcutInfo.vtN:rotate( X_AX(), ( nRotation - 1) * 90) - PARTS[nPart].TailcutInfo[sBitIndexCombinationWithInvert] = { + PARTS[nPart].TailcutInfo[BestCombination.sBitIndexCombinationToNest] = { OffsetX = TailcutInfo.OffsetX, vtN = TailcutInfo.vtN } @@ -2606,11 +2621,10 @@ function BeamExec.ProcessAlternatives( PARTS) local bApplOk, _, _ = EgtApplyAllMachinings() -- se non ci sono errori, soluzione alternativa valida: scrittura variabili globali per interfaccia if bApplOk then - local sBitIndexCombinationWithInvert = BestCombination.sBitIndexCombination .. EgtIf( BestCombination.bPartInCombiIsInverted, '_INV', '') if TotalCombiToTest[z].bIsNesting2D then - table.insert( AlternativesNest2D, sBitIndexCombinationWithInvert) + table.insert( AlternativesNest2D, BestCombination.sBitIndexCombinationToNest) else - table.insert( Alternatives, sBitIndexCombinationWithInvert) + table.insert( Alternatives, BestCombination.sBitIndexCombinationToNest) end end -- se ultima combinazione, si esce e non si riporta in posizione iniziale. Verrà infatti cancellata @@ -2629,7 +2643,6 @@ function BeamExec.ProcessAlternatives( PARTS) -- passaggio info a interfaccia da scrivere sul pezzo BEAM.INFONGEPART = {} - table.insert( BEAM.INFONGEPART, 'INITIALPOSITION=' .. PARTS[nPart].nInitialPosition) for i = 1, #AlternativesNest2D do if PARTS[nPart].HeadcutInfo then local sOffsetX = table.concat( PARTS[nPart].HeadcutInfo[AlternativesNest2D[i]].OffsetX, ',') diff --git a/LuaLibs/BeamLib.lua b/LuaLibs/BeamLib.lua index 83fba71..59efc04 100644 --- a/LuaLibs/BeamLib.lua +++ b/LuaLibs/BeamLib.lua @@ -940,22 +940,14 @@ end function BeamLib.ConvertBitIndexToRotationIndex( sBitIndexCombination) local nRotationIndex - if sBitIndexCombination == '1000' then + if EgtStartsWith( sBitIndexCombination, '1000') then return 1 - elseif sBitIndexCombination == '0100' then + elseif EgtStartsWith( sBitIndexCombination, '0100') then return 2 - elseif sBitIndexCombination == '0010' then + elseif EgtStartsWith( sBitIndexCombination, '0010') then return 3 - elseif sBitIndexCombination == '0001' then + elseif EgtStartsWith( sBitIndexCombination, '0001') then return 4 - elseif sBitIndexCombination == '1000_INV' then - return 5 - elseif sBitIndexCombination == '0100_INV' then - return 6 - elseif sBitIndexCombination == '0010_INV' then - return 7 - elseif sBitIndexCombination == '0001_INV' then - return 8 end return nRotationIndex diff --git a/NestProcess.lua b/NestProcess.lua index 84f4b06..8fb4596 100644 --- a/NestProcess.lua +++ b/NestProcess.lua @@ -538,6 +538,102 @@ local function CommitBestMove( BestMove) Job.bNested = true end +---------------------------------------------------------------------------------------------------------- +-- Dump diagnostico Input/Output +function RawInventory:DumpNestingData() + EgtOutLog("\n##########################################################################################") + EgtOutLog("### EGALWARE NESTING - DIAGNOSTIC DUMP ###") + EgtOutLog("##########################################################################################\n") + + -- 1. AMBIENTE & CONFIGURAZIONE + EgtOutLog("--- [1. NESTING ENVIRONMENT & PARAMETERS] ---") + EgtOutLog(string.format("NEST.STARTOFFSET = %s", tostring(NEST.STARTOFFSET))) + EgtOutLog(string.format("NEST.MATERIAL = %s", tostring(NEST.MATERIAL))) + EgtOutLog(string.format("NEST.MACHINE = %s", tostring(NEST.MACHINE))) + for k, v in pairs(CONFIG) do + EgtOutLog(string.format("CONFIG.%s = %s", tostring(k), tostring(v))) + end + + -- 2. MATERIALE DISPONIBILE (STOCK) + EgtOutLog("\n--- [2. RAW STOCK INVENTORY INPUTS] ---") + for i = 1, #self.Stock do + EgtOutLog(string.format("Stock Index %d: Length = %.4f mm | Qty Available = %d", i, self.Stock[i].dLength, self.Stock[i].nCount)) + end + + -- 3. COMMESSA PEZZI RICHIESTI (DEMANDED PARTS) + EgtOutLog("\n--- [3. DEMANDED PARTS (PART TABLE)] ---") + for id, count in pairs(PART) do + local sInitialPos = tostring(EgtGetInfo(id, 'INITIALPOSITION', 'i') or 0) + local sManualRot = tostring(EgtGetInfo(id, 'MANUALROT', 'i') or 0) + local sManualFlip = tostring(EgtGetInfo(id, 'MANUALFLIP', 'i') or 0) + EgtOutLog(string.format("Part ID: %5s | Demand Count: %d | CAD Base Length: %.4f mm | InitialPos: %s | ManualRot: %s | ManualFlip: %s", + tostring(id), count, EgtGetInfo(id, 'L', 'd') or 0, sInitialPos, sManualRot, sManualFlip)) + end + + -- 4. DATABASE GEOMETRICO COMPLETO (PART TEMPLATES) + EgtOutLog("\n--- [4. DETAILED GEOMETRIC TEMPLATES (ALL READABLE STATES)] ---") + for id, Template in pairs(PartTemplates) do + if type(Template) == "table" and Template.dLength then + EgtOutLog(string.format("\nPART ID: %s | Math Length: %.4f | MaxGlobalTailRecess: %.4f", tostring(id), Template.dLength, Template.dMaxGlobalTailRecess)) + for sState, State in pairs(Template.States) do + EgtOutLog(string.format(" -> State [%s]:", sState)) + -- Stringhe Grezze lette dal CAD + EgtOutLog(string.format(" Raw ALT_H String: %s", tostring(EgtGetInfo(id, 'ALT'..sState..'_H')))) + EgtOutLog(string.format(" Raw ALT_T String: %s", tostring(EgtGetInfo(id, 'ALT'..sState..'_T')))) + -- Valori matematici interpretati dal Nesting + local hOX = table.concat(State.Head.OffsetX, ", ") + local tOX = table.concat(State.Tail.OffsetX, ", ") + EgtOutLog(string.format(" HEAD Math -> OffsetX: [%s] | vtN: [X:%.6f, Y:%.6f, Z:%.6f] | vtNXabs: %.6f | dMaxHeadRecess: %.4f", + hOX, State.Head.vtN:getX(), State.Head.vtN:getY(), State.Head.vtN:getZ(), State.Head.vtNXabs, State.dMaxHeadRecess)) + EgtOutLog(string.format(" TAIL Math -> OffsetX: [%s] | vtN: [X:%.6f, Y:%.6f, Z:%.6f] | vtNXabs: %.6f | dMaxTailRecess: %.4f", + tOX, State.Tail.vtN:getX(), State.Tail.vtN:getY(), State.Tail.vtN:getZ(), State.Tail.vtNXabs, State.dMaxTailRecess)) + end + end + end + + -- 5. ANALISI DETTAGLIATA DELL'OUTPUT FINALE SULLE BARRE (ACTIVE BEAMS) + EgtOutLog("\n--- [5. FINAL NESTING SOLUTIONS AND SPATIAL COORDS] ---") + for i = 1, #self.ActiveBeams do + local Beam = self.ActiveBeams[i] + local dStartOffset = NEST.STARTOFFSET or 0 + EgtOutLog(string.format("\n==========================================================================================")) + EgtOutLog(string.format("ACTIVE BEAM [%d] -> Total Length: %.4f mm | Nesting Residual Space: %.4f mm", + i, Beam.dTotalLength, Beam.dResidualLength)) + EgtOutLog(string.format("==========================================================================================")) + + -- Ordine di Nesting (dall'ultimo appoggio a destra fino a sinistra) + EgtOutLog(" A. Array Storage Order (Nesting Logic - from Right to Left):") + for j = 1, #Beam.NestedParts do + local Part = Beam.NestedParts[j] + EgtOutLog(string.format(" [%d] ID: %5s | State: %12s | Length: %9.4f | Math PosX: %9.4f | Overlap: %9.4f | SharedCut: %s", + j, tostring(Part.id), tostring(Part.sState), Part.dLength, Part.dPosX, Part.dSafeOverlap, tostring(Part.bSharedCut))) + end + + -- Ordine di posizionamento sul Gruppo Macchina (da Sinistra X=0 a Destra) + EgtOutLog(" B. CAD Positioning Order (Output Macro - from Left X=0 to Right):") + local nIndex = 1 + for j = #Beam.NestedParts, 1, -1 do + local Part = Beam.NestedParts[j] + local dPosX = Part.dPosX - Beam.dResidualLength + dStartOffset + + -- Distanza dal pezzo precedente a sinistra (se esiste) + local sPrevDist = "N/A (First Part on Left)" + if j < #Beam.NestedParts then + local PrevPart = Beam.NestedParts[j+1] + local dPrevPosX = PrevPart.dPosX - Beam.dResidualLength + dStartOffset + sPrevDist = string.format("%.4f mm", dPosX - dPrevPosX) + end + + EgtOutLog(string.format(" PART%d -> ID: %5s | Chosen State: %12s | CAD Target PosX: %9.4f mm | Gap from left: %s", + nIndex, tostring(Part.id), tostring(Part.sState), dPosX, sPrevDist)) + nIndex = nIndex + 1 + end + end + EgtOutLog("\n##########################################################################################") + EgtOutLog("### END OF DUMP ###") + EgtOutLog("##########################################################################################\n") +end + ---------------------------------------------------------------------------------------------------------- -- script principale @@ -633,7 +729,6 @@ for i = 1, #RawInventory.ActiveBeams do for j = #Beam.NestedParts, 1, -1 do local Part = Beam.NestedParts[j] - local nInitialPosition = EgtGetInfo( Part.id, 'INITIALPOSITION', 'i') -- spostamento verso la testa della barra local dPosX = Part.dPosX - Beam.dResidualLength + dStartOffset @@ -647,8 +742,8 @@ for i = 1, #RawInventory.ActiveBeams do end -- eventuale rotazione - if ( EgtStartsWith( Part.sState, '0010') and nInitialPosition == 1) - or ( EgtStartsWith( Part.sState, '1000') and nInitialPosition == 3) then + local bIsRotationNeeded = EgtStartsWith( Part.sState, '0010') + if bIsRotationNeeded then local idSurfTmBoxDuplo = EgtGetFirstNameInGroup( idDuplo, "Box") local b3Duplo = EgtGetBBoxGlob( idSurfTmBoxDuplo, GDB_BB.STANDARD) EgtRotate( idDuplo, b3Duplo:getCenter(), X_AX(), 180, GDB_RT.GLOB) @@ -656,7 +751,9 @@ for i = 1, #RawInventory.ActiveBeams do end -- eventuale inversione - if EgtEndsWith( Part.sState, 'INV') then + -- TODO conta anche l'ordine rotazione-inversione? + local bIsInversionNeeded = EgtEndsWith( Part.sState, 'INV') + if bIsInversionNeeded then local idSurfTmBoxDuplo = EgtGetFirstNameInGroup( idDuplo, "Box") local b3Duplo = EgtGetBBoxGlob( idSurfTmBoxDuplo, GDB_BB.STANDARD) EgtRotate( idDuplo, b3Duplo:getCenter(), Z_AX(), 180, GDB_RT.GLOB) @@ -706,4 +803,9 @@ EgtResetCurrMachGroup() NEST.ERR = 0 -- calcolo bontà soluzione -RawInventory:PrintDiagnosticReport() \ No newline at end of file +RawInventory:PrintDiagnosticReport() + +-- Dump diagnostico - solo per debug +if EgtGetDebugLevel() >= 3 then + RawInventory:DumpNestingData() +end \ No newline at end of file