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
-- 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
dBarLen = dBarLen + 1800
end
+401 -214
View File
@@ -153,6 +153,11 @@ function BeamExec.GetToolsFromDB()
Tool.nDouble = EgtGetValInNotes( Tool.sUserNotes, 'DOUBLE', 'd')
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)
if sToolFamily ~= 'DRILLBIT' then
Tool.dThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK)
@@ -251,6 +256,27 @@ function BeamExec.GetStrategiesFromJSONinBD( sAISetupConfigName)
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?
-------------------------------------------------------------------------------------------------------------
-- funzione che controlla validità delle combinazioni proposte
@@ -356,188 +382,179 @@ function BeamExec.GetAvailableCombinations( PartInfo, bIsFlipRot)
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)
-- gruppo per geometrie temporanee
local idTempGroup = BeamLib.GetTempGroup()
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bIsFlipRot )
-- 1. Inizializzazione e Default
local idTempGroup = BeamLib.GetTempGroup( )
-- default per nuove costanti qualora non definite
BeamData.OVM_BLADE_HBEAM = ( BeamData.OVM_BLADE_HBEAM or 11)
BeamData.OVM_CHAIN_HBEAM = ( BeamData.OVM_CHAIN_HBEAM or 8)
BeamData.OVM_BLADE_HBEAM = ( BeamData.OVM_BLADE_HBEAM or 11 )
BeamData.OVM_CHAIN_HBEAM = ( BeamData.OVM_CHAIN_HBEAM or 8 )
-- sovramateriale intermedio nullo se non definito
dOvmMid = ( dOvmMid or 0)
dOvmMid = ( dOvmMid or 5.4 )
dOvmHead = ( dOvmHead or 0 )
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH )
-- Determinazione minimo grezzo scaricabile
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH)
-- Creazione nuovo gruppo di lavoro (di default va creato)
if bCreateMachGroup == nil then
bCreateMachGroup = true
end
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
-- 2. Gestione Gruppo di Lavoro
if ( bCreateMachGroup == nil ) then bCreateMachGroup = true end
if ( bCreateMachGroup ) then
local sMgName = EgtGetMachGroupNewName( 'Mach_1' )
local idNewMg = EgtAddMachGroup( sMgName )
if ( not idNewMg ) then
return false, 'Errore creazione gruppo di lavoro'
end
end
-- Impostazione della tavola
EgtSetTable( 'Tab')
-- salvo nota con lunghezza grezzo
-- Recupero l'identificativo del gruppo di lavoro corrente
local nMGrpId = EgtGetCurrMachGroup()
-- Lunghezza della barra
local dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd')
if not dBarLen then
EgtSetInfo( nMGrpId, 'BARLEN', dRawL)
-- 3. Configurazione Tavola Macchina
EgtSetTable( 'Tab' )
local nMGrpId = EgtGetCurrMachGroup( )
if ( not EgtGetInfo( nMGrpId, 'BARLEN', 'd' ) ) then
EgtSetInfo( nMGrpId, 'BARLEN', dRawL )
end
-- Area tavola
local b3Tab = EgtGetTableArea()
-- 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.dPosXR = EgtIf( BeamData.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR)
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( ) ) )
BeamData.ptOriXR = Point3d( b3Tab:getDimX( ), dPosY, 0 )
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 dLen = dRawL
local idPrevRaw, dPrevDelta
local dDeltaS = dOvmHead
local dDeltaSMin = 0
local dDeltaE = BeamData.OVM_MID
local dMaxX = 0
local idPrevRaw = nil
local dNextStartOffset = dOvmHead -- Il primo pezzo applica il sormonto iniziale a destra (testa)
for i = 1, #PARTS do
-- dati del pezzo
local b3BoxExact = EgtGetBBoxGlob( PARTS[i].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)
-- 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)
local CurrentPart = PARTS[i]
local b3BoxExact = EgtGetBBoxGlob( CurrentPart.id or GDB_ID.NULL, GDB_BB.EXACT )
if ( b3BoxExact:isEmpty( ) or CurrentPart.b3PartOriginal:isEmpty( ) ) then break end
EgtMoveToCornerRawPart( PARTS[i].idRaw, BeamData.ptOriXR, BeamData.dPosXR)
EgtMoveRawPart( PARTS[i].idRaw, Vector3d( dLen - dRawL, 0, 0))
-- assegno ordine in lavorazione
local dPartLen = CurrentPart.b3PartOriginal:getDimX( )
local dPartWidth = CurrentPart.b3PartOriginal:getDimY( )
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
EgtSetInfo( PARTS[i].idRaw, 'ORD', nCnt)
-- creo o pulisco gruppo geometrie aggiuntive
if not BeamLib.CreateOrEmptyAddGroup( PARTS[i].id) then
local sOut = 'Error creating Additional Group in Part ' .. tostring( PARTS[i].id)
return false, sOut
EgtSetInfo( CurrentPart.idRaw, 'ORD', nCnt )
if ( not BeamLib.CreateOrEmptyAddGroup( CurrentPart.id ) ) then
return false, 'Error creating Additional Group in Part ' .. tostring( CurrentPart.id )
end
-- aggiungo faccia per taglio iniziale al pezzo
BeamLib.AddPartStartFace( PARTS[i].id, PARTS[i].b3PartOriginal)
-- se sovramateriale di testa, lo notifico
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
BeamLib.AddPartStartFace( CurrentPart.id, CurrentPart.b3PartOriginal )
BeamLib.AddPartEndFace( CurrentPart.id, CurrentPart.b3PartOriginal )
PARTS[i].sAISetupConfig = EgtGetInfo( PARTS[i].id, 'AISETUP', 's') or
( GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo] and GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo].sAISetupConfig) or -- i parametri BTL potrebbero non esistere
GENERAL_PARAMETERS.PROJECT.sAISetupConfig or nil
-- Inserimento con dDelta (lascia lo spazio vuoto a sinistra e spinge il pezzo a destra)
EgtDeselectPartObjs( CurrentPart.id )
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
TIMER:startElapsed('Json')
BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig)
PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON)
TIMER:stopElapsed('Json')
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bIsFlipRot)
PARTS[i].idTempGroup = idTempGroup
-- Rotazione sezione se necessaria
if ( abs( dPartWidth - dRawW ) > 100 * GEO.EPS_SMALL ) then
EgtRotatePartInRawPart( CurrentPart.id, X_AX( ), 90 )
local vtEccOri = CurrentPart.b3PartOriginal:getCenter( ) - b3BoxExact:getCenter( )
local vtEccRot = Vector3d( vtEccOri )
vtEccRot:rotate( X_AX( ), 90 )
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
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
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
-- Se rimasto materiale aggiungo grezzo dell'avanzo
-- TODO valutare se ridurre la dLen minima perchè crea discrepanze tra lunghezza inserita e VMill
if dLen > 10 then
local idRaw = EgtAddRawPart( Point3d(0,0,0), dLen, dRawW, dRawH, BeamData.RAWCOL)
EgtMoveToCornerRawPart( idRaw, BeamData.ptOriXR, BeamData.dPosXR)
EgtMoveRawPart( idRaw, Vector3d( dLen - dRawL, 0, 0))
-- assegno ordine in lavorazione
-- 8. Chiusura Barra e Gestione Avanzo (Rest Material)
if ( idPrevRaw ) then EgtSetInfo( idPrevRaw, 'BDST', 10000 ) end
local dRemaining = dRawL - dMaxX
if ( dRemaining > 10 ) then
local idRawRest = EgtAddRawPart( Point3d( 0, 0, 0 ), dRemaining, dRawW, dRawH, BeamData.RAWCOL )
EgtMoveToCornerRawPart( idRawRest, BeamData.ptOriXR, BeamData.dPosXR )
EgtMoveRawPart( idRawRest, Vector3d( -dMaxX, 0, 0 ) )
nCnt = nCnt + 1
EgtSetInfo( idRaw, 'ORD', nCnt)
-- aggiorno distanza dell'ultimo pezzo dall'eventuale grezzo scaricabile
if EgtGetRawPartBBox( idRaw):getDimX() < BeamData.dMinRaw then
EgtSetInfo( idRawRest, 'ORD', nCnt )
if ( EgtGetRawPartBBox( idRawRest ):getDimX( ) < BeamData.dMinRaw ) then
PARTS[#PARTS].dDistanceToNextPiece = 10000
end
else
PARTS[#PARTS].dDistanceToNextPiece = 10000
if ( #PARTS > 0 ) then PARTS[#PARTS].dDistanceToNextPiece = 10000 end
end
return true
@@ -781,9 +798,24 @@ end
-------------------------------------------------------------------------------------------------------------
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
for i = 1, #vProcSingleRot do
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
if Proc.nFlg ~= 0 then
-- controllo la feature con tutte le altre per recuperare le dipendenze
@@ -791,6 +823,86 @@ local function GetFeatureInfoAndDependency( vProcSingleRot, Part)
local ProcB = vProcSingleRot[j]
-- non si controlla la feature con se stessa o se feature disabilitata
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)
if ( ID.IsHeadCut( Proc) and not EgtGetInfo( Proc.id, 'HEAD_ADD_CUT', 'i')) and ID.IsHeadCut( ProcB) then
if not Proc.SlaveProcIndexes then
@@ -828,7 +940,43 @@ local function GetFeatureInfoAndDependency( vProcSingleRot, Part)
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
-------------------------------------------------------------------------------------------------------------
@@ -983,6 +1131,9 @@ local function CalculateStrategies( vProcSingleRot, Part)
Proc.AvailableStrategies[nIndexCurrentStrategy].Result.dTimeToMachine = 99
end
if not Proc.AvailableStrategies.dAllStrategiesTotalTime then
Proc.AvailableStrategies.dAllStrategiesTotalTime = 0
end
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
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 StrategyScript = require( StrategyScriptName)
-- 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
else
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
local bCalcInverted = bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion
local nCycles = EgtIf( bCalcInverted, 2, 1)
PARTS[nPart].HeadcutInfo = {}
PARTS[nPart].TailcutInfo = {}
-- per ogni inversione
for nInvertIndex = 1, nCycles do
-- per ogni rotazione
for nRotIndex = 1, 4 do
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 HeadcutInfo, TailcutInfo
-- si calcolano le feature solo se la rotazione può essere presa in considerazione
if PARTS[nPart].CombinationList.Rotations[nRotIndex] == 1 then
-- 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
-- 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
-- inserisco una tabella vuota
table.insert( vProcRot, {})
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
BeamLib.RotateRawPart( PARTS[nPart], 1)
-- aggiorno info pezzo
@@ -1491,13 +1662,15 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bRePro
for nProc = 1, #ProcessingsOnPart.Rotation[1] do
-- Si controlla sempre la rotazione 1 perchè la dipendenza di una feature da un'altra non dipende dalla rotazione
-- se feature disattivata perchè eseguita da master a lei associata dichiaro comunque eseguita
if ProcessingsOnPart.Rotation[1][nProc].nFlg == 0 and ProcessingsOnPart.Rotation[1][nProc].nIndexMasterProc then
ProcessingsOnPart.Rotation[1][nProc].nIndexRotation = nUnloadPos
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[1][nProc])
local ProcOnFirstRotation = ProcessingsOnPart.Rotation[1][nProc]
if ProcOnFirstRotation.nFlg == 0 and ProcOnFirstRotation.nIndexMasterProc then
ProcOnFirstRotation.nIndexRotation = nUnloadPos
table.insert( SingleCombination.Rot0, ProcOnFirstRotation)
SingleCombination.nComplete = SingleCombination.nComplete + 1
else
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
local nNextRot = nUnloadPos
local ResultsList = {}
@@ -1523,34 +1696,40 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bRePro
nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1)
end
-- se la feature può essere lavorata in almeno una rotazione
if #ResultsList > 0 then
local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo)
Proc.nIndexRotation = Data.nIndexRotation
-- inserisco la Proc nell'apposita lista
if Data.nIndexRotation == nUnloadPos then
table.insert( SingleCombination.Rot0, Proc)
elseif Data.nIndexRotation == nUnloadPos + 1 then
table.insert( SingleCombination.Rot90, Proc)
bRot90 = true
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
-- se la feature può essere lavorata in almeno una rotazione e non è un taglio di testa o coda
if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
SingleCombination.nIndexHeadCutInVProc = nProc
elseif ID.IsTailCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
SingleCombination.nIndexTailCutInVProc = nProc
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
if #ResultsList > 0 then
local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo)
Proc.nIndexRotation = Data.nIndexRotation
-- inserisco la Proc nell'apposita lista
if Data.nIndexRotation == nUnloadPos then
table.insert( SingleCombination.Rot0, Proc)
elseif Data.nIndexRotation == nUnloadPos + 1 then
table.insert( SingleCombination.Rot90, Proc)
bRot90 = true
else
table.insert( SingleCombination.Rot180, Proc)
bRot180 = true
end
SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + Data.dTimeToMachine
SingleCombination.dTotalQuality = SingleCombination.dTotalQuality + Data.dQuality
SingleCombination.dTotalCompletionIndex = SingleCombination.dTotalCompletionIndex + Data.dCompletionIndex
SingleCombination.nComplete = SingleCombination.nComplete + EgtIf( Data.bComplete, 1, 0)
SingleCombination.nNotComplete = SingleCombination.nNotComplete + EgtIf( Data.bNotComplete, 1, 0)
SingleCombination.nNotExecute = SingleCombination.nNotExecute + EgtIf( Data.bNotApplicable, 1, 0)
SingleCombination.nIndexInCombinationList = i
SingleCombination.nIndexRotation = nUnloadPos
else
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
else
if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
@@ -1665,7 +1844,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
nPhase = nPhase}
table.insert( DB_MACH_APPLIED, MachExtraInfo)
else
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, 0)
BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, 0)
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.
-- Altrimenti bisognava ricalcolare tutto, aumentando tempo di calcolo.
@@ -1823,7 +2002,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation
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
bProcess = bProcess or bTryToReProcess
end
@@ -1832,7 +2011,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
if MatrixResult.bSomeFeatureSide then
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -1851,14 +2030,14 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation
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
bProcess = bProcess or bTryToReProcess
end
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -1877,7 +2056,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
-- aggiunta lavorazioni in ultima fase
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD')
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'STD')
bProcess = bProcess or bTryToReProcess
-- se bisogna riprocessare, si annulla tutto
@@ -1917,7 +2096,7 @@ function BeamExec.ProcessMachinings( PARTS, bIsFlipRot)
-- ===== finiti i pezzi, si scarica il restante =====
local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw)
if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then
BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0)
BeamLib.AddPhaseWithRawParts( PARTS, #PARTS + 1, BeamData.ptOriXR, BeamData.dPosXR, 0)
local nPhase = EgtGetCurrPhase()
local idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'TYPE', 'REST')
@@ -1962,8 +2141,8 @@ end
function BeamExec.ProcessAlternatives( PARTS)
-- inizializzazione variabili globali per interfaccia
BEAM.ALTERNATIVESNEST2D = ''
BEAM.ALTERNATIVES = ''
local Alternatives = {}
local AlternativesNest2D = {}
-- ciclo sui pezzi
local BestCombination = {}
@@ -2193,7 +2372,7 @@ function BeamExec.ProcessAlternatives( PARTS)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation
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
bProcess = bProcess or bTryToReProcess
end
@@ -2202,7 +2381,7 @@ function BeamExec.ProcessAlternatives( PARTS)
if MatrixResult.bSomeFeatureSide then
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -2221,14 +2400,14 @@ function BeamExec.ProcessAlternatives( PARTS)
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
nCurrPosition = nRotation
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
bProcess = bProcess or bTryToReProcess
end
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
BeamLib.AddPhaseWithRawParts( PARTS, nPart, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
nPhase = EgtGetCurrPhase()
idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'ORD', nOrd)
@@ -2247,7 +2426,7 @@ function BeamExec.ProcessAlternatives( PARTS)
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
-- aggiunta lavorazioni in ultima fase
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD')
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS, PARTS[nPart], 'STD')
bProcess = bProcess or bTryToReProcess
-- se bisogna riprocessare, si annulla tutto
@@ -2281,7 +2460,7 @@ function BeamExec.ProcessAlternatives( PARTS)
-- ===== finiti i pezzi, si scarica il restante =====
local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw)
if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then
BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0)
BeamLib.AddPhaseWithRawParts( PARTS, #PARTS + 1, BeamData.ptOriXR, BeamData.dPosXR, 0)
local nPhase = EgtGetCurrPhase()
local idDisp = EgtGetPhaseDisposition( nPhase)
EgtSetInfo( idDisp, 'TYPE', 'REST')
@@ -2292,23 +2471,14 @@ function BeamExec.ProcessAlternatives( PARTS)
local bApplOk, _, _ = EgtApplyAllMachinings()
-- se non ci sono errori, soluzione alternativa valida: scrittura variabili globali per interfaccia
if bApplOk then
local Alternatives = {}
local sBitIndexCombinationWithInvert = BestCombination.sBitIndexCombination .. EgtIf( BestCombination.bPartInCombiIsInverted, '_INV', '')
if TotalCombiToTest[z].bIsNesting2D then
if BEAM.ALTERNATIVESNEST2D and BEAM.ALTERNATIVESNEST2D ~= "" then
table.insert( Alternatives, BEAM.ALTERNATIVESNEST2D)
end
table.insert( Alternatives, sBitIndexCombinationWithInvert)
BEAM.ALTERNATIVESNEST2D = table.concat( Alternatives, ', ')
table.insert( AlternativesNest2D, sBitIndexCombinationWithInvert)
else
if BEAM.ALTERNATIVES and BEAM.ALTERNATIVES ~= "" then
table.insert( Alternatives, BEAM.ALTERNATIVES)
end
table.insert( Alternatives, sBitIndexCombinationWithInvert)
BEAM.ALTERNATIVES = table.concat( Alternatives, ', ')
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
-- si riporta pezzo in posizione iniziale
@@ -2322,6 +2492,23 @@ function BeamExec.ProcessAlternatives( PARTS)
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
EgtRemoveMachGroup( nTempMachGroupName)
+157 -14
View File
@@ -161,17 +161,45 @@ function BeamLib.GetPartSplittingPoints( Part)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc)
function BeamLib.AddPhaseWithRawParts( PARTS, nPartIndex, OriXR, PosXR, dDeltaSucc)
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
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
local dRawMove = 0
local bIsFirstRaw = true
local dPosXFirst = 0
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)
EgtMoveToCornerRawPart( idRaw, OriXR, PosXR)
EgtMoveRawPart( idRaw, Vector3d( - dRawMove, 0, 0))
if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
idRaw = EgtGetNextRawPart( idRaw)
end
-- salvo info nuova fase aggiunta
@@ -395,6 +423,24 @@ function BeamLib.GetAddGroup( PartId)
return AddGrpId, sMchGrp
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
-- TODO da spostare in FeatureLib???
@@ -512,10 +558,69 @@ function BeamLib.GetDirectionFromSCC( nSCC)
elseif nSCC == MCH_SCC.ADIR_ZM then
vtSCC = -Z_AX()
end
return vtSCC
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
function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
@@ -785,17 +890,18 @@ function BeamLib.BinaryToDecimal( dNumber)
local sNumberToConvert = tostring( dNumber)
local dResult = 0
local k = 0
for i = #sNumberToConvert, 1, -1 do
k = k + 1
local n = string.sub(sNumberToConvert, k, k)
dResult = dResult + n*(2^(i-1))
local n = string.sub( sNumberToConvert, k, k)
dResult = dResult + n * ( 2^( i-1))
end
return dResult
end
-------------------------------------------------------------------------------------------------------------
-- TODO si può sostituire con funzione EgtNumToBitString
function BeamLib.DecimalToBinary( dNumber)
local sNumberToConvert = tostring( dNumber)
local n = sNumberToConvert
@@ -803,12 +909,12 @@ function BeamLib.DecimalToBinary( dNumber)
local sResult = ""
for i = sNumberToConvert, 0, -1 do
local q = math.modf(n)
n = n/2
local b = q%2
table.insert(tmp, b)
local q = math.modf( n)
n = n / 2
local b = q % 2
table.insert( tmp, b)
if (q == 1) then
if ( q == 1) then
break
end
end
@@ -816,7 +922,7 @@ function BeamLib.DecimalToBinary( dNumber)
for i = #tmp, 1, -1 do
sResult = sResult..tmp[i]
end
return tonumber( sResult)
end
@@ -830,6 +936,43 @@ function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
return NumberString
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
--- 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
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))
end
@@ -198,7 +198,7 @@ function FeatureLib.ClassifyTopology( Proc, Part)
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 bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc, Part)
local vAdj = Proc.AdjacencyMatrix
+2 -11
View File
@@ -607,9 +607,6 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
local ToolInfo = {}
-- parametri obbligatori
if type( ToolSearchParameters.FaceToMachine) ~= 'table' then
error( 'FindBlade : missing face info')
end
if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then
error( 'FindBlade : missing top head info')
end
@@ -675,12 +672,6 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
if not bIsBladeOk then
bIsToolCompatible = false
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
@@ -1184,7 +1175,7 @@ end
-------------------------------------------------------------------------------------------------------------
-- funzione per aggiungere una nuova lavorazione
function MachiningLib.AddOperations( MACHININGS, Part, sRotation)
function MachiningLib.AddOperations( MACHININGS, PARTS, Part, sRotation)
local nErr
local sErr = ''
local bAreAllMachiningApplyOk = true
@@ -1452,7 +1443,7 @@ function MachiningLib.AddOperations( MACHININGS, Part, sRotation)
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
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
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)
end
return dTHome - dLinear1, AxesNames
return dLinear1 - dTHome
end
-------------------------------------------------------------------------------------------------------------
local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength)
-- spostamento assi macchina in posizione
local dDeltaXBeamOffset = 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)
local dDeltaXHeadOffset = MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux)
-- si recuperano gli id delle geometrie dell'asse con cui controllare la collisione
local idCollisionGroup = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'COLLISION')
@@ -321,14 +319,18 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
local CollisionSurfTmId = {}
for i = 1, #CollisionGroupEntitiesId do
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
-- se presenti geometrie nel gruppo other si aggiungono anche quelle
if CollisionGroupOtherEntitiesId and #CollisionGroupOtherEntitiesId > 0 then
for i = 1, #CollisionGroupEntitiesId do
if EgtGetType( CollisionGroupEntitiesId[i]) == GDB_TY.SRF_MESH then
table.insert( CollisionSurfTmId, CollisionGroupEntitiesId[i])
for i = 1, #CollisionGroupOtherEntitiesId do
if EgtGetType( CollisionGroupOtherEntitiesId[i]) == GDB_TY.SRF_MESH then
local idCollisionOtherSurfTmCopy = EgtCopyGlob( CollisionGroupOtherEntitiesId[i], Part.idTempGroup)
EgtMove( idCollisionOtherSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB)
table.insert( CollisionSurfTmId, idCollisionOtherSurfTmCopy)
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
if bCollisionFoundPiece then
-- si riporta la trave in posizione originale
EgtMove( Part.idRaw, Vector3d( -dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
return true
end
@@ -368,7 +368,6 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
local bCollisionFoundRestLength = false
if not ( bCollisionFoundPiece or bCannotSplitRestLength) then
local idRestLengthSurfFr = GetRestlengthSurfTm( Part, sRestLengthSideForPreSimulation)
EgtMove( idRestLengthSurfFr, Vector3d( dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
if idRestLengthSurfFr then
for i = 1, #CollisionSurfTmId do
bCollisionFoundRestLength = EgtCDeSolidSolid( idRestLengthSurfFr, CollisionSurfTmId[i], BeamData.COLL_SIC)
@@ -385,9 +384,6 @@ local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Par
end
end
-- si riporta la trave in posizione originale
EgtMove( Part.idRaw, Vector3d( -dDeltaXBeamOffset, 0, 0), GDB_RT.GLOB)
return false, bCollisionFoundRestLength
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
-- 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
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable ( Feature hinders clamping)'
EgtOutLog( sErr)
+15 -1
View File
@@ -24,6 +24,8 @@ local function GetSCC( Machining)
if TOOLS[Machining.nToolIndex].SetupInfo.bToolOnAggregate then
nSCC = MCH_SCC.ADIR_NEAR
elseif TOOLS[Machining.nToolIndex].SetupInfo.nBlockedSCC then
nSCC = TOOLS[Machining.nToolIndex].SetupInfo.nBlockedSCC
elseif Machining.vtToolDirection:getY() <= 0 then
nSCC = MCH_SCC.ADIR_YM
else
@@ -96,7 +98,7 @@ function STR0014.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Machining.nSCC = GetSCC( Strategy.Machining)
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
-- LeadIn / LeadOut
@@ -104,7 +106,19 @@ function STR0014.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Machining.LeadOut = {}
Strategy.Machining.LeadIn.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
for i = 1, #Proc.FeatureInfo.AdditionalGeometries do
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
local sChosenBladeType = ''
if not nToolIndex then
nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Face1)
nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part)
end
-- 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],
dDepthToMachine = dDepthToMachine
}
if OppositeToolDirectionMode == 'Enabled' then
BladeEngagementParameters.Edge = EdgeToMachineOpposite
end
local BladeEngagementOptionalParameters = {
bIsDicing = bIsDicing,
sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation,