- Creazione WinExec (derivazione da progetto Beam)
- Funzione allineamento pezzo - Funzione aggiunta sovramateriale pezzo - Altre modifiche minori
This commit is contained in:
Vendored
+2
-1
@@ -108,7 +108,8 @@
|
||||
"EgtFrame",
|
||||
"EgtReplaceString",
|
||||
"EgtCircle",
|
||||
"EgtArc2PV"
|
||||
"EgtArc2PV",
|
||||
"EgtTdbSetCurrTool"
|
||||
],
|
||||
"Lua.diagnostics.disable": [
|
||||
"empty-block"
|
||||
|
||||
@@ -0,0 +1,742 @@
|
||||
-- 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')
|
||||
|
||||
EgtOutLog( ' WinExec started', 1)
|
||||
EgtMdbSave()
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** variabili globali ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
TOOLS = nil
|
||||
STRATEGIES = nil
|
||||
MACHININGS = nil
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** COSTANTI *** TODO -> DA SPOSTARE IN BEAMDATA???
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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 BeamData 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 = BeamData.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 GetStrategiesFromGlobalList( Proc)
|
||||
-- cerco tra le feature
|
||||
for i = 1, #STRATEGIES.Features do
|
||||
-- se trovo la feature
|
||||
if Proc.nPrc == STRATEGIES.Features[i].nPrc and Proc.nGrp == STRATEGIES.Features[i].nGrp then
|
||||
-- cerco tra le topologie
|
||||
for j = 1, #STRATEGIES.Features[i].Topologies do
|
||||
-- se trovo la topologia
|
||||
if Proc.Topology.sName == STRATEGIES.Features[i].Topologies[j].sName then
|
||||
-- ritorno le strategie disponibili per la feature che sto analizzando
|
||||
return STRATEGIES.Features[i].Topologies[j].Strategies
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetStrategies( Proc)
|
||||
local AvailableStrategiesForProc = nil
|
||||
-- se la lista STRATEGIES è stata letta da JSON (quindi non è vuota), ritorno le strategie possibili
|
||||
if STRATEGIES and #STRATEGIES.Features > 0 then
|
||||
AvailableStrategiesForProc = GetStrategiesFromGlobalList( Proc)
|
||||
end
|
||||
-- se non ho trovato strategie disponibili nel JSON, o se JSON non presente, lancio script che setta le strategie in modo statico, come definito con cliente
|
||||
if not AvailableStrategiesForProc then
|
||||
AvailableStrategiesForProc = BCS.GetStrategiesFromBasicCustomerStrategies( Proc)
|
||||
end
|
||||
return AvailableStrategiesForProc
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetFeatureForcedStrategy( Proc)
|
||||
-- cerco nelle note se è stata forzata una strategia specifica
|
||||
local sStrategyId = EgtGetInfo( Proc.id, 'STRATEGY', 's')
|
||||
|
||||
-- se è presente la strategia forzata
|
||||
if sStrategyId then
|
||||
-- eseguo file config con i parametri di default
|
||||
local StrategyData = require( sStrategyId .. '\\' .. sStrategyId .. 'Config')
|
||||
|
||||
-- se ID strategia non esiste oppure ID letto in NGE è differente da quello letto nella strategia, esco subito
|
||||
if not StrategyData or StrategyData.sStrategyId ~= sStrategyId then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- salvo che questa strategia è stata forzata, e che quindi ho già letto il file config con i parametri di default
|
||||
-- quando si calcolerà la lavorazione non servirà leggere/riverificare i parametri di default
|
||||
StrategyData.bForcedStrategy = true
|
||||
|
||||
-- cerco e aggiorno i parametri come sono settati nel processing
|
||||
for i = 1, #StrategyData.Parameters do
|
||||
local sParameterToRead = StrategyData.sStrategyId .. '_' .. StrategyData.Parameters[i].sName
|
||||
ForcedParameterForProc = EgtGetInfo( Proc.id, sParameterToRead, 's')
|
||||
-- se ho trovato il valore, lo sovrascrivo al default
|
||||
if ForcedParameterForProc then
|
||||
StrategyData.Parameters[i].sValue = ForcedParameterForProc
|
||||
end
|
||||
end
|
||||
|
||||
-- ritorno la lista strategia con parametri
|
||||
local StrategyToProc = {}
|
||||
table.insert( StrategyToProc, StrategyData)
|
||||
return StrategyToProc
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function CollectFeatures( Part)
|
||||
-- recupero le feature
|
||||
local vProc = {}
|
||||
local LayerId = {}
|
||||
LayerId[1] = BeamLib.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 nGrp = EgtGetInfo( ProcId, 'GRP', 'i')
|
||||
local nPrc = EgtGetInfo( ProcId, 'PRC', 'i')
|
||||
local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1
|
||||
if nGrp and nPrc and nDo == 1 then
|
||||
local Proc = {}
|
||||
Proc.idPart = Part.id
|
||||
Proc.id = ProcId
|
||||
-- id della feature btl ( se non presente info, si prende id dell'entità geometrica)
|
||||
Proc.idFeature = EgtGetInfo( Proc.id, 'PRID', 's') or Proc.id
|
||||
Proc.nGrp = nGrp
|
||||
Proc.nPrc = nPrc
|
||||
Proc.nFlg = 1
|
||||
Proc.nFct = EgtSurfTmFacetCount( ProcId) or 0
|
||||
Proc.idCut = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0
|
||||
Proc.idTask = EgtGetInfo( ProcId, 'TASKID', 'i') or 0
|
||||
Proc.b3Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD)
|
||||
EgtOutLog( '------Feature ' .. Proc.idFeature .. '------')
|
||||
-- se esiste la geometria
|
||||
if Proc.b3Box and not Proc.b3Box:isEmpty() then
|
||||
-- TODO fare una funzione per recuperare i dati delle feature che non passano dal calcolo della topologia?
|
||||
-- se foro calcolo altri dati
|
||||
if ID.IsDrilling( Proc) then
|
||||
-- assegno diametro e facce di ingresso e uscita (dati tabelle sempre per riferimento)
|
||||
Proc.dDiam, Proc.dLen, Proc.nFcs, Proc.nFce = FeatureData.GetDrillingData( Proc)
|
||||
end
|
||||
-- informazioni facce e topologia
|
||||
Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part)
|
||||
-- calcolo topologia solo se necessario, altrimenti si sfruttano le informazioni della feature BTL
|
||||
Proc.Topology = {}
|
||||
if FeatureData.NeedTopologyFeature( Proc) then
|
||||
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
|
||||
Proc.Faces = FaceData.GetFacesInfo( Proc, Part)
|
||||
Proc.Topology = FeatureData.ClassifyTopology( Proc, Part)
|
||||
else
|
||||
Proc.Topology.sFamily = 'FEATURE'
|
||||
Proc.Topology.sName = 'FEATURE'
|
||||
end
|
||||
-- se topologia feature riconosciuta, oppure da non calcolare perchè il riconoscimento topologico è basato sulla feature stessa
|
||||
if Proc.Topology.sName ~= 'NOT_IMPLEMENTED' then
|
||||
Proc.MainFaces = FaceData.GetMainFaces( Proc, Part)
|
||||
-- se la processing ha una strategia forzata, riporto tutto nella proc
|
||||
local vForcedStrategy = GetFeatureForcedStrategy( Proc)
|
||||
if vForcedStrategy then
|
||||
Proc.AvailableStrategies = vForcedStrategy
|
||||
-- altrimenti cerco tra le strategie disponibili
|
||||
else
|
||||
Proc.AvailableStrategies = GetStrategies( Proc)
|
||||
end
|
||||
-- se ci sono strategie disponibili, aggiungo a lista delle feature da lavorare
|
||||
if Proc.AvailableStrategies and #Proc.AvailableStrategies > 0 then
|
||||
table.insert( vProc, Proc)
|
||||
-- altrimenti errore (non ci sono strategie per lavorare la topologia riconosciuta)
|
||||
else
|
||||
EgtOutLog( ' Feature ' .. tostring( Proc.idFeature) .. ' : NO available strategies')
|
||||
end
|
||||
-- altrimenti errore (serviva riconoscimento topologico, ma non è stato possibile farlo)
|
||||
else
|
||||
EgtOutLog( ' Feature ' .. tostring( Proc.idFeature) .. ' : NO available strategies')
|
||||
end
|
||||
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( vProcSingleRot, Part)
|
||||
-- ciclo tutte le feature
|
||||
for i = 1, #vProcSingleRot do
|
||||
local Proc = vProcSingleRot[i]
|
||||
-- controllo la feature con tutte le altre per recuperare le dipendenze
|
||||
for j = 1, #vProcSingleRot do
|
||||
-- non si controlla la feature con se stessa
|
||||
if i ~= j then
|
||||
local ProcB = vProcSingleRot[j]
|
||||
-- verifico se feature tipo LapJoint è attraversata da almeno un foro
|
||||
if ( Proc.Topology.sFamily == 'Pocket' or Proc.Topology.sFamily == 'Tunnel' or Proc.Topology.sFamily == 'Groove' or ID.IsMortise( Proc)) and
|
||||
ID.IsDrilling( ProcB) and Overlaps( Proc.b3Box, ProcB.b3Box) then
|
||||
Proc.bPassedByHole = true
|
||||
end
|
||||
-- verifiche per specchiature
|
||||
if BeamData.DOWN_HEAD or BeamData.TWO_EQUAL_HEADS then
|
||||
-- forature
|
||||
if BeamData.DOUBLE_HEAD_DRILLING and ID.IsDrilling( Proc) and ID.IsDrilling( ProcB) and not Proc.Mirror then
|
||||
if AreDrillingsMirrored( Proc, ProcB, Part) then
|
||||
Proc.Mirror = ProcB
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return vProcSingleRot
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function RunStrategyLibraries( sStrategyId)
|
||||
local StrategyConfigName = sStrategyId .. '\\' .. sStrategyId .. 'Config'
|
||||
local StrategyConfigPath = BEAM.BASEDIR .. '\\Strategies\\' .. StrategyConfigName .. '.lua'
|
||||
local StrategyScriptName = sStrategyId .. '\\' .. sStrategyId
|
||||
local StrategyScriptPath = BEAM.BASEDIR .. '\\Strategies\\' .. StrategyScriptName .. '.lua'
|
||||
local StrategyLib = {}
|
||||
if EgtExistsFile( StrategyConfigPath) and EgtExistsFile( StrategyScriptPath) then
|
||||
StrategyLib.Config = require( StrategyConfigName)
|
||||
-- eseguo file script strategia
|
||||
StrategyLib.Script = require( StrategyScriptName)
|
||||
return StrategyLib
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- ritorna l'indice della strategia migliore, tra le due passate
|
||||
local function GetIndexBestStrategyFromComparison( AvailableStrategies, nIndex1, nIndex2)
|
||||
local dChosenIndex = 0
|
||||
-- controllo indici
|
||||
if nIndex1 == 0 and nIndex2 == 0 then
|
||||
dChosenIndex = 0
|
||||
elseif nIndex1 == 0 then
|
||||
-- basta che sia applicabile
|
||||
if AvailableStrategies[nIndex2].Result and ( AvailableStrategies[nIndex2].Result.sStatus == 'Completed' or AvailableStrategies[nIndex2].Result.sStatus == 'Not-Completed') then
|
||||
dChosenIndex = nIndex2
|
||||
end
|
||||
elseif nIndex2 == 0 then
|
||||
-- basta che sia applicabile
|
||||
if AvailableStrategies[nIndex1].Result and ( AvailableStrategies[nIndex1].Result.sStatus == 'Completed' or AvailableStrategies[nIndex1].Result.sStatus == 'Not-Completed') then
|
||||
dChosenIndex = nIndex1
|
||||
end
|
||||
elseif not AvailableStrategies[nIndex1].Result or not AvailableStrategies[nIndex2].Result then
|
||||
dChosenIndex = 0
|
||||
elseif ( AvailableStrategies[nIndex1].Result.sStatus == 'Completed' and AvailableStrategies[nIndex2].Result.sStatus ~= 'Completed') or
|
||||
( AvailableStrategies[nIndex1].Result.sStatus == 'Not-Completed' and AvailableStrategies[nIndex2].Result.sStatus == 'Not-Applicable') then
|
||||
dChosenIndex = nIndex1
|
||||
elseif ( AvailableStrategies[nIndex2].Result.sStatus == 'Completed' and AvailableStrategies[nIndex1].Result.sStatus ~= 'Completed') or
|
||||
( AvailableStrategies[nIndex2].Result.sStatus == 'Not-Completed' and AvailableStrategies[nIndex1].Result.sStatus == 'Not-Applicable') then
|
||||
dChosenIndex = nIndex2
|
||||
else
|
||||
-- se le due strategie hanno stesso stato e sono entrambe applicabili (quindi entrambe complete o entrambe non-complete)
|
||||
if AvailableStrategies[nIndex1].Result.sStatus ~= 'Not-Applicable' and AvailableStrategies[nIndex2].Result.sStatus ~= 'Not-Applicable' and
|
||||
AvailableStrategies[nIndex1].Result.sStatus == AvailableStrategies[nIndex2].Result.sStatus then
|
||||
local dCompositeRatingStrategy1 = AvailableStrategies[nIndex1].Result.nQuality * AvailableStrategies[nIndex1].Result.nCompletionIndex * AvailableStrategies[nIndex1].Result.dMRR
|
||||
local dCompositeRatingStrategy2 = AvailableStrategies[nIndex2].Result.nQuality * AvailableStrategies[nIndex2].Result.nCompletionIndex * AvailableStrategies[nIndex2].Result.dMRR
|
||||
-- si predilige strategia con rating composito più alto
|
||||
if dCompositeRatingStrategy1 > dCompositeRatingStrategy2 then
|
||||
dChosenIndex = nIndex1
|
||||
elseif dCompositeRatingStrategy2 > dCompositeRatingStrategy1 then
|
||||
dChosenIndex = nIndex2
|
||||
-- altrimenti si prende la strategia con indice più basso
|
||||
else
|
||||
dChosenIndex = EgtIf( nIndex1 < nIndex2, nIndex1, nIndex2)
|
||||
end
|
||||
end
|
||||
end
|
||||
return dChosenIndex
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- funzione che processa tutte le feature sul pezzo e trova la miglior strategia di lavorazione tra quelle disponibili
|
||||
local function GetBestStrategy( vProcSingleRot, Part)
|
||||
-- per ogni feature
|
||||
for i = 1, #vProcSingleRot do
|
||||
-- processo tutte le feature attive
|
||||
local Proc = vProcSingleRot[i]
|
||||
if Proc.nFlg ~= 0 then
|
||||
-- controllo se ci sono strategie disponibili
|
||||
if Proc.AvailableStrategies and #Proc.AvailableStrategies > 0 then
|
||||
local nIndexBestStrategy = 0
|
||||
-- ciclo tutte le strategie della feature
|
||||
for nIndexCurrentStrategy = 1, #Proc.AvailableStrategies do
|
||||
-- eseguo file config con i parametri di default
|
||||
local CurrentStrategy = {}
|
||||
CurrentStrategy = RunStrategyLibraries( Proc.AvailableStrategies[nIndexCurrentStrategy].sStrategyId)
|
||||
-- controllo che le librerie siano state effettivamente caricate
|
||||
if CurrentStrategy.Config and CurrentStrategy.Script then
|
||||
local bStrategyOk
|
||||
-- eseguo la strategia solo come calcolo fattibilità e voto. Non si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati
|
||||
_, Proc.AvailableStrategies[nIndexCurrentStrategy].Result = CurrentStrategy.Script.Make( false, Proc, Part, Proc.AvailableStrategies[nIndexCurrentStrategy].Parameters)
|
||||
-- scelgo la migliore strategia tra le due
|
||||
nIndexBestStrategy = GetIndexBestStrategyFromComparison( Proc.AvailableStrategies, nIndexCurrentStrategy, nIndexBestStrategy)
|
||||
|
||||
-- se scelta strategia standard, esco subito alla prima che trovo completa
|
||||
-- TODO serve paraemtro da Beam&Wall ( oppure da confirgurazione) !!!!!!!!
|
||||
if BEAM.GetFirstCompletedStrategy and nIndexBestStrategy > 0 then
|
||||
if Proc.AvailableStrategies[nIndexBestStrategy].Result.sStatus == 'Complete' then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- se non trovo i file della strategia, scrivo che non è più disponibile
|
||||
else
|
||||
Proc.AvailableStrategies[nIndexCurrentStrategy].Result = {}
|
||||
Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sInfo = 'Strategy not found'
|
||||
end
|
||||
end
|
||||
-- salvo sulla proc la migliore strategia
|
||||
if nIndexBestStrategy ~= 0 then
|
||||
Proc.ChosenStrategy = Proc.AvailableStrategies[nIndexBestStrategy]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return vProcSingleRot
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- Ordina le feature in base a fase di lavorazione
|
||||
-- 1) Head : ( intestatura)
|
||||
-- 2) Standard : ( lavorazioni standard che non impattano sulal coda)
|
||||
-- 3) AdvanceTail : ( lavorazioni che richiedono taglio di separazione, ma che devono essere fatte prima perchè il taglio di separazione farebbe cadere il pezzo)
|
||||
-- 4) Split : ( taglio di separazione)
|
||||
-- 5) Tail : ( lavorazioni di coda, fatte dopo il taglio di separazione)
|
||||
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
|
||||
-- se entrambi disabilitati seguo l'Id
|
||||
elseif B1.nFlg == 0 and B2.nFlg == 0 then
|
||||
return ( B1.id < B2.id)
|
||||
-- se in rotazioni diverse, si mette in ordine di rotazioni
|
||||
elseif B1.nRot ~= B2.nRot then
|
||||
return ( B1.nRot < B2.nRot)
|
||||
-- se primo è taglio di testa, va prima degli altri casi
|
||||
elseif B1.Head and ( B2.Standard or B2.AdvanceTail or B2.Split or B2.Tail) then
|
||||
return true
|
||||
-- se primo è taglio standard, va prima degli altri casi
|
||||
elseif B1.Standard and ( B2.AdvanceTail or B2.Split or B2.Tail) then
|
||||
return true
|
||||
-- se primo è taglio di testa anticipata, va prima degli altri casi
|
||||
elseif B1.AdvanceTail and ( B2.Split or B2.Tail) then
|
||||
return true
|
||||
-- se primo è taglio di separazione, va prima delle lavorazioni di coda
|
||||
elseif B1.Split and B2.Tail then
|
||||
return true
|
||||
-- se da lavorare in stessa fase pezzo
|
||||
elseif B1.Head == B2.Head or B1.Standard == B2.Standard or B1.AdvanceTail == B2.AdvanceTail or B1.Split == B2.Split or B1.Tail == B2.Tail then
|
||||
-- confronto standard
|
||||
if abs( B1.b3Box:getCenter():getX() - B2.b3Box:getCenter():getX()) > 0.4 * ( B1.b3Box:getDimX() + B2.b3Box:getDimX()) then
|
||||
return B1.b3Box:getCenter():getX() > B2.b3Box:getCenter():getX()
|
||||
elseif abs( B1.b3Box:getCenter():getY() - B2.b3Box:getCenter():getY()) > 0.2 * ( B1.b3Box:getDimY() + B2.b3Box:getDimY()) then
|
||||
return B1.b3Box:getCenter():getY() > B2.b3Box:getCenter():getY()
|
||||
elseif abs( B1.b3Box:getCenter():getZ() - B2.b3Box:getCenter():getZ()) > 0.1 * ( B1.b3Box:getDimZ() + B2.b3Box:getDimZ()) then
|
||||
return B1.b3Box:getCenter():getZ() > B2.b3Box:getCenter():getZ()
|
||||
end
|
||||
-- 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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- esegue le strategie migliori che ha precedentemente scelto
|
||||
local function CalculateMachinings( vProc, Part)
|
||||
local bAreAllApplyOk = true
|
||||
MACHININGS = {}
|
||||
-- applico le strategie scelte
|
||||
for i = 1, #vProc do
|
||||
-- processo tutte le feature attive applicando le lavorazioni
|
||||
local Proc = vProc[i]
|
||||
if Proc.nFlg ~= 0 and Proc.ChosenStrategy then
|
||||
-- carico file script strategia (non serve verificare presenza del file perchè già fatto durante scelta strategia)
|
||||
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
|
||||
bAreAllApplyOk, _ = StrategyScript.Make( true, Proc, Part, Proc.ChosenStrategy.Parameters)
|
||||
end
|
||||
end
|
||||
return vProc
|
||||
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 Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Down=%s Side=%s Head=%s Tail=%s Fcse=%1d,%1d Diam=%.2f Fct=%2d Box=%s TopoName=%s',
|
||||
Proc.id, Proc.nGrp, Proc.nPrc, Proc.idTask, Proc.idCut,
|
||||
Proc.nFlg, EgtIf( Proc.bDown, 'T', 'F'), EgtIf( Proc.bSide, 'T', 'F'),
|
||||
EgtIf( Proc.bHead, 'T', 'F'), EgtIf( Proc.bTail, 'T', EgtIf( Proc.bAdvTail, 'A', 'F')),
|
||||
Proc.nFcs, Proc.nFce, Proc.dDiam, Proc.nFct, tostring( Proc.b3Box), Proc.Topology.sName or '')
|
||||
-- info speciali per Block Haus Half Lap
|
||||
if Proc.nPrc == 37 then
|
||||
local sSpec = string.format( ' N=%s Hd=%s', tostring( Proc.vtN or V_NULL()), EgtIf( Proc.bHeadDir, 'T', 'F'))
|
||||
sOut = sOut .. sSpec
|
||||
end
|
||||
EgtOutLog( sOut)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function WinExec.ProcessFeatures( PARTS)
|
||||
-- ciclo sui pezzi
|
||||
local nTotErr = 0
|
||||
local Stats = {}
|
||||
local nOrd = 1
|
||||
local Part = {}
|
||||
|
||||
for nPart = 1, #PARTS do
|
||||
if not PARTS[nPart].id and PARTS[nPart].b3Raw:getDimX() < BeamData.dMinRaw then break end
|
||||
|
||||
-- per ogni rotazione, calcolo come lavorare le feature per decidere posizionamento iniziale e in che rotazione verranno lavorate le singole feature
|
||||
local vProcRot = {}
|
||||
-- lista contenente le feature da eseguire
|
||||
local vProc = {}
|
||||
|
||||
|
||||
-- TODO da rimuovere o lasciare solo per debug
|
||||
if EgtGetDebugLevel() >= 3 then
|
||||
EgtStartCounter()
|
||||
end
|
||||
|
||||
|
||||
-- TODO Il numero di rotazioni da calcolare deve dipendere dalle impostazionei del cliente. Per adesso si calcolano tutte e 4, ma può essere ottimizzato
|
||||
for dRotIndex = 1, 4 do
|
||||
|
||||
-- recupero le feature di lavorazione della trave
|
||||
table.insert( vProcRot, CollectFeatures( PARTS[nPart]))
|
||||
|
||||
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
|
||||
-- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no
|
||||
vProcRot[dRotIndex] = GetFeatureInfoAndDependency( vProcRot[dRotIndex], PARTS[nPart])
|
||||
|
||||
-- sceglie la strategia migliore tra quelle disponibili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies)
|
||||
vProcRot[dRotIndex] = GetBestStrategy( vProcRot[dRotIndex], PARTS[nPart])
|
||||
|
||||
-- ruoto il grezzo per calcolare la fattibilità delle lavorazioni nella prossima rotazione
|
||||
-- vettore movimento grezzi per rotazione di 90deg ogni step
|
||||
local dDeltaYZ = PARTS[nPart].b3Raw:getDimY() - PARTS[nPart].b3Raw:getDimZ()
|
||||
local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2)
|
||||
local bPreMove = ( dDeltaYZ < 0)
|
||||
-- ruoto le travi della fase corrente
|
||||
if bPreMove then
|
||||
EgtMoveRawPart( PARTS[nPart].idRaw, vtMove)
|
||||
end
|
||||
EgtRotateRawPart( PARTS[nPart].idRaw, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
|
||||
if not bPreMove then
|
||||
EgtMoveRawPart( PARTS[nPart].idRaw, vtMove)
|
||||
end
|
||||
-- aggiorno info pezzo
|
||||
PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw)
|
||||
PARTS[nPart].b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[nPart].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
end
|
||||
|
||||
|
||||
-- TODO da rimuovere o lasciare solo per debug
|
||||
if EgtGetDebugLevel() >= 3 then
|
||||
local timeCollect = EgtStopCounter()
|
||||
timeCollect = timeCollect + 0
|
||||
EgtOutBox( timeCollect, 'Collect calculation time')
|
||||
EgtStartCounter()
|
||||
end
|
||||
|
||||
|
||||
-- TODO decidere come lavorare ogni feature in base alla matrice delle rotazioni
|
||||
-- la matrice delle rotazioni deve già salvare sulla proc la strategia da utilizzare
|
||||
-- Conviene salvarsi tutti i dati fino alla lavorazione e il ciclo di applicazione va ad applicare senza calcolare?
|
||||
|
||||
-- aggiungo la fase, se non è la prima
|
||||
if nOrd == 1 then
|
||||
EgtSetCurrPhase( 1)
|
||||
else
|
||||
BeamLib.AddPhaseWithRawParts( PARTS[nPart], BeamData.ptOriXR, BeamData.dPosXR, 0)
|
||||
end
|
||||
local nPhase = EgtGetCurrPhase()
|
||||
local nDispId = EgtGetPhaseDisposition( nPhase)
|
||||
EgtSetInfo( nDispId, 'TYPE', EgtIf( PARTS[nPart].id, 'START', 'REST'))
|
||||
EgtSetInfo( nDispId, 'ORD', nOrd)
|
||||
EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( PARTS[nPart].idRaw) .. ' Part=' .. tostring( PARTS[nPart].id) .. ' ***', 1)
|
||||
|
||||
-- debug
|
||||
if EgtGetDebugLevel() >= 1 then
|
||||
PrintFeatures( vProc, PARTS[nPart])
|
||||
end
|
||||
EgtOutLog( ' *** AddMachinings ***', 1)
|
||||
|
||||
-- TODO PROVVISORIO in attesa di scelta lavorazione in fase opportuna
|
||||
vProc = vProcRot[1]
|
||||
|
||||
-- ordino le features
|
||||
vProc = OrderFeatures( vProc)
|
||||
|
||||
-- TODO da fare
|
||||
MACHININGS = {}
|
||||
-- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale
|
||||
CalculateMachinings( vProc, PARTS[nPart])
|
||||
|
||||
-- TODO riordinare lavorazioni ottimizzando cambio utensile/spezzone ecc..., mantenendo dipendenze definite prima
|
||||
-- ordino le lavorazioni
|
||||
-- OrderMachining( vProc, PARTS[nPart])
|
||||
|
||||
-- aggiunge effettivamente le lavorazioni
|
||||
MachiningLib.AddOperations( vProc, PARTS[nPart])
|
||||
|
||||
|
||||
-- TODO da rimuovere o lasciare solo per debug
|
||||
if EgtGetDebugLevel() >= 3 then
|
||||
local timeMachining = EgtStopCounter()
|
||||
timeMachining = timeMachining + 0
|
||||
EgtOutBox( timeMachining, 'Machining calculation time')
|
||||
end
|
||||
|
||||
|
||||
EgtOutLog( ' *** End AddMachinings ***', 1)
|
||||
-- passo al grezzo successivo
|
||||
nOrd = nOrd + 1
|
||||
end
|
||||
|
||||
-- Aggiornamento finale di tutto
|
||||
EgtSetCurrPhase( 1)
|
||||
local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings()
|
||||
-- eventuale ricalcolo per macchine tipo PF (ma tengo warning del primo calcolo)
|
||||
if EgtExistsInfo( EgtGetCurrMachGroup(), 'RECALC') then
|
||||
EgtOutLog( ' **** RECALC ****')
|
||||
bApplOk, sApplErrors, _ = EgtApplyAllMachinings()
|
||||
EgtRemoveInfo( EgtGetCurrMachGroup(), 'RECALC')
|
||||
end
|
||||
if not bApplOk then
|
||||
nTotErr = nTotErr + 1
|
||||
table.insert( Stats, {nErr = 1, sMsg=sApplErrors, nRot=0, idCut=0, idTask=0})
|
||||
elseif sApplWarns and #sApplWarns > 0 then
|
||||
local vLine = EgtSplitString( sApplWarns, '\r\n')
|
||||
for i = 1, #vLine do
|
||||
local nPos = vLine[i]:find( '(WRN', 1, true)
|
||||
if nPos then
|
||||
local sData = vLine[i]:sub( nPos + 1, -2)
|
||||
local vVal = EgtSplitString( sData, ',')
|
||||
local nWarn = EgtGetVal( vVal[1] or '', 'WRN', 'i')
|
||||
local nCutId = EgtGetVal( vVal[2] or '', 'CUTID', 'i')
|
||||
if nWarn and nCutId then
|
||||
table.insert( Stats, { nErr=-nWarn, sMsg=vLine[i], nRot=0, idCut=nCutId, idTask=0})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ( nTotErr == 0), Stats
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return WinExec
|
||||
+81
-20
@@ -60,6 +60,31 @@ local WinExec = require( 'WinExec')
|
||||
-- Variabili globali
|
||||
PARTS = {}
|
||||
|
||||
-- Colore del grezzo
|
||||
local ColA = Color3d( 255, 165, 0, 30)
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Crea il grezzo che verrà messo in macchina
|
||||
---------------------------------------------------------------------
|
||||
local function AlignPieces( PARTS)
|
||||
for i = 1, #PARTS do
|
||||
-- TODO allinea X a globale, ma bisognerebbe tenere in considerazione l'orientamento pezzi che vuole la macchina
|
||||
local dRotX, dRotY, dRotZ = GetFixedAxesRotABCFromFrame( PARTS[i].idFrame)
|
||||
|
||||
local ptOrigFrame = getOrigin( PARTS[i].idFrame)
|
||||
|
||||
if dRotX ~= 0 then
|
||||
EgtRotate( PARTS[i].id, ptOrigFrame, X_AX(), dRotX)
|
||||
end
|
||||
if dRotY ~= 0 then
|
||||
EgtRotate( PARTS[i].id, ptOrigFrame, Y_AX(), dRotY)
|
||||
end
|
||||
if dRotZ ~= 0 then
|
||||
EgtRotate( PARTS[i].id, ptOrigFrame, Z_AX(), dRotZ)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** Recupero i pezzi da processare ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
@@ -86,8 +111,17 @@ local function MyProcessInputData()
|
||||
EgtOutBox( 'Non sono state selezionati pezzi', 'Lavora Pezzi', 'ERROR')
|
||||
return false
|
||||
else
|
||||
-- allineo i pezzi per come se li aspetta la macchina
|
||||
AlignPieces()
|
||||
-- recupero tutte le dimensioni necessarie
|
||||
local sOut = ''
|
||||
for i = 1, #PARTS do
|
||||
PARTS[i].idSolid = EgtGetFirstNameInGroup( PARTS[i].id, 'Solid')
|
||||
PARTS[i].idFrame = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo'), 'Frame')
|
||||
PARTS[i].b3Solid = EgtGetBBoxGlob( PARTS[i].idSolid or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
PARTS[i].dLength = PARTS[1].b3Solid:getDimX()
|
||||
PARTS[i].dWidth = PARTS[1].b3Solid:getDimY()
|
||||
PARTS[i].dHeight = PARTS[1].b3Solid:getDimZ()
|
||||
sOut = sOut .. PARTS[i].sName .. ', '
|
||||
end
|
||||
sOut = sOut:sub( 1, -3)
|
||||
@@ -115,10 +149,12 @@ local function GetDispOffsetFromNotes( nPieceIndex)
|
||||
DispOffset.Phase1 = {}
|
||||
DispOffset.Phase2 = {}
|
||||
|
||||
DispOffset.Phase1.dOffsetY = EgtGetInfo( PIECES[nPieceIndex].id, 'OFFY_1', 'd')
|
||||
DispOffset.Phase1.dOffsetZ = EgtGetInfo( PIECES[nPieceIndex].id, 'OFFZ_1', 'd')
|
||||
DispOffset.Phase2.dOffsetY = EgtGetInfo( PIECES[nPieceIndex].id, 'OFFY_2', 'd')
|
||||
DispOffset.Phase2.dOffsetZ = EgtGetInfo( PIECES[nPieceIndex].id, 'OFFZ_2', 'd')
|
||||
DispOffset.Phase1.dOffsetX = 0 -- dovrà essere calcolato in base alle lavorazioni
|
||||
DispOffset.Phase1.dOffsetY = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFY_1', 'd')
|
||||
DispOffset.Phase1.dOffsetZ = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFZ_1', 'd')
|
||||
DispOffset.Phase2.dOffsetX = 0 -- dovrà essere calcolato in base alle lavorazioni
|
||||
DispOffset.Phase2.dOffsetY = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFY_2', 'd')
|
||||
DispOffset.Phase2.dOffsetZ = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFZ_2', 'd')
|
||||
|
||||
-- controllo se tutti gli offset sono settati
|
||||
if DispOffset.Phase1.dOffsetY and DispOffset.Phase1.dOffsetZ and DispOffset.Phase2.dOffsetY and DispOffset.Phase2.dOffsetZ then
|
||||
@@ -131,13 +167,13 @@ end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetDispOffsetFromInput( nPieceIndex)
|
||||
-- assegno alle stringhe i valori letti, in modo che vengano proposti quelli nel dialogo
|
||||
local sOffYPh1 = EgtIf( PIECES[nPieceIndex].DispOffset.Phase1.dOffsetY, tostring( PIECES[nPieceIndex].DispOffset.Phase1.dOffsetY), tostring( PIECES[nPieceIndex].dWidth / 2))
|
||||
local sOffZPh1 = EgtIf( PIECES[nPieceIndex].DispOffset.Phase1.dOffsetZ, tostring( PIECES[nPieceIndex].DispOffset.Phase1.dOffsetZ), '0')
|
||||
local sOffYPh2 = EgtIf( PIECES[nPieceIndex].DispOffset.Phase2.dOffsetY, tostring( PIECES[nPieceIndex].DispOffset.Phase2.dOffsetY), tostring( PIECES[nPieceIndex].dWidth / 2))
|
||||
local sOffZPh2 = EgtIf( PIECES[nPieceIndex].DispOffset.Phase2.dOffsetZ, tostring( PIECES[nPieceIndex].DispOffset.Phase2.dOffsetZ), '0')
|
||||
local sOffYPh1 = EgtIf( PARTS[nPieceIndex].DispOffset.Phase1.dOffsetY, tostring( PARTS[nPieceIndex].DispOffset.Phase1.dOffsetY), tostring( PARTS[nPieceIndex].dWidth / 2))
|
||||
local sOffZPh1 = EgtIf( PARTS[nPieceIndex].DispOffset.Phase1.dOffsetZ, tostring( PARTS[nPieceIndex].DispOffset.Phase1.dOffsetZ), '0')
|
||||
local sOffYPh2 = EgtIf( PARTS[nPieceIndex].DispOffset.Phase2.dOffsetY, tostring( PARTS[nPieceIndex].DispOffset.Phase2.dOffsetY), tostring( PARTS[nPieceIndex].dWidth / 2))
|
||||
local sOffZPh2 = EgtIf( PARTS[nPieceIndex].DispOffset.Phase2.dOffsetZ, tostring( PARTS[nPieceIndex].DispOffset.Phase2.dOffsetZ), '0')
|
||||
|
||||
|
||||
local vInp = EgtDialogBox( 'Dati di disposizione pezzo: ' .. PIECES[nPieceIndex].sName,
|
||||
local vInp = EgtDialogBox( 'Dati di disposizione pezzo: ' .. PARTS[nPieceIndex].sName,
|
||||
{'Sporgenza laterale FASE1', sOffYPh1}, {'Posizione Z FASE1', sOffZPh1},
|
||||
{'Sporgenza laterale FASE2', sOffYPh2}, {'Posizione Z FASE2', sOffZPh2})
|
||||
if not vInp or #vInp == 0 then
|
||||
@@ -145,10 +181,10 @@ local function GetDispOffsetFromInput( nPieceIndex)
|
||||
end
|
||||
|
||||
-- salvo input nei valori che utilizzerò dopo
|
||||
PIECES[nPieceIndex].DispOffset.Phase1.dOffsetY = tonumber( vInp[1])
|
||||
PIECES[nPieceIndex].DispOffset.Phase1.dOffsetZ = tonumber( vInp[2])
|
||||
PIECES[nPieceIndex].DispOffset.Phase2.dOffsetY = tonumber( vInp[3])
|
||||
PIECES[nPieceIndex].DispOffset.Phase2.dOffsetZ = tonumber( vInp[4])
|
||||
PARTS[nPieceIndex].DispOffset.Phase1.dOffsetY = tonumber( vInp[1])
|
||||
PARTS[nPieceIndex].DispOffset.Phase1.dOffsetZ = tonumber( vInp[2])
|
||||
PARTS[nPieceIndex].DispOffset.Phase2.dOffsetY = tonumber( vInp[3])
|
||||
PARTS[nPieceIndex].DispOffset.Phase2.dOffsetZ = tonumber( vInp[4])
|
||||
|
||||
return true
|
||||
end
|
||||
@@ -156,23 +192,48 @@ end
|
||||
---------------------------------------------------------------------
|
||||
-- Crea il grezzo che verrà messo in macchina
|
||||
---------------------------------------------------------------------
|
||||
local function CreateRawPart( PIECES)
|
||||
|
||||
local function AddOverMaterialToRaw( PARTS)
|
||||
for i = 1, #PARTS do
|
||||
PARTS[i].RawOffset = {}
|
||||
-- recupero le info
|
||||
PARTS[i].RawOffset.dOverMatIn = EgtGetInfo( PARTS[i].id, 'OVERMAT_IN', 'd') or 5
|
||||
PARTS[i].RawOffset.dOverMatOut = EgtGetInfo( PARTS[i].id, 'OVERMAT_OUT', 'd') or 5
|
||||
PARTS[i].RawOffset.dOverMatLeft = EgtGetInfo( PARTS[i].id, 'OVERMAT_LEFT', 'd') or 5
|
||||
PARTS[i].RawOffset.dOverMatRight = EgtGetInfo( PARTS[i].id, 'OVERMAT_RIGHT', 'd') or 5
|
||||
-- aggiungo sovramateriale
|
||||
local dLength = PARTS[i].dLength + PARTS[i].RawOffset.dOverMatIn + PARTS[i].RawOffset.dOverMatOut
|
||||
local dWidth = PARTS[i].dWidth + PARTS[i].RawOffset.dOverMatLeft + PARTS[i].RawOffset.dOverMatRight
|
||||
local dHeight = PARTS[i].dHeight -- altezza non ha sovramteriale
|
||||
EgtModifyRawPartSize( PARTS[i].idRaw, dLength, dWidth, dHeight)
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Crea il grezzo che verrà messo in macchina
|
||||
---------------------------------------------------------------------
|
||||
local function CreateRaws( PARTS)
|
||||
for i = 1, #PARTS do
|
||||
PARTS[i].idRaw = EgtAddRawPartWithPart( PARTS[i].id, PARTS[i].idSolid, 0, ColA)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** Inserimento delle travi nel grezzo ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MyProcessPieces()
|
||||
|
||||
-- verifico che i pezzi selezionati siano compatibili con la macchina
|
||||
WinData.VerifyPieces( PIECES)
|
||||
WinData.VerifyPieces( PARTS)
|
||||
|
||||
-- si crea il grezzo
|
||||
CreateRawPart( PIECES)
|
||||
CreateRaws( PARTS)
|
||||
|
||||
-- aggiunta sovramateriale
|
||||
AddOverMaterialToRaw( PARTS)
|
||||
|
||||
-- recupero offset per posizionamento
|
||||
for i = 1, #PIECES do
|
||||
for i = 1, #PARTS do
|
||||
local bInsertedAllOffs = GetDispOffsetFromNotes( i)
|
||||
-- se non sono settati nelle note, li chiedo
|
||||
if not bInsertedAllOffs then
|
||||
@@ -185,7 +246,7 @@ local function MyProcessPieces()
|
||||
end
|
||||
|
||||
-- si dispongono i pezzi sulla tavola
|
||||
WinData.DisposePiecesOnTable( PIECES)
|
||||
WinData.DisposePiecesOnTable( PARTS)
|
||||
|
||||
return true
|
||||
end
|
||||
@@ -194,7 +255,7 @@ end
|
||||
-- *** Inserimento delle lavorazioni ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MyProcessFeatures()
|
||||
local bOk, Stats = WinExec.ProcessFeatures( PARTS)
|
||||
--local bOk = WinExec.ProcessFeatures( PARTS)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user