62aa67f46d
Commentato momentaneamente ordinamento su cambio utensile
558 lines
24 KiB
Lua
558 lines
24 KiB
Lua
-- WinExec.lua by Egalware s.r.l. 2024/06/13
|
|
-- Libreria esecuzione lavorazioni per Serramenti
|
|
|
|
-- Tabella per definizione modulo
|
|
local WinExec = {}
|
|
|
|
-- Include
|
|
require( 'EgtBase')
|
|
|
|
-- Carico i dati globali
|
|
local WinData = require( 'WinData')
|
|
local WinLib = require( 'WinLib')
|
|
local ID = require( 'Identity')
|
|
local FeatureData = require( 'FeatureData')
|
|
local MachiningLib = require( 'MachiningLib')
|
|
|
|
-- carico librerie di lavorazione
|
|
_G.package.loaded.Drilling = nil
|
|
_G.package.loaded.Cutting = nil
|
|
_G.package.loaded.Pocketing = nil
|
|
_G.package.loaded.Milling = nil
|
|
_G.package.loaded.Profiling = nil
|
|
local Drilling = require( 'Drilling')
|
|
local Cutting = require( 'Cutting')
|
|
local Pocketing = require( 'Pocketing')
|
|
local Milling = require( 'Milling')
|
|
local Profiling = require( 'Profiling')
|
|
|
|
|
|
EgtOutLog( ' WinExec started', 1)
|
|
EgtMdbSave()
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** variabili globali ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
TOOLS = nil
|
|
MACHININGS = nil
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** COSTANTI *** TODO -> DA SPOSTARE IN WINDATA???
|
|
-------------------------------------------------------------------------------------------------------------
|
|
TH_DIAMETER_HSK63 = 63
|
|
TH_LENGTH_HSK63 = 75
|
|
SIDEANGLE_DOVETAIL = 15
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** funzioni di base ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function GetToolTypeNameFromToolTypeID( dToolTypeID)
|
|
if dToolTypeID == MCH_TY.DRILL_STD then
|
|
return 'DRILL_STD', 'DRILLBIT'
|
|
elseif dToolTypeID == MCH_TY.DRILL_LONG then
|
|
return 'DRILL_LONG', 'DRILLBIT'
|
|
elseif dToolTypeID == MCH_TY.SAW_STD then
|
|
return 'SAW_STD', 'SAWBLADE'
|
|
elseif dToolTypeID == MCH_TY.SAW_FLAT then
|
|
return 'SAW_FLAT', 'SAWBLADE'
|
|
elseif dToolTypeID == MCH_TY.MILL_STD then
|
|
return 'MILL_STD', 'MILL'
|
|
elseif dToolTypeID == MCH_TY.MILL_NOTIP then
|
|
return 'MILL_NOTIP', 'MILL'
|
|
elseif dToolTypeID == MCH_TY.MORTISE_STD then
|
|
return 'MORTISE_STD', 'MORTISE'
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function IsToolOk( Tool)
|
|
-- controllo che i dati necessari siano impostati
|
|
if Tool.dMaxMaterial and Tool.dDiameter and Tool.dLength and Tool.sHead and Tool.sUUID then
|
|
-- se DRILLBIT non ho altri dati
|
|
if Tool.sFamily == 'DRILLBIT' then
|
|
return true
|
|
-- altrimenti controllo dati aggiuntivi altre famiglie di utensili
|
|
elseif Tool.sFamily == 'MORTISE' then
|
|
if Tool.dCornerRadius then
|
|
return true
|
|
end
|
|
else
|
|
if Tool.dThickness then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function WinExec.GetToolsFromDB()
|
|
|
|
-- TODO gli utensili profilati devono essere messi in una lista a parte ad accesso diretto TOOLS['Prof1'] in modo da non dover scorrere la lista
|
|
-- dato che saranno molti e l'applicazione sarà diretta. Non serve ciclarli
|
|
|
|
|
|
-- creo lista globale utensili disponibili
|
|
TOOLS = {}
|
|
-- lista appoggio utensile
|
|
local Tool = {}
|
|
|
|
-- recupero tutti gli utensili : punte a forare, lame, frese e motoseghe
|
|
Tool.sName = EgtTdbGetFirstTool( MCH_TF.DRILLBIT + MCH_TF.SAWBLADE + MCH_TF.MILL + MCH_TF.MORTISE)
|
|
while Tool.sName ~= '' do
|
|
-- imposto utensile come corrente per recuperarne i dati
|
|
EgtTdbSetCurrTool( Tool.sName)
|
|
|
|
-- verifico se utensile disponibile in attrezzaggio attuale e che abbia un tipo ben definito
|
|
local bToolLoadedOnSetup, sToolTCPos = EgtFindToolInCurrSetup( Tool.sName)
|
|
local nToolTypeId = EgtTdbGetCurrToolParam( MCH_TP.TYPE)
|
|
local sToolType, sToolFamily = GetToolTypeNameFromToolTypeID( nToolTypeId)
|
|
|
|
-- se verifica condizioni minime, recupero tutti gli altri dati
|
|
if bToolLoadedOnSetup and sToolType then
|
|
Tool.sTcPos = sToolTCPos
|
|
Tool.sFamily = sToolFamily
|
|
Tool.sType = sToolType
|
|
Tool.nTypeId = nToolTypeId
|
|
Tool.dMaxMaterial = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
|
|
Tool.dDiameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
|
|
Tool.dTotDiameter = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM)
|
|
Tool.dLength = EgtTdbGetCurrToolParam( MCH_TP.LEN)
|
|
Tool.dSpeed = EgtTdbGetCurrToolParam( MCH_TP.SPEED)
|
|
Tool.bIsCCW = Tool.dSpeed < 0
|
|
Tool.Feeds = {}
|
|
Tool.Feeds.dFeed = EgtTdbGetCurrToolParam( MCH_TP.FEED)
|
|
Tool.Feeds.dStartFeed = EgtTdbGetCurrToolParam( MCH_TP.STARTFEED)
|
|
Tool.Feeds.dEndFeed = EgtTdbGetCurrToolParam( MCH_TP.ENDFEED)
|
|
Tool.Feeds.dTipFeed = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED)
|
|
Tool.sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
Tool.SetupInfo = {}
|
|
Tool.SetupInfo = WinData.GetSetupInfo( {sHead = Tool.sHead, sTcPos = Tool.sTcPos})
|
|
Tool.sUUID = EgtTdbGetCurrToolParam( MCH_TP.UUID)
|
|
Tool.sUserNotes = EgtTdbGetCurrToolParam( MCH_TP.USERNOTES)
|
|
Tool.dMaxDepth = EgtTdbGetCurrToolMaxDepth() or Tool.dMaxMaterial
|
|
Tool.ToolHolder = {}
|
|
Tool.ToolHolder.dDiameter = EgtTdbGetCurrToolThDiam() or TH_DIAMETER_HSK63 -- diametro standard HSK63
|
|
Tool.ToolHolder.dLength = EgtTdbGetCurrToolThLength() or TH_LENGTH_HSK63 -- lunghezza standard HSK63
|
|
-- parametri scritti nelle note
|
|
Tool.nDouble = EgtGetValInNotes( Tool.sUserNotes, 'DOUBLE')
|
|
|
|
-- lettura parametri non comuni ( famiglia DRILLBIT non ha parametri specifici)
|
|
if sToolFamily ~= 'DRILLBIT' then
|
|
Tool.dThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK)
|
|
Tool.dLongitudinalOffset = EgtTdbGetCurrToolParam( MCH_TP.LONOFFSET)
|
|
Tool.dRadialOffset = EgtTdbGetCurrToolParam( MCH_TP.RADOFFSET)
|
|
-- recupero parametri propri delle frese
|
|
if sToolFamily == 'MILL' then
|
|
Tool.dStemDiameter = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or Tool.ToolHolder.dDiameter -- se non settato, considero diametro come ToolHolder
|
|
Tool.dSideAngle = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or 0
|
|
-- verifico che parametri siano compatibili con una fresa a coda di rondine ( angolo di fianco standard Coda di rondine -> 15°)
|
|
Tool.bIsDoveTail = Tool.Type == 'MILL_NOTIP' and abs( abs( Tool.dSideAngle) - SIDEANGLE_DOVETAIL) < 1
|
|
-- verifico che sia una fresa tipo T-Mill o BlockHaus
|
|
Tool.dSideDepth = EgtGetValInNotes( Tool.sUserNotes, 'SIDEDEPTH') or 0 -- se non settato nell'utensile, dico che non ha massimo affondamento laterale
|
|
Tool.bIsTMill = Tool.dSideDepth > 0
|
|
Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP') or ( Tool.dMaxMaterial / 3) -- se non settato nell'utensile, considero metà del tagliente
|
|
Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP') or floor( Tool.dDiameter / 3) -- se non settato nell'utensile, considero metà del diametro
|
|
Tool.bIsPen = abs( Tool.dSpeed) < 5
|
|
-- recupero parametri propri delle lame
|
|
elseif sToolFamily == 'SAWBLADE' then
|
|
Tool.bIsUsedForLongCut = EgtGetValInNotes( Tool.sUserNotes, 'LONGCUT') == 1 or false -- false coem valore di default
|
|
Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP') or Tool.dThickness -- se non settato nell'utensile, considero lo spessore lama
|
|
Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP') or Tool.dMaxMaterial -- se non settato nell'utensile, considero un quarto del diametro
|
|
-- recupero parametri propri delle motoseghe
|
|
elseif sToolFamily == 'MORTISE' then
|
|
Tool.dDistance = EgtTdbGetCurrToolParam( MCH_TP.DIST) or 90 -- 90mm dimensione standard aggregato catena
|
|
Tool.bIsMortise = EgtGetValInNotes( Tool.sUserNotes, 'MORTISE') == 1
|
|
Tool.bIsChainSaw = not Tool.bIsMortise
|
|
Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP') or floor( Tool.dMaxMaterial / 3) -- se non settato nell'utensile, considero un terzo della lunghezza
|
|
Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP') or ( Tool.dThickness - 1) -- se non settato nell'utensile, considero spessore catena meno 1mm di sicurezza
|
|
Tool.dCornerRadius = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD)
|
|
Tool.dWidth = Tool.dDiameter
|
|
end
|
|
end
|
|
|
|
-- se tutti i dati necessari sono disponibili, inserisco utensile nella lista globale degli utensili disponibili
|
|
if IsToolOk( Tool) then
|
|
table.insert( TOOLS, Tool)
|
|
-- altrimenti scrivo nel log che l'utensile non è conforme
|
|
else
|
|
EgtOutLog( '*** ' .. Tool.sName .. ' : NOT-COMPLIANT ***', 1)
|
|
end
|
|
|
|
-- reset dati
|
|
Tool = {}
|
|
end
|
|
|
|
-- recupero utensile successivo ( punte a forare, lame, frese e motoseghe)
|
|
Tool.sName = EgtTdbGetNextTool( MCH_TF.DRILLBIT + MCH_TF.SAWBLADE + MCH_TF.MILL + MCH_TF.MORTISE)
|
|
end
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** Inserimento delle lavorazioni nelle travi ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
|
|
local function CollectFeatures( vProc, Part, nIndexPart)
|
|
-- recupero le feature
|
|
local LayerId = {}
|
|
LayerId[1] = WinLib.GetAddGroup( Part.id)
|
|
LayerId[2] = EgtGetFirstNameInGroup( Part.id or GDB_ID.NULL, 'Processings')
|
|
for nInd = 1, 2 do
|
|
local ProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL)
|
|
while ProcId do
|
|
local nEntType = EgtGetType( ProcId)
|
|
if nEntType == GDB_TY.SRF_MESH or nEntType == GDB_TY.EXT_TEXT or
|
|
nEntType == GDB_TY.CRV_LINE or nEntType == GDB_TY.CRV_ARC or nEntType == GDB_TY.CRV_BEZ or nEntType == GDB_TY.CRV_COMPO then
|
|
local sType = EgtGetInfo( ProcId, 'FEATURE_TYPE', 's')
|
|
local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1
|
|
if sType and nDo == 1 then
|
|
local Proc = {}
|
|
Proc.idPart = Part.id
|
|
Proc.nIndexPart = nIndexPart
|
|
Proc.id = ProcId
|
|
Proc.nFlg = 1
|
|
Proc.sType = sType
|
|
Proc.b3Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD)
|
|
Proc.nPhase = EgtGetInfo( ProcId, 'PHASE', 'i') or nil
|
|
|
|
-- se esiste la geometria
|
|
if Proc.b3Box and not Proc.b3Box:isEmpty() then
|
|
-- calcolo dati specifici per tipologia di feature / lavorazione
|
|
-- se foro
|
|
if ID.IsDrilling( Proc) then
|
|
Proc = FeatureData.GetDrillingData( Proc)
|
|
end
|
|
-- se taglio
|
|
if ID.IsCutting( Proc) then
|
|
Proc = FeatureData.GetCuttingData( Proc)
|
|
end
|
|
-- se fresatura
|
|
if ID.IsMilling( Proc) then
|
|
Proc = FeatureData.GetMillingData( Proc)
|
|
end
|
|
-- se svuotatura
|
|
if ID.IsPocketing( Proc) then
|
|
Proc = FeatureData.GetPocketingData( Proc)
|
|
end
|
|
-- se profilatura
|
|
if ID.IsProfiling( Proc) then
|
|
Proc = FeatureData.GetProfilingData( Proc)
|
|
end
|
|
-- informazioni facce
|
|
Proc.AffectedFaces = WinLib.GetAffectedFaces( Proc, Part)
|
|
-- inserisco feature in lista
|
|
table.insert( vProc, Proc)
|
|
else
|
|
Proc.nFlg = 0
|
|
table.insert( vProc, Proc)
|
|
EgtOutLog( ' Feature ' .. tostring( Proc.idFeature) .. ' is empty (no geometry)')
|
|
end
|
|
end
|
|
end
|
|
ProcId = EgtGetNext( ProcId)
|
|
end
|
|
end
|
|
return vProc
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function GetFeatureInfoAndDependency( vProc, Part)
|
|
-- ciclo tutte le feature
|
|
for i = 1, #vProc do
|
|
local Proc = vProc[i]
|
|
-- controllo la feature con tutte le altre per recuperare le dipendenze
|
|
for j = 1, #vProc do
|
|
-- non si controlla la feature con se stessa
|
|
if i ~= j then
|
|
local ProcB = vProc[j]
|
|
-- TODO dipendenze da controllare :
|
|
-- * gruppo di forature con aggregato 2/3 uscite
|
|
-- * Se 'Left' e 'Out' hanno stesso profilo, vanno concatenati (anche 'Right' se consentito dalla macchina)
|
|
end
|
|
end
|
|
end
|
|
return vProc
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- ottimizza le lavorazioni, considerando di ridurre i cambi utensile
|
|
local function SortByChangeToolOpt( MACHININGS)
|
|
local vProcToSortToolOpt = {}
|
|
vProcToSortToolOpt = MACHININGS
|
|
|
|
for i = 1, #vProcToSortToolOpt do
|
|
for j = i + 1, #vProcToSortToolOpt do
|
|
-- se sono su stessa fase
|
|
if vProcToSortToolOpt[i].AuxiliaryData.nPhase == vProcToSortToolOpt[j].AuxiliaryData.nPhase then
|
|
-- se stesso utensile
|
|
if vProcToSortToolOpt[i].Machining.nToolIndex == vProcToSortToolOpt[j].Machining.nToolIndex then
|
|
if i + 1 == j then
|
|
-- il confronto riparte dall'ultimo spostato
|
|
i = j
|
|
else
|
|
-- sposto lavorazione confrontata dopo la principale
|
|
WinLib.ChangeElementPositionInTable( vProcToSortToolOpt, j, i+1)
|
|
-- il confronto riparte dall'ultimo spostato
|
|
i = j
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return vProcToSortToolOpt
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- Ordina le feature in base a fase di lavorazione
|
|
-- L'ordine è indicativamente:
|
|
-- 1) Tagli di testa
|
|
-- 2) Fori
|
|
-- 3) Scassi serratura/maniglia
|
|
-- 4) Profili testa / Minizinken
|
|
-- 5) Fori per spine dopo profilo di testa
|
|
-- 6) Profili longitudinali
|
|
-- 7) Passate pulitura per cambio profilo
|
|
-- 8) Incontri/scontri (encounter/clash)
|
|
-- 9) Listello ferma-vetro
|
|
-- 10) Pausa
|
|
-- 11) Lavorazioni dopo rimozione ferma-vetro
|
|
|
|
-- TODO Verificare se assegnare le fasi già quando si mette la lavorazione e ordinare solo in base alla fase di lavoro.
|
|
-- TODO il punto 11) deve essere diviso in altri punti in base alle lavorazioni. Per adesso è un gruppo generico.
|
|
-- TODO Ridefinire le fasi, prevedere anche la fase di cambio pinzaggio
|
|
|
|
local function OrderMachining( MACHININGS)
|
|
|
|
local vProcToSort = MACHININGS
|
|
-- funzione di confronto. TRUE = B1 prima di B2. FALSE = B2 prima di B1
|
|
local function CompareFeatures( B1, B2)
|
|
-- se secondo disabilitato, va lasciato dopo
|
|
if B1.Proc.nFlg ~= 0 and B2.Proc.nFlg == 0 then
|
|
return true
|
|
elseif B1.AuxiliaryData.nPhase < B2.AuxiliaryData.nPhase then
|
|
return true
|
|
elseif B1.AuxiliaryData.nPhase > B2.AuxiliaryData.nPhase then
|
|
return false
|
|
elseif B1.Machining.Geometry == B2.Machining.Geometry then
|
|
return B1.AuxiliaryData.nIndexMachining < B2.AuxiliaryData.nIndexMachining
|
|
elseif B1.AuxiliaryData.bIsProfiling and B2.AuxiliaryData.bIsDrilling and B2.AuxiliaryData.bExecAfterProfile then
|
|
return true
|
|
elseif B1.AuxiliaryData.bIsDrilling and B1.AuxiliaryData.bExecAfterProfile and B2.AuxiliaryData.bIsProfiling then
|
|
return false
|
|
elseif B1.AuxiliaryData.bIsDrilling and B2.AuxiliaryData.bIsProfiling then
|
|
return true
|
|
elseif B2.AuxiliaryData.bIsDrilling and B1.AuxiliaryData.bIsProfiling then
|
|
return false
|
|
elseif B1.AuxiliaryData.bIsProfiling and B2.AuxiliaryData.bIsProfiling then
|
|
-- profiling Generic sempre per ultimi
|
|
if B1.Proc.sProfileInfo == 'Generic' and B2.Proc.sProfileInfo ~= 'Generic' then
|
|
return false
|
|
elseif B2.Proc.sProfileInfo == 'Generic' and B1.Proc.sProfileInfo ~= 'Generic' then
|
|
return true
|
|
-- profiling Mixed dopo le profilature standard
|
|
elseif B1.Proc.sProfileInfo == 'Mixed' and B2.Proc.sProfileInfo ~= 'Mixed' then
|
|
return false
|
|
elseif B2.Proc.sProfileInfo == 'Mixed' and B1.Proc.sProfileInfo ~= 'Mixed' then
|
|
return true
|
|
-- negli altri casi si ordina solo in base alla posizione
|
|
elseif B1.Proc.b3Box:getCenter():getX() - B2.Proc.b3Box:getCenter():getX() < 10 * GEO.EPS_SMALL then
|
|
return EgtIf( B1.AuxiliaryData.nPhase == 1, true, false) -- se arrivati a questo controllo, la fase di lavorazione di entrambe è la stessa, quindi mi basta controllarne una
|
|
else
|
|
return EgtIf( B1.AuxiliaryData.nPhase == 1, false, true) -- se arrivati a questo controllo, la fase di lavorazione di entrambe è la stessa, quindi mi basta controllarne una
|
|
end
|
|
elseif B1.AuxiliaryData.bIsDrilling and B2.AuxiliaryData.bIsDrilling then
|
|
if B1.Proc.b3Box:getMin():getX() < B2.Proc.b3Box:getMin():getX() then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- test della funzione di ordinamento
|
|
if EgtGetDebugLevel() >= 3 then
|
|
EgtOutLog( ' CompareFeatures Test ')
|
|
local bCompTest = true
|
|
for i = 1, #vProcToSort do
|
|
for j = i + 1, #vProcToSort do
|
|
local bComp1 = CompareFeatures( vProcToSort[i], vProcToSort[j])
|
|
local bComp2 = CompareFeatures( vProcToSort[j], vProcToSort[i])
|
|
if bComp1 == bComp2 then
|
|
bCompTest = false
|
|
EgtOutLog( string.format( ' ProcId : %d vs %d --> ERROR', vProcToSort[i].Proc.id, vProcToSort[j].Proc.id))
|
|
end
|
|
end
|
|
end
|
|
if bCompTest then
|
|
EgtOutLog( ' ALL OK')
|
|
end
|
|
end
|
|
|
|
-- eseguo un primo ordinamento
|
|
table.sort( vProcToSort, CompareFeatures)
|
|
|
|
-- ordino per ottimizzare cambio utensile
|
|
-- MACHININGS = SortByChangeToolOpt( MACHININGS)
|
|
|
|
return true
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- applica le lavorazioni
|
|
local function AddMachinings( vProc, PARTS)
|
|
local bMachiningOk = true
|
|
for nFeatureIndex = 1, #vProc do
|
|
local Proc = vProc[nFeatureIndex]
|
|
local Part = PARTS[vProc[nFeatureIndex].nIndexPart]
|
|
if ID.IsDrilling( Proc) then
|
|
bMachiningOk = Drilling.Make( Proc, Part)
|
|
end
|
|
-- se taglio
|
|
if ID.IsCutting( Proc) then
|
|
bMachiningOk = Cutting.Make( Proc, Part)
|
|
end
|
|
-- se fresatura
|
|
if ID.IsMilling( Proc) then
|
|
bMachiningOk = Milling.Make( Proc, Part)
|
|
end
|
|
-- se svuotatura
|
|
if ID.IsPocketing( Proc) then
|
|
bMachiningOk = Pocketing.Make( Proc, Part)
|
|
end
|
|
-- se profilatura
|
|
if ID.IsProfiling( Proc) then
|
|
bMachiningOk = Profiling.Make( Proc, Part)
|
|
end
|
|
end
|
|
return bMachiningOk
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function PrintFeatures( vProc, PARTS)
|
|
EgtOutLog( ' === PARTS ====')
|
|
for i = 1, #PARTS do
|
|
EgtOutLog( ' RawBox(' .. tostring( i) .. ') =' .. tostring( PARTS[i].RawBox))
|
|
end
|
|
EgtOutLog( ' === FEATURES ====')
|
|
for i = 1, #vProc do
|
|
local Proc = vProc[i]
|
|
local sOut = string.format( 'Id=%3d Flg=%2d Type=%s', Proc.id, Proc.nFlg, Proc.sType)
|
|
EgtOutLog( sOut)
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function UpdateRawPosition( PARTS)
|
|
for i = 1, #PARTS do
|
|
PARTS[i].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo') or GDB_ID.NULL, GDB_BB.STANDARD)
|
|
PARTS[i].b3RawPart = EgtGetRawPartBBox( PARTS[i].idRaw)
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function CheckAndMovePawPart( nIdRawToMove, vtMove)
|
|
EgtMoveRawPart( nIdRawToMove, vtMove)
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function WinExec.ProcessFeatures( PARTS)
|
|
-- ciclo sui pezzi
|
|
local nTotErr = 0
|
|
local Stats = {}
|
|
local vProc = {}
|
|
MACHININGS = {}
|
|
|
|
-- aggiorno posizione grezzi dopo disposizione
|
|
EgtSetCurrPhase( 1)
|
|
UpdateRawPosition( PARTS)
|
|
|
|
-- si recuperano tutte le feature di tutti i pezzi in una lista unica
|
|
for nPart = 1, #PARTS do
|
|
-- recupero le feature di lavorazione della trave
|
|
vProc = CollectFeatures( vProc, PARTS[nPart], nPart)
|
|
|
|
-- recupero informazioni ausiliarie feature e dipendenze tra feature dello stesso pezzo
|
|
vProc = GetFeatureInfoAndDependency( vProc, PARTS[nPart])
|
|
end
|
|
|
|
-- debug
|
|
if EgtGetDebugLevel() >= 1 then
|
|
PrintFeatures( vProc, PARTS)
|
|
end
|
|
|
|
EgtOutLog( ' *** AddMachinings ***', 1)
|
|
|
|
-- esegue le lavorazioni e le salva in lista
|
|
AddMachinings( vProc, PARTS)
|
|
|
|
-- ordina le lavorazioni
|
|
OrderMachining( MACHININGS)
|
|
|
|
for i = 1, #MACHININGS do
|
|
if MACHININGS[i].AuxiliaryData.nPhase == 1 then
|
|
-- aggiunge effettivamente la lavorazione e restituisce gli ingombri
|
|
local bIsApplyOk, sErr, b3MachEncumbrance = MachiningLib.AddOperation( MACHININGS[i]) -- TODO ingombro lavorazione mi restituisce dati sbagliati. C'è un riferimento?
|
|
-- se feature di testa, sposto testa in base a ingombro lavorazione
|
|
if MACHININGS[i].Proc.bHeadProfile and b3MachEncumbrance then
|
|
PARTS[MACHININGS[i].Proc.nIndexPart].DispOffsets.Phase1.dOffsetX = b3MachEncumbrance:getMax():getX() - PARTS[MACHININGS[i].Proc.nIndexPart].b3Part:getMin():getX() + 5
|
|
end
|
|
end
|
|
end
|
|
|
|
-- TODO lo spostamento, oltre a controllare le collisioni con il profilo di testa, deve anche considerare il pinzaggio del pezzo nel suo insieme?
|
|
-- Es.: basterebbe aggiungere un offset di 50mm per la testa, ma se metto 60mm, posso utilizzare una morsa in più che altrimenti avrei dovuto togliere per una collisione con una svuotatura
|
|
|
|
-- sposto pezzo per permettere pinzaggio migliore e non aver colisione in testa
|
|
for i = 1, #PARTS do
|
|
-- TODO controllare calcolo ingombro
|
|
local vtMove = Vector3d( - PARTS[i].DispOffsets.Phase1.dOffsetX, 0, 0)
|
|
if vtMove ~= V_NULL() then
|
|
CheckAndMovePawPart( PARTS[i].idRaw, vtMove)
|
|
end
|
|
end
|
|
|
|
-- scrivo lavorazioni seconda fase
|
|
EgtSetCurrPhase( 2)
|
|
UpdateRawPosition( PARTS)
|
|
for i = 1, #MACHININGS do
|
|
if MACHININGS[i].AuxiliaryData.nPhase == 2 then
|
|
-- aggiunge effettivamente la lavorazione
|
|
local bIsApplyOk, sErr, b3MachEncumbrance = MachiningLib.AddOperation( MACHININGS[i]) -- TODO ingombro lavorazione mi restituisce dati sbagliati. C'è un riferimento?
|
|
-- se feature di testa, sposto testa in base a ingombro lavorazione
|
|
if MACHININGS[i].Proc.bHeadProfile and b3MachEncumbrance then
|
|
PARTS[MACHININGS[i].Proc.nIndexPart].DispOffsets.Phase2.dOffsetX = PARTS[MACHININGS[i].Proc.nIndexPart].b3Part:getMax():getX() - b3MachEncumbrance:getMin():getX() + 5
|
|
end
|
|
end
|
|
end
|
|
-- sposto pezzo per permettere pinzaggio migliore e non aver colisione in testa
|
|
for i = 1, #PARTS do
|
|
-- TODO controllare calcolo ingombro
|
|
local vtMove = Vector3d( PARTS[i].DispOffsets.Phase2.dOffsetX, 0, 0)
|
|
if vtMove ~= V_NULL() then
|
|
CheckAndMovePawPart( PARTS[i].idRaw, vtMove)
|
|
end
|
|
end
|
|
|
|
EgtOutLog( ' *** End AddMachinings ***', 1)
|
|
|
|
-- Aggiornamento finale di tutto
|
|
EgtSetCurrPhase( 1)
|
|
local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings()
|
|
if not bApplOk then
|
|
nTotErr = nTotErr + 1
|
|
table.insert( Stats, {nErr = 1, sMsg=sApplErrors})
|
|
end
|
|
|
|
return ( nTotErr == 0), Stats
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
return WinExec
|