cc3ac6e186
- aggiunta funzione GetAffectedFaces per calcolo facce di riferimento - Lettura DB Utensili (da sistemare) - Gestione multipezzo in raccolta e lavorazione feature - Piccole correzioni varie
433 lines
18 KiB
Lua
433 lines
18 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
|
|
-- TODO Tool.AName -> da rimuovere perchè non serve. Per il momento lo manteniamo solo perchè è più facile vedere e interpretare la lista utensili nella watch di zerobrane
|
|
-- Nell'utilizzo, si legge sempre il Tool.Name
|
|
Tool.AName = Tool.sName
|
|
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.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)
|
|
-- TODO serve funzione in WinData che data la posizione dell'utensile e della testa, capisca il montaggio (testa sopra - testa sotto - aggregato - ecc...)
|
|
Tool.sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
Tool.SetupInfo = {}
|
|
Tool.SetupInfo = WinData.GetSetupInfo( Tool.sHead)
|
|
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( Part)
|
|
-- recupero le feature
|
|
local vPartProc = {}
|
|
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.id = ProcId
|
|
Proc.nFlg = 1
|
|
Proc.sType = sType
|
|
Proc.b3Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD)
|
|
Proc.nPhase = EgtGetInfo( ProcId, 'PHASE', 'i') or nil
|
|
-- informazioni facce
|
|
Proc.AffectedFaces = WinLib.GetAffectedFaces( Proc, Part)
|
|
|
|
-- 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
|
|
|
|
-- inserisco feature in lista
|
|
table.insert( vPartProc, Proc)
|
|
else
|
|
Proc.nFlg = 0
|
|
table.insert( vPartProc, Proc)
|
|
EgtOutLog( ' Feature ' .. tostring( Proc.idFeature) .. ' is empty (no geometry)')
|
|
end
|
|
end
|
|
end
|
|
ProcId = EgtGetNext( ProcId)
|
|
end
|
|
end
|
|
return vPartProc
|
|
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]
|
|
end
|
|
end
|
|
end
|
|
return vProc
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function OrderMachining( vProc, PARTS)
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- Ordina le feature in base a fase di lavorazione
|
|
-- L'ordine è indicativamente:
|
|
-- 1) Fori
|
|
-- 2) Scassi serratura/maniglia
|
|
-- 3) Profili testa
|
|
-- 4) Profili Lati
|
|
-- 5) Incontri/scontri
|
|
-- TODO Ordinamento da fare
|
|
local function OrderFeatures( vProc)
|
|
local vProcToSort = vProc
|
|
-- 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.nFlg ~= 0 and B2.nFlg == 0 then
|
|
return true
|
|
elseif B1.nPhase and B2.nPhase and B1.nPhase < B2.nPhase then
|
|
return true
|
|
elseif B1.nPhase and B2.nPhase and B2.nPhase < B1.nPhase then
|
|
return true
|
|
-- altrimenti si inverte
|
|
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].id, vProcToSort[j].id))
|
|
end
|
|
end
|
|
end
|
|
if bCompTest then
|
|
EgtOutLog( ' ALL OK')
|
|
end
|
|
end
|
|
|
|
-- eseguo ordinamento
|
|
table.sort( vProcToSort, CompareFeatures)
|
|
|
|
return vProcToSort
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- applica le lavorazioni
|
|
local function AddMachinings( ProcPart, Part)
|
|
local bMachiningOk = true
|
|
for nFeatureIndex = 1, #ProcPart do
|
|
local Proc = ProcPart[nFeatureIndex]
|
|
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, Part)
|
|
EgtOutLog( ' RawBox=' .. tostring( Part.RawBox))
|
|
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
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function WinExec.ProcessFeatures( PARTS)
|
|
-- ciclo sui pezzi
|
|
local nTotErr = 0
|
|
local Stats = {}
|
|
local nOrd = 1
|
|
local Part = {}
|
|
|
|
local vProc = {}
|
|
for nPart = 1, #PARTS do
|
|
-- lista contenente le feature da eseguire
|
|
|
|
-- recupero le feature di lavorazione della trave
|
|
table.insert( vProc, CollectFeatures( PARTS[nPart]))
|
|
|
|
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
|
|
vProc[nPart] = GetFeatureInfoAndDependency( vProc[nPart], PARTS[nPart])
|
|
|
|
-- debug
|
|
if EgtGetDebugLevel() >= 1 then
|
|
PrintFeatures( vProc[nPart], PARTS[nPart])
|
|
end
|
|
|
|
-- ordino le features
|
|
vProc[nPart] = OrderFeatures( vProc[nPart])
|
|
|
|
EgtOutLog( ' *** AddMachinings ***', 1)
|
|
|
|
-- TODO da fare
|
|
MACHININGS = {}
|
|
-- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale
|
|
AddMachinings( vProc[nPart], PARTS[nPart])
|
|
|
|
|
|
EgtOutLog( ' *** End AddMachinings ***', 1)
|
|
-- passo al grezzo successivo
|
|
nOrd = nOrd + 1
|
|
end
|
|
|
|
OrderMachining( vProc, PARTS)
|
|
|
|
-- aggiunge effettivamente le lavorazioni
|
|
MachiningLib.AddOperations( vProc, PARTS)
|
|
|
|
-- 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
|