46 Commits

Author SHA1 Message Date
andrea.villa adf08876a9 DA CONTROLLARE!!!! Piccole modifiche per far funzionare nesting inclinato 2026-05-29 07:48:14 +02:00
luca.mazzoleni 476f214b99 Merge remote-tracking branch 'origin/develop' into ObliqueNesting 2026-05-21 18:53:12 +02:00
luca.mazzoleni eacabb5af7 - in BeamExec.ProcessBeams correzioni. Sembra funzionare correttamente in tutti i casi 2026-05-21 18:53:02 +02:00
luca.mazzoleni 5c7751aebd - in BeamLib aggiunta GetNewMachGroupName per avere il prossimo numero MachGroup intero libero
- in NestProcess i nomi MachGroup sono sempre interi; si mantiene sempre un BEAM_SAFETY_BUFFER nel riempimento delle barre
- in BeamExec.GetCombinationListFromMatrix corretti indici taglio di testa e coda
2026-05-21 15:02:23 +02:00
luca.mazzoleni 6649842c70 - in NestProcess modifiche per nestare pezzi senza alternative 2026-05-21 10:49:28 +02:00
luca.mazzoleni 27475763a2 - in BeamExec correzioni per il caso di taglio standard che diventa taglio di testa
- in MachiningLib.FindBlade e relativi non si testa più la normale della faccia in caso di informazioni lato mancanti (portava erroneamente a non trovare la lama nei casi solo downUp)
2026-05-21 09:29:55 +02:00
luca.mazzoleni 3fcca044ed - in BeamExec si ritornano stati per l'interfaccia anche per tagli che sono diventati Headcut e TailCut 2026-05-20 16:14:54 +02:00
luca.mazzoleni 630d28bf5b - in BeamExec se un taglio è diventato Headcut o Tailcut viene comunque considerato nel punteggio delle combinazioni 2026-05-20 16:00:15 +02:00
luca.mazzoleni 5e5f3d08c4 - in BeamExec se non è stato trovato nessun taglio di testa o di coda si usa quello settato in precedenza 2026-05-20 14:42:59 +02:00
luca.mazzoleni a773e0156a - in BeamLib.AddPhaseWithRawParts e correlati correzioni in caso di scarico ultimo grezzo 2026-05-19 17:03:21 +02:00
luca.mazzoleni 72e3b7dc8f - in BeamLib.AddPhaseWithRawParts correzioni 2026-05-19 15:53:53 +02:00
luca.mazzoleni 10592ac612 - in BeamLib.AddPhaseWithRawParts correzioni, ma ancora non funziona correttamente 2026-05-19 14:29:16 +02:00
andrea.villa a5d606b225 Prima versione gestione utensile flottante. Per ora solo su marcature.
Gestione da migliorare.
2026-05-19 13:05:15 +02:00
luca.mazzoleni 3ba456f72f - in BeamLib e correlate modificata AddPhaseWithRawParts per funzionare con overlap dei pezzi per nesting obliquo 2026-05-19 12:47:21 +02:00
luca.mazzoleni 608f8da033 - in NestProcess si fanno correttamente inversioni e rotazioni 2026-05-19 09:50:58 +02:00
luca.mazzoleni 08397ae102 - in NestProcess aggiunte eventuali rotazioni/inversioni duplo nella barra 2026-05-18 18:28:57 +02:00
luca.mazzoleni b7dbc7422c - in BeamExec.ProcessAlternatives si passa all'interfaccia da scrivere anche la posizione iniziale del pezzo 2026-05-18 17:26:05 +02:00
luca.mazzoleni 974d1abb41 - in NestProcess correzione bug 2026-05-18 16:40:58 +02:00
andrea.villa c4697fbd6f In STR0014:
- se utensile PEN, si riduce il percorso per evitare di attaccare fuori dal grezzo
- gestione parametro SCC bloccato letto dalla macchina
2026-05-18 16:38:02 +02:00
luca.mazzoleni b79617fbe4 - in NestProcess primo abbozzo della creazione MachGroup 2026-05-18 15:53:18 +02:00
luca.mazzoleni e5f1abc47d - in NestProcess aggiunto lo spostamento delle travi verso la testa della trave (vedere se poi integrare in creazione MachGroup) 2026-05-18 14:45:57 +02:00
luca.mazzoleni 965c6e8f9e - in NestProcess aggiunta MIN_FILLER_LIMITin CONFIG per pulizia codice 2026-05-18 12:40:06 +02:00
luca.mazzoleni d59039eae0 - in NestProcess correzioni in PrintDiagnosticReport 2026-05-18 12:28:36 +02:00
luca.mazzoleni a404bf2f9e - in NestProcess si provano barre nuove solo se non si trovano soluzioni con quelle già attive 2026-05-18 12:03:46 +02:00
luca.mazzoleni 1cde1c94d9 - in NestProcess aggiunta PrintDiagnosticReport per stimare la bontà del nesting; in CalculateMove modificato calcolo efficienza nel caso di barra nuova; correzioni minori 2026-05-18 11:32:15 +02:00
luca.mazzoleni a66054a6c8 - in NestProcess correzioni e modifiche per migliorare l'efficienza. Sembra funzionare, da verificare bontà nesting. Manca creazione MachGroup veri e propri 2026-05-18 10:16:20 +02:00
luca.mazzoleni b77e79d0d0 - in NestProcess loop completo, alcune migliorie possibili per prestazioni; manca la parte che effettivamente crea i MachGroup 2026-05-15 18:33:15 +02:00
luca.mazzoleni cad57b2fd5 - in NestProcess piccole correzioni 2026-05-15 10:37:58 +02:00
luca.mazzoleni 5e503762e5 - in NestProcess agiunto sorting della JobPool 2026-05-15 10:26:30 +02:00
luca.mazzoleni f27000b7bc - in NestProcess.PartTemplates:AddPart si salvano i MaxHeadRecess testa e coda; creata funzione FindBestPartForBeam, da completare 2026-05-15 10:10:25 +02:00
luca.mazzoleni f90dd95880 - in NestProcess creato il loop di base dello script. Mancano funzioni accessorie 2026-05-14 16:44:12 +02:00
luca.mazzoleni 0497877abb - in NestProcess ora si compilano correttamente le tabelle di grezzi e pezzi da nestare, in preparazione al neting 2026-05-14 15:39:29 +02:00
luca.mazzoleni b8299df247 - in BeamExec.ProcessAlternatives si passano correttamente le info a interfaccia da scrivere sul pezzo
- in BeamLib aggiunta funzione ConvertBitIndexToRotationIndex per convertire da BitIndex a RotationIndex
2026-05-13 18:42:01 +02:00
luca.mazzoleni 4a99f2bdf6 - in BeamExec.GetProcessings per HeadcutInfo e TailcutInfo si usano gli indici di rotazione canonici (1,2,3,4 per std e 5,6,7,8 per invertiti) 2026-05-13 16:28:04 +02:00
luca.mazzoleni 1e86180723 - in BeamExec si scrivono HeadcutInfo e TailcutInfo nel PARTS che serviranno per nesting; da completare output alternative 2026-05-13 16:00:20 +02:00
luca.mazzoleni f6d6043c0e - piccole modifiche per test nesting 2026-05-13 12:40:45 +02:00
luca.mazzoleni b048e2ebe2 - in BeamLib.GetSortedVertices piccola correzione 2026-05-13 11:58:28 +02:00
luca.mazzoleni fc47bca0f1 - in NestProcess prime modifiche per nesting obliquo (da completare)
- in BeamExec test BEAM.INFONGEPART per scrittura note pezzo in nge tramite Aedifica
- in BeamLib aggiunta funzione RotateTableFromIndex per reindicizzare una tabella passata
2026-05-13 11:47:25 +02:00
luca.mazzoleni 0274096f57 - in BeamExec.GetFeatureInfoAndDependency si salvano le info necessarie per nesting (offset X dei vertici dei tagli rispetto al box, normali delle facce) 2026-05-12 11:59:26 +02:00
luca.mazzoleni 983609397e - in BeamLib funzione GetSurfTmSortedVertices diventa GetSortedVertices e si passa la Proc direttamente
- in BeamLib aggiunta funzione GetAdjacentIndices per la ricerca degli indici precedente e successivo con circular indexing
2026-05-12 10:45:26 +02:00
luca.mazzoleni 05a8d23f6a - in BeamExec.GetFeatureInfoAndDependency si calcolano i punti ai vertici dei tagli di testa e coda
- in BeamLib aggiunta funzione GetSurfTmSortedVertices per restituire i punti ai vertici già ordinati; da correggere perchè i vertici non arrivano ordinati dalla funzione EgtSurfTmGetAllVertInFacet
2026-05-12 09:06:43 +02:00
luca.mazzoleni 40580cdc69 - NestProcess attuale rinominata Old per test nesting obliqui, con NestProcess ripulita 2026-05-11 12:42:34 +02:00
luca.mazzoleni f6b2477f2b - in BeamExec.GetFeatureInfoAndDependency correzione 2026-05-08 12:29:46 +02:00
luca.mazzoleni 69db74e30e - in BeamExec.ProcessBeams modifiche per accettare grezzi compenetranti
- in BeamExec.GetFeatureInfoAndDependency si scelgono taglio di testa e coda anche obliqui, quelli più verso il centro della trave. Gli altri tagli si disattivano
- da completare
2026-05-08 12:00:58 +02:00
luca.mazzoleni f58004dfeb - in PreSimulationLIb correzioni importanti in test collisione 2026-05-08 11:54:16 +02:00
luca.mazzoleni 7c485360de Merge branch 'ScarfJoint' into develop 2026-04-27 18:18:19 +02:00
12 changed files with 1694 additions and 662 deletions
+2 -1
View File
@@ -390,7 +390,8 @@ if bToProcess then
end end
end end
-- Assegno lunghezza della barra -- Assegno lunghezza della barra
dBarLen = PARTS[1].b3PartOriginal:getDimX() + 10 -- TODO nella ProcessBeams andava in errore con 10mm!!! CONTROLLARE
dBarLen = PARTS[1].b3PartOriginal:getDimX() + 20
if dBarLen < 2200 then if dBarLen < 2200 then
dBarLen = dBarLen + 1800 dBarLen = dBarLen + 1800
end end
+401 -214
View File
@@ -153,6 +153,11 @@ function BeamExec.GetToolsFromDB()
Tool.nDouble = EgtGetValInNotes( Tool.sUserNotes, 'DOUBLE', 'd') Tool.nDouble = EgtGetValInNotes( Tool.sUserNotes, 'DOUBLE', 'd')
Tool.bIsProfiledTool = not EgtTdbIsCurrToolStandardDraw() Tool.bIsProfiledTool = not EgtTdbIsCurrToolStandardDraw()
-- TODO per capire se ToolHolder è flottante bisogna leggere nota TYPE='Float' su ToolHolder. Serve funzione
-- info per utensile su ToolHolder flottante
Tool.dOverHang = EgtGetValInNotes( Tool.sUserNotes, 'TOOL_OVERHANG', 'd') or 0
Tool.bToolOnFloatingTH = Tool.dOverHang > 0
-- lettura parametri non comuni ( famiglia DRILLBIT non ha parametri specifici) -- lettura parametri non comuni ( famiglia DRILLBIT non ha parametri specifici)
if sToolFamily ~= 'DRILLBIT' then if sToolFamily ~= 'DRILLBIT' then
Tool.dThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK) Tool.dThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK)
@@ -251,6 +256,27 @@ function BeamExec.GetStrategiesFromJSONinBD( sAISetupConfigName)
end end
end end
-------------------------------------------------------------------------------------------------------------
local function GetRotationName( nRotIndex, nInvertIndex)
local sRotation = ''
if nRotIndex == 1 then
sRotation = '0'
elseif nRotIndex == 2 then
sRotation = '90'
elseif nRotIndex == 3 then
sRotation = '180'
elseif nRotIndex == 4 then
sRotation = '270'
end
if nInvertIndex > 1 then
sRotation = sRotation .. 'INV'
end
return sRotation
end
-- TODO prevedere parametri per preferire carico del pezzo verticale oppure orizzontale? -- TODO prevedere parametri per preferire carico del pezzo verticale oppure orizzontale?
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- funzione che controlla validità delle combinazioni proposte -- funzione che controlla validità delle combinazioni proposte
@@ -356,188 +382,179 @@ function BeamExec.GetAvailableCombinations( PartInfo, bIsFlipRot)
end end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- *** funzioni posizionamento pezzi all'interno della barra *** -- *** Funzioni posizionamento pezzi all'interno della barra***
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bIsFlipRot) function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bIsFlipRot )
-- gruppo per geometrie temporanee -- 1. Inizializzazione e Default
local idTempGroup = BeamLib.GetTempGroup() local idTempGroup = BeamLib.GetTempGroup( )
-- default per nuove costanti qualora non definite BeamData.OVM_BLADE_HBEAM = ( BeamData.OVM_BLADE_HBEAM or 11 )
BeamData.OVM_BLADE_HBEAM = ( BeamData.OVM_BLADE_HBEAM or 11) BeamData.OVM_CHAIN_HBEAM = ( BeamData.OVM_CHAIN_HBEAM or 8 )
BeamData.OVM_CHAIN_HBEAM = ( BeamData.OVM_CHAIN_HBEAM or 8)
-- sovramateriale intermedio nullo se non definito dOvmMid = ( dOvmMid or 5.4 )
dOvmMid = ( dOvmMid or 0) dOvmHead = ( dOvmHead or 0 )
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH )
-- Determinazione minimo grezzo scaricabile -- 2. Gestione Gruppo di Lavoro
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) if ( bCreateMachGroup == nil ) then bCreateMachGroup = true end
if ( bCreateMachGroup ) then
-- Creazione nuovo gruppo di lavoro (di default va creato) local sMgName = EgtGetMachGroupNewName( 'Mach_1' )
if bCreateMachGroup == nil then local idNewMg = EgtAddMachGroup( sMgName )
bCreateMachGroup = true if ( not idNewMg ) then
end return false, 'Errore creazione gruppo di lavoro'
if bCreateMachGroup then
local sMgName = EgtGetMachGroupNewName( 'Mach_1')
local idNewMg = EgtAddMachGroup( sMgName)
if not idNewMg then
local sOut = 'Errore nella creazione del gruppo di lavoro ' .. sMgName
return false, sOut
end end
end end
-- Impostazione della tavola -- 3. Configurazione Tavola Macchina
EgtSetTable( 'Tab') EgtSetTable( 'Tab' )
local nMGrpId = EgtGetCurrMachGroup( )
-- salvo nota con lunghezza grezzo if ( not EgtGetInfo( nMGrpId, 'BARLEN', 'd' ) ) then
-- Recupero l'identificativo del gruppo di lavoro corrente EgtSetInfo( nMGrpId, 'BARLEN', dRawL )
local nMGrpId = EgtGetCurrMachGroup()
-- Lunghezza della barra
local dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd')
if not dBarLen then
EgtSetInfo( nMGrpId, 'BARLEN', dRawL)
end end
-- Area tavola local b3Tab = EgtGetTableArea( )
local b3Tab = EgtGetTableArea() local dPosY = EgtIf( BeamData.CENTER_BEAM, ( b3Tab:getDimY( ) + dRawW * EgtIf( BeamData.RIGHT_LOAD, -1, 1 ) ) / 2, EgtIf( BeamData.RIGHT_LOAD, 0, b3Tab:getDimY( ) ) )
-- Calcolo posizione estremo TR/BR della tavola rispetto a sua origine in BL
local dPosY = EgtIf( BeamData.CENTER_BEAM, ( b3Tab:getDimY() + dRawW * EgtIf( BeamData.RIGHT_LOAD, -1, 1)) / 2, EgtIf( BeamData.RIGHT_LOAD, 0, b3Tab:getDimY())) BeamData.ptOriXR = Point3d( b3Tab:getDimX( ), dPosY, 0 )
BeamData.ptOriXR = Point3d( b3Tab:getDimX(), dPosY, 0) BeamData.dPosXR = EgtIf( BeamData.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR )
BeamData.dPosXR = EgtIf( BeamData.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR)
-- Impostazione dell'attrezzaggio di default EgtImportSetup( )
EgtImportSetup()
-- Inserimento dei pezzi con il loro grezzo -- 4. Ciclo di Inserimento Pezzi
local nCnt = 0 local nCnt = 0
local dLen = dRawL local dMaxX = 0
local idPrevRaw, dPrevDelta local idPrevRaw = nil
local dDeltaS = dOvmHead local dNextStartOffset = dOvmHead -- Il primo pezzo applica il sormonto iniziale a destra (testa)
local dDeltaSMin = 0
local dDeltaE = BeamData.OVM_MID
for i = 1, #PARTS do for i = 1, #PARTS do
-- dati del pezzo local CurrentPart = PARTS[i]
local b3BoxExact = EgtGetBBoxGlob( PARTS[i].id or GDB_ID.NULL, GDB_BB.EXACT) local b3BoxExact = EgtGetBBoxGlob( CurrentPart.id or GDB_ID.NULL, GDB_BB.EXACT )
if b3BoxExact:isEmpty() or PARTS[i].b3PartOriginal:isEmpty() then break end
EgtOutLog( 'PartSez=' .. EgtNumToString( b3BoxExact:getDimY(), 1) .. 'x' .. EgtNumToString( b3BoxExact:getDimZ(), 1), 3) if ( b3BoxExact:isEmpty( ) or CurrentPart.b3PartOriginal:isEmpty( ) ) then break end
-- se sezione compatibile e lunghezza disponibile sufficiente
local dPartLen = PARTS[i].b3PartOriginal:getDimX()
local dPartWidth = PARTS[i].b3PartOriginal:getDimY()
local dPartHeight = PARTS[i].b3PartOriginal:getDimZ()
local dNextLen = dLen - EgtIf( i == 1, dDeltaS, 0) - dPartLen - dDeltaE
if (( abs( dPartWidth - dRawW) < 100 * GEO.EPS_SMALL and abs( dPartHeight - dRawH) < 100 * GEO.EPS_SMALL) or
( abs( dPartHeight - dRawW) < 100 * GEO.EPS_SMALL and abs( dPartWidth - dRawH) < 100 * GEO.EPS_SMALL)) and
dNextLen + dDeltaE >= 0 then
-- eventuale sovramateriale di testa
if i > 1 then
if PARTS[i].dPosX then
dDeltaS = max( PARTS[i].dPosX - ( dRawL - dLen), dDeltaSMin)
else
dDeltaS = max( dOvmMid - dDeltaE, 0)
end
end
-- dimensioni del grezzo
local dCrawLen = min( dPartLen + dDeltaS + dDeltaE, dLen)
local dDelta = dCrawLen - dPartLen - dDeltaS
-- creo e posiziono il grezzo
PARTS[i].idRaw = EgtAddRawPart( Point3d(0,0,0), dCrawLen, dRawW, dRawH, BeamData.RAWCOL)
EgtMoveToCornerRawPart( PARTS[i].idRaw, BeamData.ptOriXR, BeamData.dPosXR) local dPartLen = CurrentPart.b3PartOriginal:getDimX( )
EgtMoveRawPart( PARTS[i].idRaw, Vector3d( dLen - dRawL, 0, 0)) local dPartWidth = CurrentPart.b3PartOriginal:getDimY( )
-- assegno ordine in lavorazione local dPartHeight = CurrentPart.b3PartOriginal:getDimZ( )
local dStartOffset = dNextStartOffset
local dEndOffset = dOvmMid
-- LOGICA LOOK-AHEAD: Analisi del gap reale per la ripartizione specchiata
if ( i < #PARTS ) then
local dTotalGap = PARTS[i + 1].dPosX - CurrentPart.dPosX - dPartLen
if ( dTotalGap > dOvmMid ) then
dEndOffset = dOvmMid -- Max 5.4mm sulla coda (lato sinistro del grezzo)
dNextStartOffset = dTotalGap - dOvmMid -- Il residuo sulla testa del prossimo (lato destro)
else
-- Gestione automatica sotto-soglia o compenetrazione geometrica (Nesting Obliquo)
dEndOffset = dTotalGap
dNextStartOffset = 0
end
end
-- MATEMATICA CORRETTA PER X CAD INVERTITA:
-- Il grezzo idRaw si estende verso destra. Spostando il pezzo internamente di dEndOffset (dDelta),
-- lasciamo dEndOffset a sinistra (coda) e matematicamente dStartOffset a destra (testa).
local dCrawLen = dPartLen + dStartOffset + dEndOffset
local dDelta = dEndOffset
local dStartPos = (CurrentPart.dPosX or 0) - dStartOffset
local bIsSectionOk = ( ( abs( dPartWidth - dRawW ) < 100 * GEO.EPS_SMALL and abs( dPartHeight - dRawH ) < 100 * GEO.EPS_SMALL ) or
( abs( dPartHeight - dRawW ) < 100 * GEO.EPS_SMALL and abs( dPartWidth - dRawH ) < 100 * GEO.EPS_SMALL ) )
if ( bIsSectionOk and ( dStartPos + dCrawLen <= dRawL + GEO.EPS_SMALL ) ) then
-- 5. Creazione e Posizionamento del Contenitore RawPart
CurrentPart.idRaw = EgtAddRawPart( Point3d( 0, 0, 0 ), dCrawLen, dRawW, dRawH, BeamData.RAWCOL )
EgtMoveToCornerRawPart( CurrentPart.idRaw, BeamData.ptOriXR, BeamData.dPosXR )
EgtMoveRawPart( CurrentPart.idRaw, Vector3d( -dStartPos, 0, 0 ) )
-- 6. Configurazione Geometrie Pezzo
nCnt = nCnt + 1 nCnt = nCnt + 1
EgtSetInfo( PARTS[i].idRaw, 'ORD', nCnt) EgtSetInfo( CurrentPart.idRaw, 'ORD', nCnt )
-- creo o pulisco gruppo geometrie aggiuntive
if not BeamLib.CreateOrEmptyAddGroup( PARTS[i].id) then if ( not BeamLib.CreateOrEmptyAddGroup( CurrentPart.id ) ) then
local sOut = 'Error creating Additional Group in Part ' .. tostring( PARTS[i].id) return false, 'Error creating Additional Group in Part ' .. tostring( CurrentPart.id )
return false, sOut
end end
-- aggiungo faccia per taglio iniziale al pezzo
BeamLib.AddPartStartFace( PARTS[i].id, PARTS[i].b3PartOriginal) BeamLib.AddPartStartFace( CurrentPart.id, CurrentPart.b3PartOriginal )
-- se sovramateriale di testa, lo notifico BeamLib.AddPartEndFace( CurrentPart.id, CurrentPart.b3PartOriginal )
if dDeltaS > 0.09 then
EgtSetInfo( PARTS[i].idRaw, 'HOVM', dDeltaS)
if idPrevRaw then
EgtSetInfo( idPrevRaw, 'BDST', dDeltaS + dPrevDelta)
end
end
if dDeltaE > 0.09 then
EgtSetInfo( PARTS[i].idRaw, 'TOVM', dDeltaE)
end
-- aggiungo faccia per taglio finale al pezzo
BeamLib.AddPartEndFace( PARTS[i].id, PARTS[i].b3PartOriginal)
-- inserisco il pezzo nel grezzo
EgtDeselectPartObjs( PARTS[i].id)
local ptPos = b3BoxExact:getMin() - PARTS[i].b3PartOriginal:getMin() + Vector3d( dDelta, ( dRawW - dPartWidth) / 2, ( dRawH - dPartHeight) / 2)
EgtAddPartToRawPart( PARTS[i].id, ptPos, PARTS[i].idRaw)
if abs( dPartWidth - dRawW) > 100 * GEO.EPS_SMALL then
-- rotazione attorno a centro geometria complessiva del pezzo
EgtRotatePartInRawPart( PARTS[i].id, X_AX(), 90)
-- correggo per eccentricità solido rispetto a geometria complessiva del pezzo
local vtEccOri = PARTS[i].b3PartOriginal:getCenter() - b3BoxExact:getCenter()
local vtEccRot = Vector3d( vtEccOri)
vtEccRot:rotate( X_AX(), 90)
EgtMovePartInRawPart( PARTS[i].id, ( vtEccOri - vtEccRot))
end
-- aggiorno la lunghezza residua della barra
dLen = dLen - dCrawLen
-- aggiorno grezzo precedente
idPrevRaw = PARTS[i].idRaw
dPrevDelta = dDelta
PARTS[i].bIsLastPart = ( i == #PARTS)
PARTS[i].dDistanceToNextPiece = dDelta
PARTS[i].dRestLength = dLen
PARTS[i].b3Raw = EgtGetRawPartBBox( PARTS[i].idRaw)
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].idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL)
PARTS[i].b3Part = EgtGetBBoxGlob( PARTS[i].idBoxTm, GDB_BB.STANDARD)
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].dHeadOverMaterial = dDeltaS
PARTS[i].sBTLInfo = EgtGetInfo( PARTS[i].id, 'PROJ', 's') or nil
PARTS[i].sAISetupConfig = EgtGetInfo( PARTS[i].id, 'AISETUP', 's') or -- Inserimento con dDelta (lascia lo spazio vuoto a sinistra e spinge il pezzo a destra)
( GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo] and GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo].sAISetupConfig) or -- i parametri BTL potrebbero non esistere EgtDeselectPartObjs( CurrentPart.id )
GENERAL_PARAMETERS.PROJECT.sAISetupConfig or nil local ptPos = b3BoxExact:getMin( ) - CurrentPart.b3PartOriginal:getMin( ) + Vector3d( dDelta, ( dRawW - dPartWidth ) / 2, ( dRawH - dPartHeight ) / 2 )
EgtAddPartToRawPart( CurrentPart.id, ptPos, CurrentPart.idRaw )
-- si carica configurazione lavorazioni -- Rotazione sezione se necessaria
TIMER:startElapsed('Json') if ( abs( dPartWidth - dRawW ) > 100 * GEO.EPS_SMALL ) then
BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig) EgtRotatePartInRawPart( CurrentPart.id, X_AX( ), 90 )
PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON) local vtEccOri = CurrentPart.b3PartOriginal:getCenter( ) - b3BoxExact:getCenter( )
TIMER:stopElapsed('Json') local vtEccRot = Vector3d( vtEccOri )
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bIsFlipRot) vtEccRot:rotate( X_AX( ), 90 )
PARTS[i].idTempGroup = idTempGroup EgtMovePartInRawPart( CurrentPart.id, ( vtEccOri - vtEccRot ) )
end
-- 7. Popolamento Metadati della Tabella CurrentPart
CurrentPart.bIsLastPart = ( i == #PARTS )
CurrentPart.dDistanceToNextPiece = dEndOffset
CurrentPart.b3Raw = EgtGetRawPartBBox( CurrentPart.idRaw )
CurrentPart.dLength = CurrentPart.b3Raw:getDimX( )
CurrentPart.dWidth = CurrentPart.b3Raw:getDimY( )
CurrentPart.dHeight = CurrentPart.b3Raw:getDimZ( )
CurrentPart.bSquareSection = abs( CurrentPart.dWidth - CurrentPart.dHeight ) < 100 * GEO.EPS_SMALL
CurrentPart.idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( CurrentPart.id, 'Box' ) or GDB_ID.NULL )
CurrentPart.b3Part = EgtGetBBoxGlob( CurrentPart.idBoxTm, GDB_BB.STANDARD )
CurrentPart.nIndexInParts = i
CurrentPart.SplittingPoints = BeamLib.GetPartSplittingPoints( CurrentPart )
CurrentPart.NotClampableLength = { STD = { dHead = 0, dTail = 0 }, SIDE = { dHead = 0, dTail = 0 }, DOWN = { dHead = 0, dTail = 0 } }
CurrentPart.dHeadOverMaterial = dStartOffset
CurrentPart.sBTLInfo = EgtGetInfo( CurrentPart.id, 'PROJ', 's' ) or nil
CurrentPart.idTempGroup = idTempGroup
-- Notifiche al Post-Processor basate sulla nuova scomposizione
if ( dStartOffset > 0.09 ) then EgtSetInfo( CurrentPart.idRaw, 'HOVM', dStartOffset ) end
if ( dEndOffset > 0.09 ) then EgtSetInfo( CurrentPart.idRaw, 'TOVM', dEndOffset ) end
if ( idPrevRaw ) then EgtSetInfo( idPrevRaw, 'BDST', dStartOffset ) end
-- Caricamento Strategie JSON
CurrentPart.sAISetupConfig = EgtGetInfo( CurrentPart.id, 'AISETUP', 's' ) or
( GENERAL_PARAMETERS.BTL[CurrentPart.sBTLInfo] and GENERAL_PARAMETERS.BTL[CurrentPart.sBTLInfo].sAISetupConfig ) or
GENERAL_PARAMETERS.PROJECT.sAISetupConfig or nil
TIMER:startElapsed( 'Json' )
BeamExec.GetStrategiesFromJSONinBD( CurrentPart.sAISetupConfig )
CurrentPart.GeneralParameters = BeamLib.GetPieceGeneralParameters( CurrentPart, GENERAL_PARAMETERS_JSON )
TIMER:stopElapsed( 'Json' )
CurrentPart.CombinationList = BeamExec.GetAvailableCombinations( CurrentPart, bIsFlipRot )
-- Avanzamento calcolato sulla coordinata reale di fine RawPart (estremità sinistra sulla barra)
dMaxX = max( dMaxX, dStartPos + dCrawLen )
CurrentPart.dRestLength = dRawL - dMaxX
idPrevRaw = CurrentPart.idRaw
else else
local sOut = 'Error: part L(' .. EgtNumToString( dPartLen, 1) .. ') too big for raw part L(' .. EgtNumToString( dLen - 0.1, 1) .. ')' local sOut = 'Error: part L(' .. EgtNumToString( dPartLen, 1 ) .. ') too big for remaining bar space'
return false, sOut return false, sOut
end end
-- se rimasto troppo poco grezzo, esco
--if Len < BeamData.MinRaw then break end
DeltaS = 0
end
if idPrevRaw then
EgtSetInfo( idPrevRaw, 'BDST', 10000)
end end
-- Se rimasto materiale aggiungo grezzo dell'avanzo -- 8. Chiusura Barra e Gestione Avanzo (Rest Material)
-- TODO valutare se ridurre la dLen minima perchè crea discrepanze tra lunghezza inserita e VMill if ( idPrevRaw ) then EgtSetInfo( idPrevRaw, 'BDST', 10000 ) end
if dLen > 10 then
local idRaw = EgtAddRawPart( Point3d(0,0,0), dLen, dRawW, dRawH, BeamData.RAWCOL) local dRemaining = dRawL - dMaxX
EgtMoveToCornerRawPart( idRaw, BeamData.ptOriXR, BeamData.dPosXR) if ( dRemaining > 10 ) then
EgtMoveRawPart( idRaw, Vector3d( dLen - dRawL, 0, 0)) local idRawRest = EgtAddRawPart( Point3d( 0, 0, 0 ), dRemaining, dRawW, dRawH, BeamData.RAWCOL )
-- assegno ordine in lavorazione EgtMoveToCornerRawPart( idRawRest, BeamData.ptOriXR, BeamData.dPosXR )
EgtMoveRawPart( idRawRest, Vector3d( -dMaxX, 0, 0 ) )
nCnt = nCnt + 1 nCnt = nCnt + 1
EgtSetInfo( idRaw, 'ORD', nCnt) EgtSetInfo( idRawRest, 'ORD', nCnt )
-- aggiorno distanza dell'ultimo pezzo dall'eventuale grezzo scaricabile
if EgtGetRawPartBBox( idRaw):getDimX() < BeamData.dMinRaw then if ( EgtGetRawPartBBox( idRawRest ):getDimX( ) < BeamData.dMinRaw ) then
PARTS[#PARTS].dDistanceToNextPiece = 10000 PARTS[#PARTS].dDistanceToNextPiece = 10000
end end
else else
PARTS[#PARTS].dDistanceToNextPiece = 10000 if ( #PARTS > 0 ) then PARTS[#PARTS].dDistanceToNextPiece = 10000 end
end end
return true return true
@@ -781,9 +798,24 @@ end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
local function GetFeatureInfoAndDependency( vProcSingleRot, Part) local function GetFeatureInfoAndDependency( vProcSingleRot, Part)
-- gruppo per geometrie temporanee
local idTempGroup = BeamLib.GetTempGroup()
local HeadProcOriginal
local TailProcOriginal
local HeadProc
local TailProc
-- ciclo tutte le feature -- ciclo tutte le feature
for i = 1, #vProcSingleRot do for i = 1, #vProcSingleRot do
local Proc = vProcSingleRot[i] local Proc = vProcSingleRot[i]
if Proc.Topology.sName == 'HeadCut' then
HeadProcOriginal = Proc
HeadProcOriginal.bIsOriginalHeadcut = true
elseif Proc.Topology.sName == 'TailCut' then
TailProcOriginal = Proc
TailProcOriginal.bIsOriginalTailcut = true
end
-- se feature abilitata alla lavorazione -- se feature abilitata alla lavorazione
if Proc.nFlg ~= 0 then if Proc.nFlg ~= 0 then
-- controllo la feature con tutte le altre per recuperare le dipendenze -- controllo la feature con tutte le altre per recuperare le dipendenze
@@ -791,6 +823,86 @@ local function GetFeatureInfoAndDependency( vProcSingleRot, Part)
local ProcB = vProcSingleRot[j] local ProcB = vProcSingleRot[j]
-- non si controlla la feature con se stessa o se feature disabilitata -- non si controlla la feature con se stessa o se feature disabilitata
if i ~= j and ProcB.nFlg ~= 0 then if i ~= j and ProcB.nFlg ~= 0 then
local bAreBothTruncatingCuts =
( ID.IsCut( Proc) or ID.IsHeadCut( Proc) or ID.IsTailCut( Proc)) and ( ID.IsCut( ProcB) or ID.IsHeadCut( ProcB) or ID.IsTailCut( ProcB))
and ( FeatureLib.IsFeatureCuttingEntireSection( Proc.b3Box, Part) and FeatureLib.IsFeatureCuttingEntireSection( ProcB.b3Box, Part))
-- si trovano i veri tagli di testa e coda e si disattivano gli altri, se necessario
if bAreBothTruncatingCuts then
-- testa
if Proc.Faces[1].vtN:getX() > GEO.EPS_SMALL and ProcB.Faces[1].vtN:getX() > GEO.EPS_SMALL then
-- il primo taglio è più verso il centro della trave
if ( Proc.b3Box:getMin():getX() < ProcB.b3Box:getMin():getX() - 10 * GEO.EPS_SMALL) then
HeadProc = Proc
local idProcCopy = EgtCopyGlob( Proc.id, idTempGroup)
local idProcBCopy = EgtCopyGlob( ProcB.id, idTempGroup)
EgtMove( idProcCopy, - 500 * GEO.EPS_SMALL * Proc.Faces[1].vtN, GDB_RT.GLOB)
EgtMove( idProcBCopy, 500 * GEO.EPS_SMALL * ProcB.Faces[1].vtN, GDB_RT.GLOB)
-- se i tagli non si intersecano, quello più esterno è da disattivare
if not EgtTestSurfaceSurface( idProcCopy, idProcBCopy, GEO.EPS_SMALL) then
if not Proc.SlaveProcIndexes then
Proc.SlaveProcIndexes = {}
end
table.insert( Proc.SlaveProcIndexes, j)
ProcB.nIndexMasterProc = i
ProcB.nFlg = 0
end
-- il secondo taglio è più verso il centro della trave
elseif Proc.b3Box:getMin():getX() >= ProcB.b3Box:getMin():getX() - 10 * GEO.EPS_SMALL then
HeadProc = ProcB
local idProcCopy = EgtCopyGlob( Proc.id, idTempGroup)
local idProcBCopy = EgtCopyGlob( ProcB.id, idTempGroup)
EgtMove( idProcBCopy, - 500 * GEO.EPS_SMALL * ProcB.Faces[1].vtN, GDB_RT.GLOB)
EgtMove( idProcCopy, 500 * GEO.EPS_SMALL * Proc.Faces[1].vtN, GDB_RT.GLOB)
-- se i tagli non si intersecano, quello più esterno è da disattivare
if not EgtTestSurfaceSurface( idProcCopy, idProcBCopy, GEO.EPS_SMALL) then
if not ProcB.SlaveProcIndexes then
ProcB.SlaveProcIndexes = {}
end
table.insert( ProcB.SlaveProcIndexes, i)
Proc.nIndexMasterProc = j
Proc.nFlg = 0
end
end
-- coda
elseif Proc.Faces[1].vtN:getX() <= GEO.EPS_SMALL and ProcB.Faces[1].vtN:getX() <= GEO.EPS_SMALL then
-- il primo taglio è più verso il centro della trave
if Proc.b3Box:getMax():getX() > ProcB.b3Box:getMax():getX() + 10 * GEO.EPS_SMALL then
TailProc = Proc
local idProcCopy = EgtCopyGlob( Proc.id, idTempGroup)
local idProcBCopy = EgtCopyGlob( ProcB.id, idTempGroup)
EgtMove( idProcCopy, - 500 * GEO.EPS_SMALL * Proc.Faces[1].vtN, GDB_RT.GLOB)
EgtMove( idProcBCopy, 500 * GEO.EPS_SMALL * ProcB.Faces[1].vtN, GDB_RT.GLOB)
-- se i tagli non si intersecano, quello più esterno è da disattivare
if not EgtTestSurfaceSurface( idProcCopy, idProcBCopy, GEO.EPS_SMALL) then
if not Proc.SlaveProcIndexes then
Proc.SlaveProcIndexes = {}
end
table.insert( Proc.SlaveProcIndexes, j)
ProcB.nIndexMasterProc = i
ProcB.nFlg = 0
end
-- il secondo taglio è più verso il centro della trave
elseif Proc.b3Box:getMax():getX() >= ProcB.b3Box:getMax():getX() - 10 * GEO.EPS_SMALL then
TailProc = ProcB
local idProcCopy = EgtCopyGlob( Proc.id, idTempGroup)
local idProcBCopy = EgtCopyGlob( ProcB.id, idTempGroup)
EgtMove( idProcBCopy, - 500 * GEO.EPS_SMALL * ProcB.Faces[1].vtN, GDB_RT.GLOB)
EgtMove( idProcCopy, 500 * GEO.EPS_SMALL * Proc.Faces[1].vtN, GDB_RT.GLOB)
-- se i tagli non si intersecano, quello più esterno è da disattivare
if not EgtTestSurfaceSurface( idProcCopy, idProcBCopy, GEO.EPS_SMALL) then
if not ProcB.SlaveProcIndexes then
ProcB.SlaveProcIndexes = {}
end
table.insert( ProcB.SlaveProcIndexes, i)
Proc.nIndexMasterProc = j
Proc.nFlg = 0
end
end
end
end
-- se entrambi tagli di testa, si tiene sempre il primo ( ma non quello aggiunto dall'automatismo) -- se entrambi tagli di testa, si tiene sempre il primo ( ma non quello aggiunto dall'automatismo)
if ( ID.IsHeadCut( Proc) and not EgtGetInfo( Proc.id, 'HEAD_ADD_CUT', 'i')) and ID.IsHeadCut( ProcB) then if ( ID.IsHeadCut( Proc) and not EgtGetInfo( Proc.id, 'HEAD_ADD_CUT', 'i')) and ID.IsHeadCut( ProcB) then
if not Proc.SlaveProcIndexes then if not Proc.SlaveProcIndexes then
@@ -828,7 +940,43 @@ local function GetFeatureInfoAndDependency( vProcSingleRot, Part)
end end
end end
end end
return vProcSingleRot
if not HeadProc then
HeadProc = HeadProcOriginal
end
if not TailProc then
TailProc = TailProcOriginal
end
HeadProc.Topology = {}
TailProc.Topology = {}
HeadProc.Topology.sFamily = 'HeadCut'
HeadProc.Topology.sName = 'HeadCut'
TailProc.Topology.sFamily = 'TailCut'
TailProc.Topology.sName = 'TailCut'
HeadProc.AvailableStrategies = GetStrategies( HeadProc, Part.sAISetupConfig)
TailProc.AvailableStrategies = GetStrategies( TailProc, Part.sAISetupConfig)
-- per nesting, si settano come info gli offset X degli estremi dei tagli
local HeadcutInfo = {}
local PtSortedHead = BeamLib.GetSortedVertices( HeadProc)
if PtSortedHead then
HeadcutInfo.OffsetX = {}
for i = 1, #PtSortedHead do
table.insert( HeadcutInfo.OffsetX, Part.b3Part:getMax():getX() - PtSortedHead[i]:getX())
end
end
local TailcutInfo = {}
local PtSortedTail = BeamLib.GetSortedVertices( TailProc)
if PtSortedTail then
TailcutInfo.OffsetX = {}
for i = 1, #PtSortedHead do
table.insert( TailcutInfo.OffsetX, Part.b3Part:getMin():getX() - PtSortedTail[i]:getX())
end
end
-- per nesting, si settano come info le normali delle facce di taglio
HeadcutInfo.vtN = HeadProc.Faces[1].vtN
TailcutInfo.vtN = TailProc.Faces[1].vtN
return vProcSingleRot, HeadcutInfo, TailcutInfo
end end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
@@ -983,6 +1131,9 @@ local function CalculateStrategies( vProcSingleRot, Part)
Proc.AvailableStrategies[nIndexCurrentStrategy].Result.dTimeToMachine = 99 Proc.AvailableStrategies[nIndexCurrentStrategy].Result.dTimeToMachine = 99
end end
if not Proc.AvailableStrategies.dAllStrategiesTotalTime then
Proc.AvailableStrategies.dAllStrategiesTotalTime = 0
end
Proc.AvailableStrategies.dAllStrategiesTotalTime = Proc.AvailableStrategies.dAllStrategiesTotalTime + Proc.AvailableStrategies[nIndexCurrentStrategy].Result.dTimeToMachine Proc.AvailableStrategies.dAllStrategiesTotalTime = Proc.AvailableStrategies.dAllStrategiesTotalTime + Proc.AvailableStrategies[nIndexCurrentStrategy].Result.dTimeToMachine
-- se scelta strategia in modalità base o standard, esco subito alla prima che trovo completa -- se scelta strategia in modalità base o standard, esco subito alla prima che trovo completa
if Part.GeneralParameters.GEN_sMachiningStrategy == 'FIRST_IN_LIST' and Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sStatus == 'Complete' then if Part.GeneralParameters.GEN_sMachiningStrategy == 'FIRST_IN_LIST' and Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sStatus == 'Complete' then
@@ -1192,7 +1343,11 @@ local function CalculateMachinings( vProc, Part, nInitialRotation)
local StrategyScriptName = Proc.ChosenStrategy.sStrategyId .. '\\' .. Proc.ChosenStrategy.sStrategyId local StrategyScriptName = Proc.ChosenStrategy.sStrategyId .. '\\' .. Proc.ChosenStrategy.sStrategyId
local StrategyScript = require( StrategyScriptName) local StrategyScript = require( StrategyScriptName)
-- eseguo la strategia e si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati -- eseguo la strategia e si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati
_, _ = StrategyScript.Make( true, Proc, Part, Proc.ChosenStrategy) local _, Result = StrategyScript.Make( true, Proc, Part, Proc.ChosenStrategy)
-- per i tagli di testa e coda, che non hanno girato nel CalculateStrategies, si devono settare i risultati
if ID.IsHeadCut( Proc) or ID.IsTailCut( Proc) then
Proc.ChosenStrategy.Result = Result
end
-- se tutte le strategie disponibili non sono applicabili -- se tutte le strategie disponibili non sono applicabili
else else
local nOffsetIndex = EgtIf( Part.bPartInCombiIsInverted, 4, 0) local nOffsetIndex = EgtIf( Part.bPartInCombiIsInverted, 4, 0)
@@ -1244,12 +1399,16 @@ function BeamExec.GetProcessings( PARTS, bIsFlipRot)
-- se è prerotazione, oltre al ciclo normale, si devono verificare anche invertiti -- se è prerotazione, oltre al ciclo normale, si devono verificare anche invertiti
local bCalcInverted = bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion local bCalcInverted = bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion
local nCycles = EgtIf( bCalcInverted, 2, 1) local nCycles = EgtIf( bCalcInverted, 2, 1)
PARTS[nPart].HeadcutInfo = {}
PARTS[nPart].TailcutInfo = {}
-- per ogni inversione -- per ogni inversione
for nInvertIndex = 1, nCycles do for nInvertIndex = 1, nCycles do
-- per ogni rotazione -- per ogni rotazione
for nRotIndex = 1, 4 do for nRotIndex = 1, 4 do
local nOffsetIndex = EgtIf( nInvertIndex == 2, 4, 0) local nOffsetIndex = EgtIf( nInvertIndex == 2, 4, 0)
-- le rotazioni sono 1,2,3,4 (0, 90, 180, 270) e 5,6,7,8 (le stesse invertite)
local nIndex = nRotIndex + nOffsetIndex local nIndex = nRotIndex + nOffsetIndex
local HeadcutInfo, TailcutInfo
-- si calcolano le feature solo se la rotazione può essere presa in considerazione -- si calcolano le feature solo se la rotazione può essere presa in considerazione
if PARTS[nPart].CombinationList.Rotations[nRotIndex] == 1 then if PARTS[nPart].CombinationList.Rotations[nRotIndex] == 1 then
-- recupero le feature di lavorazione della trave -- recupero le feature di lavorazione della trave
@@ -1257,11 +1416,23 @@ function BeamExec.GetProcessings( PARTS, bIsFlipRot)
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
-- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no -- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no
vProcRot[nIndex] = GetFeatureInfoAndDependency( vProcRot[nIndex], PARTS[nPart]) vProcRot[nIndex], HeadcutInfo, TailcutInfo = GetFeatureInfoAndDependency( vProcRot[nIndex], PARTS[nPart])
else else
-- inserisco una tabella vuota -- inserisco una tabella vuota
table.insert( vProcRot, {}) table.insert( vProcRot, {})
end end
if HeadcutInfo then
PARTS[nPart].HeadcutInfo[nIndex] = {
OffsetX = HeadcutInfo.OffsetX,
vtN = HeadcutInfo.vtN
}
end
if TailcutInfo then
PARTS[nPart].TailcutInfo[nIndex] = {
OffsetX = TailcutInfo.OffsetX,
vtN = TailcutInfo.vtN
}
end
-- rotazione pezzo di 90° per volta -- rotazione pezzo di 90° per volta
BeamLib.RotateRawPart( PARTS[nPart], 1) BeamLib.RotateRawPart( PARTS[nPart], 1)
-- aggiorno info pezzo -- aggiorno info pezzo
@@ -1491,13 +1662,15 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bRePro
for nProc = 1, #ProcessingsOnPart.Rotation[1] do 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 -- 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 -- 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 local ProcOnFirstRotation = ProcessingsOnPart.Rotation[1][nProc]
ProcessingsOnPart.Rotation[1][nProc].nIndexRotation = nUnloadPos if ProcOnFirstRotation.nFlg == 0 and ProcOnFirstRotation.nIndexMasterProc then
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[1][nProc]) ProcOnFirstRotation.nIndexRotation = nUnloadPos
table.insert( SingleCombination.Rot0, ProcOnFirstRotation)
SingleCombination.nComplete = SingleCombination.nComplete + 1 SingleCombination.nComplete = SingleCombination.nComplete + 1
else else
local nOffsetIndex = EgtIf( SingleCombination.bPartInCombiIsInverted, 4, 0) local nOffsetIndex = EgtIf( SingleCombination.bPartInCombiIsInverted, 4, 0)
if not ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) and not ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then if not ( ( ID.IsHeadCut( ProcOnFirstRotation) and ProcOnFirstRotation.bIsOriginalHeadcut)
or ( ID.IsTailCut( ProcOnFirstRotation) and ProcOnFirstRotation.bIsOriginalTailcut)) then
-- ciclo sulle rotazioni -- ciclo sulle rotazioni
local nNextRot = nUnloadPos local nNextRot = nUnloadPos
local ResultsList = {} local ResultsList = {}
@@ -1523,34 +1696,40 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bRePro
nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1) nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1)
end end
-- se la feature può essere lavorata in almeno una rotazione -- se la feature può essere lavorata in almeno una rotazione e non è un taglio di testa o coda
if #ResultsList > 0 then if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo) SingleCombination.nIndexHeadCutInVProc = nProc
Proc.nIndexRotation = Data.nIndexRotation elseif ID.IsTailCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
-- inserisco la Proc nell'apposita lista SingleCombination.nIndexTailCutInVProc = nProc
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 else
ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nIndexRotation = nUnloadPos if #ResultsList > 0 then
ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nFlg = 0 local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo)
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc]) Proc.nIndexRotation = Data.nIndexRotation
SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1 -- 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
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
end end
else else
if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
@@ -1665,7 +1844,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
nPhase = nPhase} nPhase = nPhase}
table.insert( DB_MACH_APPLIED, MachExtraInfo) table.insert( DB_MACH_APPLIED, MachExtraInfo)
else else
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, 0) BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, 0)
end end
-- si sposta il pezzo nella posizione originale, di quando è stata fatta la collect. In questo modo tutti i dati calcolati nella collect restano validi. -- 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. -- Altrimenti bisognava ricalcolare tutto, aumentando tempo di calcolo.
@@ -1823,7 +2002,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition) BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation nCurrPosition = nRotation
EgtSetInfo( idDisp, 'ROT', -2) EgtSetInfo( idDisp, 'ROT', -2)
bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'DOWN') bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'DOWN')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
bProcess = bProcess or bTryToReProcess bProcess = bProcess or bTryToReProcess
end end
@@ -1832,7 +2011,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
if MatrixResult.bSomeFeatureSide then if MatrixResult.bSomeFeatureSide then
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima -- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown then if MatrixResult.bSomeFeatureDown then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0)) BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase() nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase) idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd) EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -1851,14 +2030,14 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition) BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation nCurrPosition = nRotation
EgtSetInfo( idDisp, 'ROT', -1) EgtSetInfo( idDisp, 'ROT', -1)
bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'SIDE') bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'SIDE')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
bProcess = bProcess or bTryToReProcess bProcess = bProcess or bTryToReProcess
end end
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima -- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0)) BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase() nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase) idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd) EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -1877,7 +2056,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1) BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
-- aggiunta lavorazioni in ultima fase -- aggiunta lavorazioni in ultima fase
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD') _, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'STD')
bProcess = bProcess or bTryToReProcess bProcess = bProcess or bTryToReProcess
-- se bisogna riprocessare, si annulla tutto -- se bisogna riprocessare, si annulla tutto
@@ -1917,7 +2096,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
-- ===== finiti i pezzi, si scarica il restante ===== -- ===== finiti i pezzi, si scarica il restante =====
local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw) local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw)
if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then
BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0) BeamLib.AddPhaseWithRawParts( PARTS, #PARTS + 1, BeamData.ptOriXR, BeamData.dPosXR, 0)
local nPhase = EgtGetCurrPhase() local nPhase = EgtGetCurrPhase()
local idDisp = EgtGetPhaseDisposition( nPhase) local idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'TYPE', 'REST') EgtSetInfo( idDisp, 'TYPE', 'REST')
@@ -1962,8 +2141,8 @@ end
function BeamExec.ProcessAlternatives( PARTS) function BeamExec.ProcessAlternatives( PARTS)
-- inizializzazione variabili globali per interfaccia -- inizializzazione variabili globali per interfaccia
BEAM.ALTERNATIVESNEST2D = '' local Alternatives = {}
BEAM.ALTERNATIVES = '' local AlternativesNest2D = {}
-- ciclo sui pezzi -- ciclo sui pezzi
local BestCombination = {} local BestCombination = {}
@@ -2193,7 +2372,7 @@ function BeamExec.ProcessAlternatives( PARTS)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition) BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation nCurrPosition = nRotation
EgtSetInfo( idDisp, 'ROT', -2) EgtSetInfo( idDisp, 'ROT', -2)
bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'DOWN') bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'DOWN')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
bProcess = bProcess or bTryToReProcess bProcess = bProcess or bTryToReProcess
end end
@@ -2202,7 +2381,7 @@ function BeamExec.ProcessAlternatives( PARTS)
if MatrixResult.bSomeFeatureSide then if MatrixResult.bSomeFeatureSide then
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima -- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown then if MatrixResult.bSomeFeatureDown then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0)) BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase() nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase) idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd) EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -2221,14 +2400,14 @@ function BeamExec.ProcessAlternatives( PARTS)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition) BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation nCurrPosition = nRotation
EgtSetInfo( idDisp, 'ROT', -1) EgtSetInfo( idDisp, 'ROT', -1)
bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'SIDE') bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'SIDE')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
bProcess = bProcess or bTryToReProcess bProcess = bProcess or bTryToReProcess
end end
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima -- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0)) BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase() nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase) idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd) EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -2247,7 +2426,7 @@ function BeamExec.ProcessAlternatives( PARTS)
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1) BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
-- aggiunta lavorazioni in ultima fase -- aggiunta lavorazioni in ultima fase
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD') _, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'STD')
bProcess = bProcess or bTryToReProcess bProcess = bProcess or bTryToReProcess
-- se bisogna riprocessare, si annulla tutto -- se bisogna riprocessare, si annulla tutto
@@ -2281,7 +2460,7 @@ function BeamExec.ProcessAlternatives( PARTS)
-- ===== finiti i pezzi, si scarica il restante ===== -- ===== finiti i pezzi, si scarica il restante =====
local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw) local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw)
if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then
BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0) BeamLib.AddPhaseWithRawParts( PARTS, #PARTS + 1, BeamData.ptOriXR, BeamData.dPosXR, 0)
local nPhase = EgtGetCurrPhase() local nPhase = EgtGetCurrPhase()
local idDisp = EgtGetPhaseDisposition( nPhase) local idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'TYPE', 'REST') EgtSetInfo( idDisp, 'TYPE', 'REST')
@@ -2292,23 +2471,14 @@ function BeamExec.ProcessAlternatives( PARTS)
local bApplOk, _, _ = EgtApplyAllMachinings() local bApplOk, _, _ = EgtApplyAllMachinings()
-- se non ci sono errori, soluzione alternativa valida: scrittura variabili globali per interfaccia -- se non ci sono errori, soluzione alternativa valida: scrittura variabili globali per interfaccia
if bApplOk then if bApplOk then
local Alternatives = {}
local sBitIndexCombinationWithInvert = BestCombination.sBitIndexCombination .. EgtIf( BestCombination.bPartInCombiIsInverted, '_INV', '') local sBitIndexCombinationWithInvert = BestCombination.sBitIndexCombination .. EgtIf( BestCombination.bPartInCombiIsInverted, '_INV', '')
if TotalCombiToTest[z].bIsNesting2D then if TotalCombiToTest[z].bIsNesting2D then
if BEAM.ALTERNATIVESNEST2D and BEAM.ALTERNATIVESNEST2D ~= "" then table.insert( AlternativesNest2D, sBitIndexCombinationWithInvert)
table.insert( Alternatives, BEAM.ALTERNATIVESNEST2D)
end
table.insert( Alternatives, sBitIndexCombinationWithInvert)
BEAM.ALTERNATIVESNEST2D = table.concat( Alternatives, ', ')
else else
if BEAM.ALTERNATIVES and BEAM.ALTERNATIVES ~= "" then
table.insert( Alternatives, BEAM.ALTERNATIVES)
end
table.insert( Alternatives, sBitIndexCombinationWithInvert) table.insert( Alternatives, sBitIndexCombinationWithInvert)
BEAM.ALTERNATIVES = table.concat( Alternatives, ', ')
end end
end end
-- se ultima combinazione, si esce e non si riporta in posizione inizale. Verrà infatti cancellata -- se ultima combinazione, si esce e non si riporta in posizione iniziale. Verrà infatti cancellata
if z == #TotalCombiToTest then break end if z == #TotalCombiToTest then break end
-- si riporta pezzo in posizione iniziale -- si riporta pezzo in posizione iniziale
@@ -2322,6 +2492,23 @@ function BeamExec.ProcessAlternatives( PARTS)
end end
-- passaggio info a interfaccia da scrivere sul pezzo
BEAM.INFONGEPART = {}
table.insert( BEAM.INFONGEPART, 'INITIALPOSITION=' .. PARTS[nPart].nInitialPosition)
for i = 1, #AlternativesNest2D do
local sRotation = BeamLib.ConvertBitIndexToRotationIndex( AlternativesNest2D[i])
if PARTS[nPart].HeadcutInfo then
local sOffsetX = table.concat( PARTS[nPart].HeadcutInfo[sRotation].OffsetX, ',')
local sVtN = ( tostring( PARTS[nPart].HeadcutInfo[sRotation].vtN)):gsub("^%(", ""):gsub("%)$", "")
table.insert( BEAM.INFONGEPART, 'ALT' .. AlternativesNest2D[i].. '_H' .. '=' .. sOffsetX .. ';' .. sVtN )
end
if PARTS[nPart].TailcutInfo then
local sOffsetX = table.concat( PARTS[nPart].TailcutInfo[sRotation].OffsetX, ',')
local sVtN = ( tostring( PARTS[nPart].TailcutInfo[sRotation].vtN)):gsub("^%(", ""):gsub("%)$", "")
table.insert( BEAM.INFONGEPART, 'ALT' .. AlternativesNest2D[i] .. '_T' .. '=' .. sOffsetX .. ';' .. sVtN)
end
end
-- si cancella eventuale mach group creato per le alternative -- si cancella eventuale mach group creato per le alternative
EgtRemoveMachGroup( nTempMachGroupName) EgtRemoveMachGroup( nTempMachGroupName)
+157 -14
View File
@@ -161,17 +161,45 @@ function BeamLib.GetPartSplittingPoints( Part)
end end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc) function BeamLib.AddPhaseWithRawParts( PARTS, nPartIndex, OriXR, PosXR, dDeltaSucc)
local nPhase = EgtAddPhase() local nPhase = EgtAddPhase()
local Part
local idRaw
-- se l'indice è oltre significa che è l'ultimo grezzo senza pezzi
if nPartIndex > #PARTS then
idRaw = EgtGetNextRawPart( PARTS[#PARTS].idRaw)
else
Part = PARTS[nPartIndex]
idRaw = Part.idRaw
end
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola -- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000) EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
local dRawMove = 0 local dRawMove = 0
local bIsFirstRaw = true
local dPosXFirst = 0
while idRaw do while idRaw do
local dPosX
for i = 1, #PARTS do
local CurrentPart = PARTS[i]
if CurrentPart.idRaw == idRaw then
dPosX = CurrentPart.dPosX
if bIsFirstRaw then
dPosXFirst = dPosX
end
break
end
if i == #PARTS then
dPosX = PARTS[i].dPosX + PARTS[i].b3Raw:getDimX()
end
end
if bIsFirstRaw then
bIsFirstRaw = false
else
dRawMove = dDeltaSucc + dPosX - dPosXFirst
end
EgtKeepRawPart( idRaw) EgtKeepRawPart( idRaw)
EgtMoveToCornerRawPart( idRaw, OriXR, PosXR) EgtMoveToCornerRawPart( idRaw, OriXR, PosXR)
EgtMoveRawPart( idRaw, Vector3d( - dRawMove, 0, 0)) EgtMoveRawPart( idRaw, Vector3d( - dRawMove, 0, 0))
if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
idRaw = EgtGetNextRawPart( idRaw) idRaw = EgtGetNextRawPart( idRaw)
end end
-- salvo info nuova fase aggiunta -- salvo info nuova fase aggiunta
@@ -395,6 +423,24 @@ function BeamLib.GetAddGroup( PartId)
return AddGrpId, sMchGrp return AddGrpId, sMchGrp
end end
-------------------------------------------------------------------------------------------------------------
-- Funzione prossimo nome MachGroup libero (numero intero)
function BeamLib.GetNewMachGroupName()
local idMachGroup = EgtGetFirstMachGroup()
if not idMachGroup then return 1 end
local nMaxMachGroup = 0
while idMachGroup do
local sMachGroupName = EgtGetMachGroupName( idMachGroup)
local nMachGroupName = tonumber( sMachGroupName)
if nMachGroupName > nMaxMachGroup then
nMaxMachGroup = nMachGroupName
end
idMachGroup = EgtGetNextMachGroup( idMachGroup)
end
return nMaxMachGroup + 1
end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- restituisce le facce della parte interessate dalla feature Proc -- restituisce le facce della parte interessate dalla feature Proc
-- TODO da spostare in FeatureLib??? -- TODO da spostare in FeatureLib???
@@ -512,10 +558,69 @@ function BeamLib.GetDirectionFromSCC( nSCC)
elseif nSCC == MCH_SCC.ADIR_ZM then elseif nSCC == MCH_SCC.ADIR_ZM then
vtSCC = -Z_AX() vtSCC = -Z_AX()
end end
return vtSCC return vtSCC
end end
-------------------------------------------------------------------------------------------------------------
-- Restituisce una tabella con i punti ai vertici della faccia, in globale
-- ordinati partendo da quello ai valori minimi degli assi e i successivi secondo rotazione destrorsa X+;
-- solo per Proc a 1 faccia
function BeamLib.GetSortedVertices( Proc)
local PtVerticesSorted = {}
-- se più di una faccia si esce subito
if Proc.nFct > 1 then
return
end
local PtVertices = {}
local nFirstIndex
local dMinYZ = GEO.INFINITO
for i = 1, #Proc.Faces[1].Edges do
local Edge = Proc.Faces[1].Edges[i]
table.insert( PtVertices, Edge.ptStart)
if ( Edge.ptStart:getY() + Edge.ptStart:getZ() < dMinYZ) then
nFirstIndex = i
dMinYZ = Edge.ptStart:getY() + Edge.ptStart:getZ()
end
end
table.insert( PtVerticesSorted, PtVertices[nFirstIndex])
local nCurrentIndex = nFirstIndex
-- faccia che guarda verso X+, ordine ok
if Proc.Faces[1].vtN:getX() > GEO.EPS_SMALL then
for _ = 1, #PtVertices - 1 do
_, nCurrentIndex = BeamLib.GetAdjacentIndices( nCurrentIndex, #PtVertices)
table.insert( PtVerticesSorted, PtVertices[nCurrentIndex])
end
-- faccia che guarda verso X-, ordine da invertire
else
for _ = 1, #PtVertices - 1 do
nCurrentIndex = BeamLib.GetAdjacentIndices( nCurrentIndex, #PtVertices)
table.insert( PtVerticesSorted, PtVertices[nCurrentIndex])
end
end
return PtVerticesSorted
end
-------------------------------------------------------------------------------------------------------------
-- restituisce il precedente e prossimo indice 1-based, tenendo conto del massimo indice
function BeamLib.GetAdjacentIndices( nCurrentIndex, nMaxIndex)
local nPreviousIndex, nNextIndex
if ( nCurrentIndex < 1) or ( nCurrentIndex > nMaxIndex) then
return
end
-- circular indexing 1-based
nPreviousIndex = ((nCurrentIndex - 2 + nMaxIndex) % nMaxIndex) + 1
nNextIndex = (nCurrentIndex % nMaxIndex) + 1
return nPreviousIndex, nNextIndex
end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce -- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce
function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId) function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
@@ -785,17 +890,18 @@ function BeamLib.BinaryToDecimal( dNumber)
local sNumberToConvert = tostring( dNumber) local sNumberToConvert = tostring( dNumber)
local dResult = 0 local dResult = 0
local k = 0 local k = 0
for i = #sNumberToConvert, 1, -1 do for i = #sNumberToConvert, 1, -1 do
k = k + 1 k = k + 1
local n = string.sub(sNumberToConvert, k, k) local n = string.sub( sNumberToConvert, k, k)
dResult = dResult + n*(2^(i-1)) dResult = dResult + n * ( 2^( i-1))
end end
return dResult return dResult
end end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- TODO si può sostituire con funzione EgtNumToBitString
function BeamLib.DecimalToBinary( dNumber) function BeamLib.DecimalToBinary( dNumber)
local sNumberToConvert = tostring( dNumber) local sNumberToConvert = tostring( dNumber)
local n = sNumberToConvert local n = sNumberToConvert
@@ -803,12 +909,12 @@ function BeamLib.DecimalToBinary( dNumber)
local sResult = "" local sResult = ""
for i = sNumberToConvert, 0, -1 do for i = sNumberToConvert, 0, -1 do
local q = math.modf(n) local q = math.modf( n)
n = n/2 n = n / 2
local b = q%2 local b = q % 2
table.insert(tmp, b) table.insert( tmp, b)
if (q == 1) then if ( q == 1) then
break break
end end
end end
@@ -816,7 +922,7 @@ function BeamLib.DecimalToBinary( dNumber)
for i = #tmp, 1, -1 do for i = #tmp, 1, -1 do
sResult = sResult..tmp[i] sResult = sResult..tmp[i]
end end
return tonumber( sResult) return tonumber( sResult)
end end
@@ -830,6 +936,43 @@ function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
return NumberString return NumberString
end end
-------------------------------------------------------------------------------------------------------------
function BeamLib.ConvertBitIndexToRotationIndex( sBitIndexCombination)
local nRotationIndex
if sBitIndexCombination == '1000' then
return 1
elseif sBitIndexCombination == '0100' then
return 2
elseif sBitIndexCombination == '0010' then
return 3
elseif 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
end
-------------------------------------------------------------------------------------------------------------
-- reindicizza una tabella passata ripartendo dall'indice nStartIndex e mantenendo l'ordine
function BeamLib.RotateTableFromIndex( Table, nStartIndex)
local RotatedTable = {}
for i = 1, #Table do
RotatedTable[#RotatedTable + 1] = Table[((RotatedTable + i - 2) % #Table) + 1]
end
return RotatedTable
end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
--- copia una tabella lua in modo ricorsivo, ossia mantiene indipendenti anche tutte le sottotabelle --- copia una tabella lua in modo ricorsivo, ossia mantiene indipendenti anche tutte le sottotabelle
--- ATTENZIONE: in caso di modifiche vanno gestiti anche i tipi custom; sarebbe meglio metterla nel LuaLibs --- ATTENZIONE: in caso di modifiche vanno gestiti anche i tipi custom; sarebbe meglio metterla nel LuaLibs
+2 -2
View File
@@ -43,7 +43,7 @@ end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra -- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra
local function IsFeatureCuttingEntireSection( b3Proc, Part) function FeatureLib.IsFeatureCuttingEntireSection( b3Proc, Part)
return ( b3Proc:getDimY() > ( Part.b3Part:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( Part.b3Part:getDimZ() - 500 * GEO.EPS_SMALL)) return ( b3Proc:getDimY() > ( Part.b3Part:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( Part.b3Part:getDimZ() - 500 * GEO.EPS_SMALL))
end end
@@ -198,7 +198,7 @@ function FeatureLib.ClassifyTopology( Proc, Part)
if not Proc.AffectedFaces then Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) end if not Proc.AffectedFaces then Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) end
local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.b3Box, Part) local bIsFeatureCuttingEntireSection = FeatureLib.IsFeatureCuttingEntireSection( Proc.b3Box, Part)
local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part) local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part)
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc, Part) local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc, Part)
local vAdj = Proc.AdjacencyMatrix local vAdj = Proc.AdjacencyMatrix
+2 -11
View File
@@ -607,9 +607,6 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
local ToolInfo = {} local ToolInfo = {}
-- parametri obbligatori -- parametri obbligatori
if type( ToolSearchParameters.FaceToMachine) ~= 'table' then
error( 'FindBlade : missing face info')
end
if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then
error( 'FindBlade : missing top head info') error( 'FindBlade : missing top head info')
end end
@@ -675,12 +672,6 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
if not bIsBladeOk then if not bIsBladeOk then
bIsToolCompatible = false bIsToolCompatible = false
end end
-- se si ha solo la faccia si può verificare se questa è orientata correttamente
elseif FaceToMachine then
if MachiningLib.IsFaceZOutOfRange( FaceToMachine.vtN, TOOLS[i]) then
bIsToolCompatible = false
end
end end
end end
@@ -1184,7 +1175,7 @@ end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
-- funzione per aggiungere una nuova lavorazione -- funzione per aggiungere una nuova lavorazione
function MachiningLib.AddOperations( MACHININGS, Part, sRotation) function MachiningLib.AddOperations( MACHININGS, PARTS, Part, sRotation)
local nErr local nErr
local sErr = '' local sErr = ''
local bAreAllMachiningApplyOk = true local bAreAllMachiningApplyOk = true
@@ -1452,7 +1443,7 @@ function MachiningLib.AddOperations( MACHININGS, Part, sRotation)
bSplitExecuted = true bSplitExecuted = true
MACHININGS.Info.bSplitExecuted = true MACHININGS.Info.bSplitExecuted = true
BeamLib.AddPhaseWithRawParts( Part.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET) BeamLib.AddPhaseWithRawParts( PARTS, Part.nIndexInParts, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
-- se grezzo successivo senza pezzi e finale, va tolto -- se grezzo successivo senza pezzi e finale, va tolto
local nNextRawId = EgtGetNextRawPart( Part.idRaw) local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then
+10 -14
View File
@@ -301,16 +301,14 @@ local function MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux)
EgtSetAxisPos( AxesNames[6], dRotative3) EgtSetAxisPos( AxesNames[6], dRotative3)
end end
return dTHome - dLinear1, AxesNames return dLinear1 - dTHome
end end
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength) local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength)
-- spostamento assi macchina in posizione -- spostamento assi macchina in posizione
local dDeltaXBeamOffset = MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux) local dDeltaXHeadOffset = MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux)
-- spostamento trave in posizione macchina (è da riportare in posizione originale prima di return)
EgtMove( Part.idRaw, Vector3d( dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
-- si recuperano gli id delle geometrie dell'asse con cui controllare la collisione -- si recuperano gli id delle geometrie dell'asse con cui controllare la collisione
local idCollisionGroup = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'COLLISION') local idCollisionGroup = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'COLLISION')
@@ -321,14 +319,18 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
local CollisionSurfTmId = {} local CollisionSurfTmId = {}
for i = 1, #CollisionGroupEntitiesId do for i = 1, #CollisionGroupEntitiesId do
if EgtGetType( CollisionGroupEntitiesId[i]) == GDB_TY.SRF_MESH then if EgtGetType( CollisionGroupEntitiesId[i]) == GDB_TY.SRF_MESH then
table.insert( CollisionSurfTmId, CollisionGroupEntitiesId[i]) local idCollisionSurfTmCopy = EgtCopyGlob( CollisionGroupEntitiesId[i], Part.idTempGroup)
EgtMove( idCollisionSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB)
table.insert( CollisionSurfTmId, idCollisionSurfTmCopy)
end end
end end
-- se presenti geometrie nel gruppo other si aggiungono anche quelle -- se presenti geometrie nel gruppo other si aggiungono anche quelle
if CollisionGroupOtherEntitiesId and #CollisionGroupOtherEntitiesId > 0 then if CollisionGroupOtherEntitiesId and #CollisionGroupOtherEntitiesId > 0 then
for i = 1, #CollisionGroupEntitiesId do for i = 1, #CollisionGroupOtherEntitiesId do
if EgtGetType( CollisionGroupEntitiesId[i]) == GDB_TY.SRF_MESH then if EgtGetType( CollisionGroupOtherEntitiesId[i]) == GDB_TY.SRF_MESH then
table.insert( CollisionSurfTmId, CollisionGroupEntitiesId[i]) local idCollisionOtherSurfTmCopy = EgtCopyGlob( CollisionGroupOtherEntitiesId[i], Part.idTempGroup)
EgtMove( idCollisionOtherSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB)
table.insert( CollisionSurfTmId, idCollisionOtherSurfTmCopy)
end end
end end
end end
@@ -357,8 +359,6 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
-- se trovata collisione con pezzo è inutile procedere con il grezzo -- se trovata collisione con pezzo è inutile procedere con il grezzo
if bCollisionFoundPiece then if bCollisionFoundPiece then
-- si riporta la trave in posizione originale
EgtMove( Part.idRaw, Vector3d( -dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
return true return true
end end
@@ -368,7 +368,6 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
local bCollisionFoundRestLength = false local bCollisionFoundRestLength = false
if not ( bCollisionFoundPiece or bCannotSplitRestLength) then if not ( bCollisionFoundPiece or bCannotSplitRestLength) then
local idRestLengthSurfFr = GetRestlengthSurfTm( Part, sRestLengthSideForPreSimulation) local idRestLengthSurfFr = GetRestlengthSurfTm( Part, sRestLengthSideForPreSimulation)
EgtMove( idRestLengthSurfFr, Vector3d( dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
if idRestLengthSurfFr then if idRestLengthSurfFr then
for i = 1, #CollisionSurfTmId do for i = 1, #CollisionSurfTmId do
bCollisionFoundRestLength = EgtCDeSolidSolid( idRestLengthSurfFr, CollisionSurfTmId[i], BeamData.COLL_SIC) bCollisionFoundRestLength = EgtCDeSolidSolid( idRestLengthSurfFr, CollisionSurfTmId[i], BeamData.COLL_SIC)
@@ -385,9 +384,6 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
end end
end end
-- si riporta la trave in posizione originale
EgtMove( Part.idRaw, Vector3d( -dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
return false, bCollisionFoundRestLength return false, bCollisionFoundRestLength
end end
+623 -404
View File
File diff suppressed because it is too large Load Diff
+477
View File
@@ -0,0 +1,477 @@
-- BeamNestProcess.lua by Egaltech s.r.l. 2023/01/15
-- Gestione nesting automatico travi
-- 2022/10/05 Piccole modifiche per far funzionare correttamente i compilati.
-- 2022/10/06 Corretto bug che moltiplicava i pezzi se erano presenti più grezzi della stessa sezione.
-- 2023/01/15 Piccole correzioni.
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- Per test
--NEST = {}
--NEST.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
--NEST.MACHINE = 'Essetre-90480019_MW'
--NEST.FLAG = 3
local sLog = ' +++ BeamNestProcess : ' .. NEST.FILE .. ', ' .. NEST.MACHINE .. ', ' .. LEN[1]
EgtOutLog( sLog)
-- flag per abilitare statistiche in log
local bLogStat = false
-- Cancello file di log specifico
local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt')
EgtEraseFile( sLogFile)
-- Funzioni per scrittura su file di log specifico
local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
hFile:close()
end
local function WriteTimeToLogFile( dTime)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
hFile:close()
end
-- Funzione per gestire visualizzazione dopo errore
local function PostErrView( nErr, sMsg)
if nErr ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
end
end
-- Funzione per gestire visualizzazione dopo warning
local function PostWarnView( nWarn, sMsg)
if nWarn ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
end
end
-- Funzione per aggiornare dati ausiliari
local function UpdateAuxData( sAuxFile)
local bModif = false
-- Se definito LOAD90, aggiorno
local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
if sLoad90 ~= '' then
local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
bModif = true
end
return bModif
end
local function PartsToFill( Parts)
local nToFill = 0
for i = 1, #Parts do
if Parts[i].Cnt > 0 then
nToFill = nToFill + Parts[i].Cnt
end
end
return nToFill
end
local function ExecMaximumFilling( Raw, Parts)
-- Inizializzo maximum filler
EgtMaxFillerStart()
-- Inserisco i pezzi
for i = 1, #Parts do
EgtMaxFillerAddPart( i, Parts[i].Len, Parts[i].DispLen or Parts[i].Len, Parts[i].Cnt or 1)
end
-- Eseguo l'ottimizzazione
EgtMaxFillerCompute( Raw.LenToFill, Raw.StartGap, Raw.MidGap, Raw.EndGap, Raw.SortType)
-- Recupero i risultati
local nFilledParts, nDiffParts, dTotFillRatio = EgtMaxFillerGetResults()
local OneRes = {}
for i = 0, nDiffParts - 1 do
local nPartId, nCount = EgtMaxFillerGetOneResult( i)
table.insert( OneRes, { Id=nPartId, Count=nCount})
end
--return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Time=dTime, Data=OneRes}
return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Data=OneRes}
end
-- Funzione per trovare nome MachGroup
local function NewMachGroupName()
local nMachGroupId = EgtGetFirstMachGroup()
if not nMachGroupId then return 1 end
local nMaxMachGroup = 0
while nMachGroupId do
sMachGroupName = EgtGetMachGroupName(nMachGroupId)
local nMachGroupName = tonumber(sMachGroupName)
if nMachGroupName > nMaxMachGroup then
nMaxMachGroup = nMachGroupName
end
nMachGroupId = EgtGetNextMachGroup(nMachGroupId)
end
return nMaxMachGroup + 1
end
local function TotRawCount(Raws)
local nTotRaws = 0
for RawIndex = 1, #Raws do
nTotRaws = nTotRaws + Raws[RawIndex].Count
end
return nTotRaws
end
local function TotPartLen(Parts)
local nTotPartLen = 0
for PartIndex = 1, #Parts do
nTotPartLen = nTotPartLen + ( Parts[PartIndex].Len * Parts[PartIndex].Cnt)
end
return nTotPartLen
end
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( NEST.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto la macchina corrente e verifico sia abilitata per la lavorazione delle Travi
EgtSetCurrMachine( NEST.MACHINE)
local sMachDir = EgtGetCurrMachineDir()
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
NEST.ERR = 12
NEST.MSG = 'Error not configured for beam machine : ' .. sMachine
WriteErrToLogFile( NEST.ERR, NEST.MSG)
PostErrView( NEST.ERR, NEST.MSG)
return
end
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Inizializzo contatori errori e avvisi
local nErrCnt = 0
local nWarnCnt = 0
-- Grezzi
local Raws = {}
-- creo tabella dei grezzi
for nIndex, nLen in pairs( LEN) do
Raws[tonumber(nIndex)] = {LenToFill = nLen, StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1}
end
for nIndex, nQty in pairs( QTY) do
Raws[tonumber(nIndex)].Count = nQty
end
-- cerco il grezzo con la lunghezza maggiore, epurata dello start gap
local maxRawLenToFillNoStartGap = 0
for RawIndex = 1, #Raws do
if Raws[RawIndex].Count > 0 then
maxRawLenToFillNoStartGap = max( maxRawLenToFillNoStartGap, Raws[RawIndex].LenToFill - Raws[RawIndex].StartGap)
end
end
-- Pezzi
local Parts = {}
-- ciclo su pezzi per aggiungerli al nesting
local dTotLen = 0
for nPartId, nCount in pairs( PART) do
-- recupero lunghezza pezzo
local Len = EgtGetInfo( nPartId, "L", 'd')
local DispLen = EgtIf( Len <= 1000, 2000, 0) --EgtIf( Len <= 2000, max( 2000, 6000 - Len), 0)
-- aggiungo il pezzo solo se ci sta nel grezzo più lungo a disposizione
if Len < maxRawLenToFillNoStartGap then
for nCntIndex = 1 , nCount do
table.insert( Parts, {Id = nPartId, Len = Len, DispLen = DispLen, Cnt = 1})
dTotLen = dTotLen + Len
end
end
end
-- lunghezza totale pezzi
local dTotPartLen = TotPartLen( Parts)
-- calcolo media delle barre necessarie
local NeededRawsForType = {}
for RawIndex = 1, #Raws do
NeededRawsForType[RawIndex] = min( ceil( dTotPartLen / Raws[RawIndex].LenToFill), Raws[RawIndex].Count)
end
local RawQtySum = 0
for NeededRawIndex = 1, #NeededRawsForType do
RawQtySum = RawQtySum + NeededRawsForType[NeededRawIndex]
end
local MediumRawQty = ceil( RawQtySum / #NeededRawsForType)
if MediumRawQty > 1 then
MediumRawQty = MediumRawQty - 1
end
-- lista dei risultati
local ResultList = {}
local BestResult = nil
local BestResultIndex = nil
-- riordino lista pezzi per lunghezza
table.sort( Parts, function( B1, B2) return B1.Len < B2.Len end)
local function NestSolutionByIndex( Index)
-- creo copia lista raw
local TempRaws = {}
for TempRawIndex = 1, #Raws do
table.insert(TempRaws, {LenToFill = Raws[TempRawIndex].LenToFill, StartGap = Raws[TempRawIndex].StartGap, MidGap = Raws[TempRawIndex].MidGap, EndGap = Raws[TempRawIndex].EndGap, SortType = Raws[TempRawIndex].SortType, Count = Raws[TempRawIndex].Count})
end
-- recupero pezzi corti
local ShortList = {}
local LongList = {}
for PartIndex = 1, #Parts do
if PartIndex <= Index then
table.insert( ShortList, Parts[PartIndex])
else
table.insert( LongList, Parts[PartIndex])
end
Parts[PartIndex].Cnt = 1
end
-- numero di pezzi piccoli per barra
local ShortCount = Index
local ShortForRaw = floor( ShortCount / MediumRawQty)
local ExtraShortForRaw = 0
if MediumRawQty > 0 then
ExtraShortForRaw = fmod( ShortCount, MediumRawQty)
end
-- creo lista pezzi corti singoli
local SingleShortList = {}
for ShortIndex = 1, #ShortList do
for ShortCount = 1, ShortList[ShortIndex].Cnt do
table.insert( SingleShortList, {Id = ShortList[ShortIndex].Id, Len = ShortList[ShortIndex].Len, DispLen = ShortList[ShortIndex].DispLen, Cnt = 1})
end
end
-- li divido per le barre previste
local RawsShortList = {}
local RawIndex = 0
local ShortRawIndex = 0
for ShortIndex = 1, #SingleShortList do
if ShortRawIndex > 0 then
table.insert( RawsShortList[RawIndex], SingleShortList[ShortIndex])
ShortRawIndex = ShortRawIndex - 1
else
table.insert( RawsShortList, {SingleShortList[ShortIndex]})
RawIndex = RawIndex + 1
ShortRawIndex = ShortForRaw + EgtIf( RawIndex <= ExtraShortForRaw, 1, 0) - 1
end
end
-- Ciclo fino ad esaurimento pezzi o barre
local dTotPartInRawLen = 0
local nRawTot = 0
local dRawTotLen = 0
local dTime = 0
local nCycle = 1
local CurrResult = {}
while TotRawCount( TempRaws) > 0 and PartsToFill( Parts) > 0 do
-- creo lista con pezzi lunghi e pezzi corti di questo Cycle
local PartsToNest = {}
for PartIndex = 1, #LongList do
table.insert( PartsToNest, LongList[PartIndex])
end
for CycleIndex = 1, #RawsShortList do
if CycleIndex <= nCycle then
for PartIndex = 1, #RawsShortList[CycleIndex] do
table.insert( PartsToNest, RawsShortList[CycleIndex][PartIndex])
end
end
end
-- se non ci sono pezzi da nestare, esco
if PartsToFill( PartsToNest) <= 0 then
break
end
-- Eseguo ottimizzazione per ogni lunghezza di barra
local Results = {}
for RawIndex = 1, #TempRaws do
if TempRaws[RawIndex].Count > 0 then
Results[RawIndex] = ExecMaximumFilling( TempRaws[RawIndex], PartsToNest)
else
Results[RawIndex] = { FillRatio = 0.001, LenToFill = 1000, DiffParts = 0}
end
end
-- verifico quale e' quella con meno scarto
local nMinWasteRawIndex = GDB_ID.NULL
local dMinWaste = 100000
for ResultIndex = 1, #Results do
if Results[ResultIndex] then
local dWaste = (1 - Results[ResultIndex].FillRatio) * TempRaws[ResultIndex].LenToFill
if Results[ResultIndex].DiffParts > 0 and dWaste < dMinWaste then
dMinWaste = dWaste
nMinWasteRawIndex = ResultIndex
end
end
end
-- verifico se ci sono pezzi
if nMinWasteRawIndex > 0 and Results[nMinWasteRawIndex] and Results[nMinWasteRawIndex].DiffParts > 0 then
-- riporto barra e pezzi nel risultato corrente
local CurrBar = { BarLen = TempRaws[nMinWasteRawIndex].LenToFill, Parts = {}}
local CurrX = TempRaws[nMinWasteRawIndex].StartGap
local nInfoIndex = 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartIndex = Results[nMinWasteRawIndex].Data[i].Id
local PartId = PartsToNest[PartIndex].Id
local dLen = PartsToNest[PartIndex].Len
for j = 1, Results[nMinWasteRawIndex].Data[i].Count do
-- creo pezzo copia
CurrPart = { Index = nInfoIndex, PartId = PartId, PosX = CurrX}
table.insert( CurrBar.Parts, CurrPart)
CurrX = CurrX + dLen + TempRaws[nMinWasteRawIndex].MidGap
nInfoIndex = nInfoIndex + 1
end
end
table.insert( CurrResult, CurrBar)
dTotPartInRawLen = dTotPartInRawLen + ( Results[nMinWasteRawIndex].FillRatio * TempRaws[nMinWasteRawIndex].LenToFill)
nRawTot = nRawTot + 1
dRawTotLen = dRawTotLen + TempRaws[nMinWasteRawIndex].LenToFill
-- Aggiorno per prossima iterazione
TempRaws[nMinWasteRawIndex].Count = TempRaws[nMinWasteRawIndex].Count - 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartId = Results[nMinWasteRawIndex].Data[i].Id
PartsToNest[PartId].Cnt = PartsToNest[PartId].Cnt - Results[nMinWasteRawIndex].Data[i].Count
end
else
-- se non sono riuscito ad inserire alcun pezzo esco dal ciclo perche' non ci sono pezzi inseribili
break
end
nCycle = nCycle + 1
end
-- riporto risultato in lista
ResultList[Index] = dTotPartInRawLen
if not BestResult or not BestResultIndex or
( dTotPartInRawLen > ResultList[BestResultIndex] + 0.02 or ( abs( dTotPartInRawLen - ResultList[BestResultIndex]) < 0.02 and dRawTotLen < BestResult.RawTotLen - 0.02)) then
BestResult = CurrResult
BestResult.RawTotLen = dRawTotLen
BestResultIndex = Index
end
end
local CycleCount = 0
local MinTime = 10 + pow( 3, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MinTime: ' .. MinTime ) end
local MaxTime = 30 + pow( 7, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MaxTime: ' .. MaxTime ) end
local TargetRatio = 0.98
local dTargetRatioLen = TargetRatio * dTotLen
if bLogStat then EgtOutLog('TargetRatioLen: ' .. dTargetRatioLen ) end
local CurrTime = 0
local function NestSolutionFromSP( StartingPoint, OscillationStep)
-- ciclo sulle possibilita' da un punto di origine con uno step fisso
local CurrResultIndex = StartingPoint
NestSolutionByIndex( StartingPoint)
if OscillationStep == 0 then return end
local CycleIndex = 1
local nOutOfBoundary = 0
while nOutOfBoundary ~= 3 do
CurrTime = EgtStopCounter() / 1000
if bLogStat then EgtOutLog('CurrTime: ' .. CurrTime ) end
if bLogStat then EgtOutLog('BestRatio: ' .. dTotLen / BestResult.RawTotLen ) end
-- se e' passato il tempo massimo, o e' passato il tempo minimo, ha inserito tutti i pezzi e la percentuale di utilizzo del materiale e' maggiore della soglia
if CurrTime > MaxTime or ( CurrTime > MinTime and ResultList[BestResultIndex] > dTotLen - 0.1 and ( dTotLen / BestResult.RawTotLen ) >= TargetRatio) then
if bLogStat then EgtOutLog('Brake') end
break
end
local bCurrOutOfBoundary = false
if CurrResultIndex < 0 then
bCurrOutOfBoundary = true
if nOutOfBoundary == 2 then
nOutOfBoundary = 3
else
nOutOfBoundary = 1
end
end
if CurrResultIndex > #Parts then
bCurrOutOfBoundary = true
if nOutOfBoundary == 1 then
nOutOfBoundary = 3
else
nOutOfBoundary = 2
end
end
if not bCurrOutOfBoundary and not ResultList[CurrResultIndex] then
NestSolutionByIndex( CurrResultIndex)
if bLogStat then EgtOutLog('CurrResultIndex: ' .. CurrResultIndex ) end
if bLogStat then EgtOutLog('Result: ' .. ResultList[CurrResultIndex]) end
CycleCount = CycleCount + 1
end
CurrResultIndex = StartingPoint + EgtIf( CycleIndex % 2 == 0, (CycleIndex / 2) * OscillationStep, -( ( CycleIndex + 1) / 2) * OscillationStep )
CycleIndex = CycleIndex + 1
end
end
-- lancio calcolo
EgtStartCounter()
local StartingResult = floor( #Parts * 0.3)
if bLogStat then EgtOutLog('StartingResult: ' .. StartingResult ) end
--local Step = floor( #Parts / 10) * floor( log10( #Parts))
local nDividendo = pow( 10, floor( log10( #Parts)) - 1)
nDividendo = EgtIf( nDividendo ~= 1, nDividendo, 10)
local Step = floor( #Parts / nDividendo) * floor( log10( #Parts))
if bLogStat then EgtOutLog('Step: ' .. Step ) end
NestSolutionFromSP( StartingResult, Step)
if Step > 1 then
NestSolutionFromSP( StartingResult, 1)
end
-- creo gruppi di lavorazione per risultato
for MachGroupIndex = 1, #BestResult do
local CurrMachGroup = BestResult[ MachGroupIndex]
-- creo gruppo di lavorazione
local MachGroupName = NewMachGroupName()
nMachGroup = EgtAddMachGroup( MachGroupName)
EgtSetInfo( nMachGroup, "BARLEN", CurrMachGroup.BarLen)
EgtSetInfo( nMachGroup, "MATERIAL", NEST.MATERIAL)
EgtSetInfo( nMachGroup, "AUTONEST", 1)
-- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
-- Disegno i pezzi
for i = 1, #CurrMachGroup.Parts do
local CurrPart = CurrMachGroup.Parts[ i]
-- creo pezzo copia
local nPartDuploId = EgtDuploNew( CurrPart.PartId)
EgtSetInfo( nMachGroup, "PART" .. CurrPart.Index, nPartDuploId .. "," .. CurrPart.PosX)
end
end
-- creo grezzi per ogni gruppo di lavorazione
local nRawCnt = 0
local nRawTot = ResultList[BestResultIndex]
_G.BEAM = {}
BEAM.FILE = NEST.FILE
BEAM.MACHINE = NEST.MACHINE
BEAM.FLAG = 6 -- CREATE_PANEL
BEAM.BASEDIR = NEST.BASEDIR
nMachGroup = EgtGetFirstMachGroup()
while nMachGroup do
local nNextMachGroup = EgtGetNextMachGroup( nMachGroup)
EgtSetCurrMachGroup( nMachGroup)
if EgtGetInfo( nMachGroup, "AUTONEST",'i') == 1 then
EgtRemoveInfo( nMachGroup, "AUTONEST")
EgtSetInfo( nMachGroup, "UPDATEUI", 1)
local bOk, sErr = pcall( dofile, BEAM.BASEDIR .. "\\BatchProcessNew.lua")
if not bOk then
EgtOutLog( 'Error in BatchProcessNew.lua call (' .. ( sErr or '') ..')')
end
nRawCnt = nRawCnt + 1
-- aggiorno interfaccia
EgtProcessEvents( 200 + ( nRawCnt / nRawTot * 100), 0)
end
nMachGroup = nNextMachGroup
end
EgtResetCurrMachGroup()
NEST.ERR = 0
EgtOutLog( ' +++ BeamNestProcess completed')
+1
View File
@@ -215,6 +215,7 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
end end
-- se la lavorazione ostacola il pinzaggio, non posso farla, serve una lavorazioen che lasci il testimone -- se la lavorazione ostacola il pinzaggio, non posso farla, serve una lavorazioen che lasci il testimone
-- TODO Girando il pezzo trova sempre che limitano il pinzaggio se pezzo piccolo!! Il controllo non va bene. Da rifare
if MachiningLib.IsFeatureHinderingClamping( Proc, Part) then if MachiningLib.IsFeatureHinderingClamping( Proc, Part) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable ( Feature hinders clamping)' local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable ( Feature hinders clamping)'
EgtOutLog( sErr) EgtOutLog( sErr)
+15 -1
View File
@@ -24,6 +24,8 @@ local function GetSCC( Machining)
if TOOLS[Machining.nToolIndex].SetupInfo.bToolOnAggregate then if TOOLS[Machining.nToolIndex].SetupInfo.bToolOnAggregate then
nSCC = MCH_SCC.ADIR_NEAR nSCC = MCH_SCC.ADIR_NEAR
elseif TOOLS[Machining.nToolIndex].SetupInfo.nBlockedSCC then
nSCC = TOOLS[Machining.nToolIndex].SetupInfo.nBlockedSCC
elseif Machining.vtToolDirection:getY() <= 0 then elseif Machining.vtToolDirection:getY() <= 0 then
nSCC = MCH_SCC.ADIR_YM nSCC = MCH_SCC.ADIR_YM
else else
@@ -96,7 +98,7 @@ function STR0014.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Machining.nSCC = GetSCC( Strategy.Machining) Strategy.Machining.nSCC = GetSCC( Strategy.Machining)
Strategy.Machining.nType = MCH_MY.MILLING Strategy.Machining.nType = MCH_MY.MILLING
Strategy.Machining.sDepth = EgtClamp( Strategy.Parameters.dMachiningDepth, -1, 5) Strategy.Machining.sDepth = EgtClamp( Strategy.Parameters.dMachiningDepth, -1, TOOLS[Strategy.Machining.nToolIndex].dMaxMaterial)
Strategy.Machining.nWorkside = MCH_MILL_WS.CENTER Strategy.Machining.nWorkside = MCH_MILL_WS.CENTER
-- LeadIn / LeadOut -- LeadIn / LeadOut
@@ -104,7 +106,19 @@ function STR0014.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Machining.LeadOut = {} Strategy.Machining.LeadOut = {}
Strategy.Machining.LeadIn.nType = MCH_MILL_LI.NONE Strategy.Machining.LeadIn.nType = MCH_MILL_LI.NONE
Strategy.Machining.LeadOut.nType = MCH_MILL_LI.NONE Strategy.Machining.LeadOut.nType = MCH_MILL_LI.NONE
-- se è una penna, si limita la lavorazione per evitare di partire fuori dal grezzo
if ToolSearchParameters.sMillShape == 'PEN' then
Strategy.Machining.LeadIn.dStartAddLength = -20
Strategy.Machining.LeadOut.dEndAddLength = -20
end
-- TODO gestire meglio
-- se utensile montato su aggregato flottante
if TOOLS[Strategy.Machining.nToolIndex].bToolOnFloatingTH then
Strategy.Machining.dMaxElev = Strategy.Parameters.dMachiningDepth
Strategy.Machining.dLongitudinalOffset = -5
end
-- stessi parametri cambia solo al geometria -- stessi parametri cambia solo al geometria
for i = 1, #Proc.FeatureInfo.AdditionalGeometries do for i = 1, #Proc.FeatureInfo.AdditionalGeometries do
local AuxId = Proc.id + Proc.FeatureInfo.AdditionalGeometries[i] local AuxId = Proc.id + Proc.FeatureInfo.AdditionalGeometries[i]
+1 -1
View File
@@ -977,7 +977,7 @@ local function CutWithDicing( Proc, Part, OptionalParameters)
-- scelta lama da sopra o da sotto -- scelta lama da sopra o da sotto
local sChosenBladeType = '' local sChosenBladeType = ''
if not nToolIndex then if not nToolIndex then
nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Face1) nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part)
end end
-- se non trovata lama la lavorazione non è fattibile -- se non trovata lama la lavorazione non è fattibile
+3
View File
@@ -232,6 +232,9 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Tool = TOOLS[Cutting.nToolIndex], Tool = TOOLS[Cutting.nToolIndex],
dDepthToMachine = dDepthToMachine dDepthToMachine = dDepthToMachine
} }
if OppositeToolDirectionMode == 'Enabled' then
BladeEngagementParameters.Edge = EdgeToMachineOpposite
end
local BladeEngagementOptionalParameters = { local BladeEngagementOptionalParameters = {
bIsDicing = bIsDicing, bIsDicing = bIsDicing,
sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation, sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation,