From 1c00c1224b5c2f855efa40e7a21228de1ed78985 Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Mon, 17 Jun 2024 17:09:43 +0200 Subject: [PATCH] =?UTF-8?q?-=20Crazione=20strategie=20di=20lavorazione=20(?= =?UTF-8?q?per=20ora=20=C3=A8=20una=20per=20tipo)=20-=20Rimosso=20da=20Win?= =?UTF-8?q?Exec=20gestione=20strategie=20derivata=20da=20Beam=20-=20Pulita?= =?UTF-8?q?=20Collect=20da=20parametri=20provenienti=20da=20BTL=20-=20Proc?= =?UTF-8?q?essFeature=20semplitifacta.=20Non=20contempla=20rotazioni/ribal?= =?UTF-8?q?tamenti=20del=20pezzo=20-=20Aggiunta=20libreria=20delle=20lavor?= =?UTF-8?q?azioni=20-=20Aggiunta=20libreria=20identit=C3=A0=20di=20una=20l?= =?UTF-8?q?avorazione=20-=20Aggiunta=20libreria=20recupero=20informazioni?= =?UTF-8?q?=20feature=20-=20AlignRawsToTable=20spostata=20in=20ProcessWin?= =?UTF-8?q?=20(prima=20era=20nella=20macchina)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAMAuto/LuaLibs/FeatureData.lua | 44 +++ CAMAuto/LuaLibs/Identity.lua | 36 +++ CAMAuto/LuaLibs/MachiningLib.lua | 391 +++++++++++++++++++++++++ CAMAuto/LuaLibs/WinExec.lua | 472 ++++--------------------------- CAMAuto/LuaLibs/WinLib.lua | 14 + CAMAuto/ProcessWin.lua | 35 ++- CAMAuto/Strategies/Cutting.lua | 17 ++ CAMAuto/Strategies/Drillin.lua | 17 ++ CAMAuto/Strategies/Milling.lua | 17 ++ CAMAuto/Strategies/Pocketing.lua | 17 ++ CAMAuto/Strategies/Profiling.lua | 38 +++ 11 files changed, 679 insertions(+), 419 deletions(-) create mode 100644 CAMAuto/LuaLibs/FeatureData.lua create mode 100644 CAMAuto/LuaLibs/Identity.lua create mode 100644 CAMAuto/LuaLibs/MachiningLib.lua create mode 100644 CAMAuto/Strategies/Cutting.lua create mode 100644 CAMAuto/Strategies/Drillin.lua create mode 100644 CAMAuto/Strategies/Milling.lua create mode 100644 CAMAuto/Strategies/Pocketing.lua create mode 100644 CAMAuto/Strategies/Profiling.lua diff --git a/CAMAuto/LuaLibs/FeatureData.lua b/CAMAuto/LuaLibs/FeatureData.lua new file mode 100644 index 0000000..7907e0f --- /dev/null +++ b/CAMAuto/LuaLibs/FeatureData.lua @@ -0,0 +1,44 @@ +-- FeatureData.lua by Egalware s.r.l. 2024/06/18 +-- Libreria lettura o calcolo dati e proprietà della feature + +-- Tabella per definizione modulo +local FeatureData = {} + +-- Carico i dati globali +local WinData = require( 'WinData') + +------------------------------------------------------------------------------------------------------------- +-- Recupero dati foro +function FeatureData.GetDrillingData( Proc) + local bOk, ptCentre, vtDir, dRadius = EgtCurveIsACircle( Proc.id) + + Proc.dDiam = dRadius * 2 + Proc.dLen = abs( EgtCurveThickness( Proc.id)) or 0 + Proc.ptCentre = ptCentre + Proc.vtDir = vtDir + + return Proc +end + +------------------------------------------------------------------------------------------------------------- +-- Recupero dati profilatura +function FeatureData.GetProfilingData( Proc) + -- recupero utensili + Proc.nToolsToUse = EgtGetInfo( Proc.id, 'NTOOLS', 'i') or 0 + Proc.Tools = {} + for t = 1, Proc.nToolsToUse do + local Data = {} + Data.sName = EgtGetInfo( Proc.id, 'TOOL_NAME_' .. tostring(t), 's') or 0 + Data.dRadialOvermat = EgtGetInfo( Proc.id, 'OFFR_' .. tostring(t), 'd') or 0 + Data.dLongitudinalOvermat = EgtGetInfo( Proc.id, 'OFFL_' .. tostring(t), 'd') or 0 + Data.sSide = EgtGetInfo( Proc.id, 'N', 's') or 0 + table.insert( Proc.Tools, Data) + end + + Proc.ProfileType = EgtGetInfo( Proc.id, 'ProfileType', 's') or '' + return Proc +end + +------------------------------------------------------------------------------------------------------------- + +return FeatureData \ No newline at end of file diff --git a/CAMAuto/LuaLibs/Identity.lua b/CAMAuto/LuaLibs/Identity.lua new file mode 100644 index 0000000..8955f9c --- /dev/null +++ b/CAMAuto/LuaLibs/Identity.lua @@ -0,0 +1,36 @@ +-- Identity.lua by Egalware s.r.l. 2024/06/18 +-- Libreria Riconoscimento della feature + +-- Tabella per definizione modulo +local Identity = {} + +--------------------------------------------------------------------- +------------------------ STANDARD FEATURES ------------------------ +--------------------------------------------------------------------- +-- Feature : Drilling +function Identity.IsDrilling( Proc) + return Proc.sType == 'Hole' +end +--------------------------------------------------------------------- +-- Feature : Cutting +function Identity.IsCutting( Proc) + return Proc.sType == 'Cut' +end +--------------------------------------------------------------------- +-- Feature : Milling +function Identity.IsMilling( Proc) + return Proc.sType == 'Milling' +end +--------------------------------------------------------------------- +-- Feature : Pocketing +function Identity.IsPocketing( Proc) + return Proc.sType == 'Pocket' +end +--------------------------------------------------------------------- +-- Feature : Profiling +function Identity.IsProfiling( Proc) + return Proc.sType == 'Profiling' +end + +--------------------------------------------------------------------- +return Identity diff --git a/CAMAuto/LuaLibs/MachiningLib.lua b/CAMAuto/LuaLibs/MachiningLib.lua new file mode 100644 index 0000000..f39f4cd --- /dev/null +++ b/CAMAuto/LuaLibs/MachiningLib.lua @@ -0,0 +1,391 @@ +-- MachiningLib.lua by Egalware s.r.l. 2024/06/17 +-- Libreria ricerca lavorazioni per serramenti + +-- Tabella per definizione modulo +local MachiningLib = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local BeamData = require( 'BeamData') + +EgtOutLog( ' MachiningLib started', 1) + +--------------------------------------------------------------------- +-- TODO da considerare solo angolo 2D?? +local function GetToolEntryAngle( Proc, vtTool) + local Angle = {} + + local dSinAngle = -10 * GEO.EPS_SMALL + local vtNorm + if Proc.AffectedFaces.bTop then + vtNorm = Z_AX() + dSinAngle = max( dSinAngle, vtTool * vtNorm) + end + if Proc.AffectedFaces.bBottom then + vtNorm = -Z_AX() + dSinAngle = max( dSinAngle, vtTool * vtNorm) + end + if Proc.AffectedFaces.bFront then + vtNorm = -Y_AX() + dSinAngle = max( dSinAngle, vtTool * vtNorm) + end + if Proc.AffectedFaces.bBack then + vtNorm = Y_AX() + dSinAngle = max( dSinAngle, vtTool * vtNorm) + end + if Proc.AffectedFaces.bLeft then + vtNorm = -X_AX() + dSinAngle = max( dSinAngle, vtTool * vtNorm) + end + if Proc.AffectedFaces.bRight then + vtNorm = X_AX() + dSinAngle = max( dSinAngle, vtTool * vtNorm) + end + + local dCosAngle = sqrt( 1 - sqr( dSinAngle)) + local dAngle = acos( dCosAngle) + local dTanAngle + if dAngle ~= 0 and dAngle ~= 90 then + dTanAngle = sqrt( 1 - dCosAngle * dCosAngle) / dCosAngle + end + + Angle.dValue = dAngle + Angle.dSin = dSinAngle + Angle.dCos = dCosAngle + Angle.dTan = dTanAngle + + return Angle + end + + ------------------------------------------------------------------------------------------------------------- +-- funzione per cercare utensile tipo FRESA con certe caratteristiche +function MachiningLib.FindMill( Proc, ToolSearchParameters) + local ToolInfo = {} + + local nBestToolIndex + local dBestToolResidualDepth = 0 + for i = 1, #TOOLS do + -- prima verifico che utensile sia compatibile + local bIsToolCompatible = true + if ToolSearchParameters.sName and ToolSearchParameters.sName ~= TOOLS[i].sName then + bIsToolCompatible = false + elseif ToolSearchParameters.dMaxToolDiameter and TOOLS[i].dDiameter > ToolSearchParameters.dMaxToolDiameter then + bIsToolCompatible = false + elseif ToolSearchParameters.sMillShape and ToolSearchParameters.sMillShape == 'STANDARD' and ( TOOLS[i].dSideAngle ~= 0 or TOOLS[i].bIsPen) then + bIsToolCompatible = false + elseif ToolSearchParameters.sMillShape and ToolSearchParameters.sMillShape == 'DOVETAIL' and not TOOLS[i].bIsDoveTail then + bIsToolCompatible = false + elseif ToolSearchParameters.sMillShape and ToolSearchParameters.sMillShape == 'TSHAPEMILL' and not TOOLS[i].bIsTMill then + bIsToolCompatible = false + elseif ToolSearchParameters.sMillShape and ToolSearchParameters.sMillShape == 'PEN' and not TOOLS[i].bIsPen then + bIsToolCompatible = false + elseif ToolSearchParameters.sType and TOOLS[i].sType ~= ToolSearchParameters.sType then + -- se sto cercando una fresa che non può lavorare di testa, quelle che lavorano di testa sono comunque ammesse + if TOOLS[i].sType == 'MILL_STD' and ToolSearchParameters.sType == 'MILL_NOTIP' then + bIsToolCompatible = true + else + bIsToolCompatible = false + end + end + + -- scelgo il migliore + if bIsToolCompatible then + -- calcolo riduzione del massimo materiale utilizzabile + local ToolEntryAngle = GetToolEntryAngle( Proc, ToolSearchParameters.vtToolDirection) + -- se ToolHolder più grande dell'utensile, il primo oggetto in collisione è il ToolHolder. Altrimenti il motore. + local dDimObjToCheck = EgtIf( TOOLS[i].ToolHolder.dDiameter > TOOLS[i].dDiameter, TOOLS[i].ToolHolder.dDiameter, BeamData.C_SIMM_ENC) + local dCurrentMaxMatReduction = BeamData.COLL_SIC or 5 + + -- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom) + -- TODO considerare anche il caso in cui lo stelo sia più grande del diametro utensile + -- TODO nei confronti tra valori gestire tolleranze + -- calcolo riduzione per non toccare con ToolHolder / Motore + if ToolEntryAngle.dValue > 0 and ToolEntryAngle.dValue < 90 then + dCurrentMaxMatReduction = dCurrentMaxMatReduction / ToolEntryAngle.dSin + ( ( dDimObjToCheck - TOOLS[i].dDiameter) / 2) / ToolEntryAngle.dTan + end + -- dCurrMachReduction = negativo -> limitare, positivo -> mm extra disponibili + local dCurrentResidualDepth = ToolSearchParameters.dElevation + dCurrentMaxMatReduction - TOOLS[i].dMaxDepth + + -- se non ancora trovato, oppure se completo e il migliore fino ad ora non è completo: corrente è il migliore + if not nBestToolIndex or ( dBestToolResidualDepth > 0 and dCurrentResidualDepth <= 0) then + nBestToolIndex = i + dBestToolResidualDepth = dCurrentResidualDepth + -- altrimenti scelgo il migliore + else + -- se entrambi completi + if dBestToolResidualDepth <= 0 and dCurrentResidualDepth <= 0 then + -- se il migliore era su aggregato e corrente montanto direttamente, prediligo utensile montato direttamente + if not TOOLS[i].SetupInfo.bToolOnAggregate and TOOLS[i].SetupInfo.bToolOnAggregate then + nBestToolIndex = i + dBestToolResidualDepth = dCurrentResidualDepth + -- se hanno stesso montaggio + elseif TOOLS[i].SetupInfo.bToolOnAggregate == TOOLS[nBestToolIndex].SetupInfo.bToolOnAggregate then + -- scelgo utensile con indice di bontà utensile calcolato come: lunghezza / massimo materiale / diametro + if ( TOOLS[i].dLength / TOOLS[i].dMaxMaterial) / TOOLS[i].dDiameter < ( TOOLS[nBestToolIndex].dLength / TOOLS[nBestToolIndex].dMaxMaterial) / TOOLS[nBestToolIndex].dDiameter then + nBestToolIndex = i + dBestToolResidualDepth = dCurrentResidualDepth + end + end + -- se entrambi incompleti + elseif dBestToolResidualDepth > 0 and dCurrentResidualDepth > 0 then + --scelgo quello che lavora di più + if dCurrentResidualDepth < dBestToolResidualDepth then + nBestToolIndex = i + dBestToolResidualDepth = dCurrentResidualDepth + end + end + end + end + end + + ToolInfo.nToolIndex = nBestToolIndex + ToolInfo.dResidualDepth = dBestToolResidualDepth + + return ToolInfo +end + +------------------------------------------------------------------------------------------------------------- +-- funzione per cercare utensile tipo LAMA con certe caratteristiche +-- TODO da completare +function MachiningLib.FindBlade( Proc, ToolSearchParameters) + local ToolInfo = {} + + -- parametri opzionali + ToolSearchParameters.dElevation = ToolSearchParameters.dElevation or 0 + ToolSearchParameters.bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false + + local nBestToolIndex + for i = 1, #TOOLS do + local bIsToolCompatible = false + + -- TODO per il momento si prende la prima lama. Da completare + if TOOLS[i].sFamily == 'SAWBLADE' then + bIsToolCompatible = true + end + + if bIsToolCompatible then + nBestToolIndex = i + break + end + end + + ToolInfo.nToolIndex = nBestToolIndex + + return ToolInfo +end + +------------------------------------------------------------------------------------------------------------- +-- funzione per cercare utensile tipo PUNTA A FORARE con certe caratteristiche +-- TODO da fare +function MachiningLib.FindDrill() +end + +------------------------------------------------------------------------------------------------------------- +-- salva in lista globale la lavorazione appena calcolata +function MachiningLib.AddNewMachining( ProcToAdd, MachiningToAdd) + -- Controllo parametri obbligatori + if not MachiningToAdd.nType or not MachiningToAdd.nToolIndex or not MachiningToAdd.Geometry or not ProcToAdd.id then + return false + end + + -- Drilling + if MachiningToAdd.nType == MCH_MY.DRILLING then + MachiningToAdd.sTypeName = 'Drill_' + -- Milling + elseif MachiningToAdd.nType == MCH_MY.MILLING then + -- se utensile lama + if TOOLS[MachiningToAdd.nToolIndex].sFamily == 'SAWBLADE' then + MachiningToAdd.sTypeName = 'Cut_' + else + MachiningToAdd.sTypeName = 'Mill_' + end + -- Pocketing + elseif MachiningToAdd.nType == MCH_MY.POCKETING then + MachiningToAdd.sTypeName = 'Pocket_' + -- Mortising + elseif MachiningToAdd.nType == MCH_MY.MORTISING then + MachiningToAdd.sTypeName = 'ChSaw_' + end + -- se nome non definito, assegno alla lavorazioen un nome standard + if not MachiningToAdd.sOperationName then + MachiningToAdd.sOperationName = MachiningToAdd.sTypeName .. ( EgtGetName( ProcToAdd.id) or tostring( ProcToAdd.id)) .. '_' .. tostring( MachiningToAdd.Geometry[1][2]) + end + if not MachiningToAdd.sToolName then + MachiningToAdd.sToolName = TOOLS[MachiningToAdd.nToolIndex].sName + end + local Machining = {} + Machining.Proc = ProcToAdd + Machining.Machining = MachiningToAdd + table.insert( MACHININGS, Machining) + return true +end + +------------------------------------------------------------------------------------------------------------- +-- funzione per aggiungere una nuova lavorazione +function MachiningLib.AddOperations( vProc, Part) + local nErr + local sErr = '' + local bAreAllMachiningApplyOk = true + + for i = 1, #MACHININGS do + -- creazione lavorazione + local nOperationId = EgtCreateMachining( MACHININGS[i].Machining.sOperationName, MACHININGS[i].Machining.nType, MACHININGS[i].Machining.sToolName) + + if nOperationId then + -- impostazione geometria + EgtSetMachiningGeometry( MACHININGS[i].Machining.Geometry) + + -- impostazione parametri lavorazione + if MACHININGS[i].Machining.sDepth then + EgtSetMachiningParam( MCH_MP.DEPTH_STR, MACHININGS[i].Machining.sDepth) + end + if MACHININGS[i].Machining.bInvert then + EgtSetMachiningParam( MCH_MP.INVERT, MACHININGS[i].Machining.bInvert) + end + if MACHININGS[i].Machining.nWorkside then + EgtSetMachiningParam( MCH_MP.WORKSIDE, MACHININGS[i].Machining.nWorkside) + end + if MACHININGS[i].Machining.nFaceuse then + EgtSetMachiningParam( MCH_MP.FACEUSE, MACHININGS[i].Machining.nFaceuse) + end + if MACHININGS[i].Machining.nSCC then + EgtSetMachiningParam( MCH_MP.SCC, MACHININGS[i].Machining.nSCC) + end + if MACHININGS[i].Machining.bToolInvert then + EgtSetMachiningParam( MCH_MP.TOOLINVERT, MACHININGS[i].Machining.bToolInvert) + end + if MACHININGS[i].Machining.sBlockedAxis then + EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, MACHININGS[i].Machining.sBlockedAxis) + end + if MACHININGS[i].Machining.sInitialAngles then + EgtSetMachiningParam( MCH_MP.INITANGS, MACHININGS[i].Machining.sInitialAngles) + end + if MACHININGS[i].Machining.nHeadSide then + EgtSetMachiningParam( MCH_MP.HEADSIDE, MACHININGS[i].Machining.nHeadSide) + end + if MACHININGS[i].Machining.nSubType then + EgtSetMachiningParam( MCH_MP.SUBTYPE, MACHININGS[i].Machining.nSubType) + end + if MACHININGS[i].Machining.dOverlap then + EgtSetMachiningParam( MCH_MP.OVERL, MACHININGS[i].Machining.dOverlap) + end + + -- step + if MACHININGS[i].Machining.Steps then + if MACHININGS[i].Machining.Steps.dStepType then + EgtSetMachiningParam( MCH_MP.STEPTYPE, MACHININGS[i].Machining.Steps.dStepType) + end + if MACHININGS[i].Machining.Steps.dStep then + EgtSetMachiningParam( MCH_MP.STEP, MACHININGS[i].Machining.Steps.dStep) + end + if MACHININGS[i].Machining.Steps.dSideStep then + EgtSetMachiningParam( MCH_MP.SIDESTEP, MACHININGS[i].Machining.Steps.dSideStep) + end + end + + if MACHININGS[i].Machining.dStartPos then + EgtSetMachiningParam( MCH_MP.STARTPOS, MACHININGS[i].Machining.dStartPos) + end + if MACHININGS[i].Machining.dReturnPos then + EgtSetMachiningParam( MCH_MP.RETURNPOS, MACHININGS[i].Machining.dReturnPos) + end + + if MACHININGS[i].Machining.dRadialOffset then + EgtSetMachiningParam( MCH_MP.OFFSR, MACHININGS[i].Machining.dRadialOffset) + end + if MACHININGS[i].Machining.dLongitudinalOffset then + EgtSetMachiningParam( MCH_MP.OFFSL, MACHININGS[i].Machining.dLongitudinalOffset) + end + + -- paraemtri attacco + if MACHININGS[i].Machining.LeadIn then + if MACHININGS[i].Machining.LeadIn.nType then + EgtSetMachiningParam( MCH_MP.LEADINTYPE, MACHININGS[i].Machining.LeadIn.nType) + end + if MACHININGS[i].Machining.LeadIn.dStartAddLength then + EgtSetMachiningParam( MCH_MP.STARTADDLEN, MACHININGS[i].Machining.LeadIn.dStartAddLength) + end + if MACHININGS[i].Machining.LeadIn.dTangentDistance then + EgtSetMachiningParam( MCH_MP.LITANG, MACHININGS[i].Machining.LeadIn.dTangentDistance) + end + if MACHININGS[i].Machining.LeadIn.dPerpDistance then + EgtSetMachiningParam( MCH_MP.LIPERP, MACHININGS[i].Machining.LeadIn.dPerpDistance) + end + if MACHININGS[i].Machining.LeadIn.dElevation then + EgtSetMachiningParam( MCH_MP.LIELEV, MACHININGS[i].Machining.LeadIn.dElevation) + end + if MACHININGS[i].Machining.LeadIn.dCompLength then + EgtSetMachiningParam( MCH_MP.LICOMPLEN, MACHININGS[i].Machining.LeadIn.dCompLength) + end + end + -- parametri uscita + if MACHININGS[i].Machining.LeadOut then + if MACHININGS[i].Machining.LeadOut.nType then + EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MACHININGS[i].Machining.LeadOut.nType) + end + if MACHININGS[i].Machining.LeadOut.dEndAddLength then + EgtSetMachiningParam( MCH_MP.ENDADDLEN, MACHININGS[i].Machining.LeadOut.dEndAddLength) + end + if MACHININGS[i].Machining.LeadOut.dTangentDistance then + EgtSetMachiningParam( MCH_MP.LOTANG, MACHININGS[i].Machining.LeadOut.dTangentDistance) + end + if MACHININGS[i].Machining.LeadOut.dPerpDistance then + EgtSetMachiningParam( MCH_MP.LOPERP, MACHININGS[i].Machining.LeadOut.dPerpDistance) + end + if MACHININGS[i].Machining.LeadOut.dElevation then + EgtSetMachiningParam( MCH_MP.LOELEV, MACHININGS[i].Machining.LeadOut.dElevation) + end + if MACHININGS[i].Machining.LeadOut.dCompLength then + EgtSetMachiningParam( MCH_MP.LOCOMPLEN, MACHININGS[i].Machining.LeadOut.dCompLength) + end + end + + if MACHININGS[i].Machining.dStartSlowLen then + EgtSetMachiningParam( MCH_MP.STARTSLOWLEN, MACHININGS[i].Machining.dStartSlowLen) + end + if MACHININGS[i].Machining.dEndSlowLen then + EgtSetMachiningParam( MCH_MP.ENDSLOWLEN, MACHININGS[i].Machining.dEndSlowLen) + end + if MACHININGS[i].Machining.dThrouAddLen then + EgtSetMachiningParam( MCH_MP.THROUADDLEN, MACHININGS[i].Machining.dThrouAddLen) + end + + -- parametri da settare nelle note di sistema + -- TODO da decidere quali sono le note da salvare qui. Probabilmente tutte quelle relative all'ordine delle lavorazioni + local sSystemNotes = EgtGetMachiningParam( MCH_MP.SYSNOTES) + --if MACHININGS[i].Machining.nMachiningOrder then + -- sSystemNotes = EgtSetValInNotes( sSystemNotes, 'MachiningOrder', MACHININGS[i].Machining.nMachiningOrder) + --end + EgtSetMachiningParam( MCH_MP.SYSNOTES, sSystemNotes) + + -- parametri da settare nelle note utente + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) + if MACHININGS[i].Machining.dMaxElev then + sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', MACHININGS[i].Machining.dMaxElev) + end + EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) + + local bIsApplyOk = MachiningLib.ApplyMachining( true, false) + if not bIsApplyOk then + bAreAllMachiningApplyOk = false + nErr, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nOperationId, false) + end + else + return false, 'UNEXPECTED ERROR: Error on creating machining' + end + + end + return bAreAllMachiningApplyOk, sErr +end + +------------------------------------------------------------------------------------------------------------- +function MachiningLib.ApplyMachining( bRecalc, bApplyPost) + local bResult = EgtApplyMachining( bRecalc, bApplyPost) + return bResult +end + +------------------------------------------------------------------------------------------------------------- +return MachiningLib diff --git a/CAMAuto/LuaLibs/WinExec.lua b/CAMAuto/LuaLibs/WinExec.lua index b975612..c79d716 100644 --- a/CAMAuto/LuaLibs/WinExec.lua +++ b/CAMAuto/LuaLibs/WinExec.lua @@ -9,6 +9,9 @@ require( 'EgtBase') -- Carico i dati globali local WinData = require( 'WinData') +local WinLib = require( 'WinLib') +local ID = require( 'Identity') +local FeatureData = require( 'FeatureData') EgtOutLog( ' WinExec started', 1) EgtMdbSave() @@ -17,7 +20,6 @@ EgtMdbSave() -- *** variabili globali *** ------------------------------------------------------------------------------------------------------------- TOOLS = nil -STRATEGIES = nil MACHININGS = nil ------------------------------------------------------------------------------------------------------------- @@ -183,81 +185,11 @@ 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[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) @@ -265,65 +197,40 @@ local function CollectFeatures( Part) 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 sType = EgtGetInfo( ProcId, 'FEATURE_TYPE', 's') local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1 - if nGrp and nPrc and nDo == 1 then + if sType 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.sType = sType Proc.b3Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) - EgtOutLog( '------Feature ' .. Proc.idFeature .. '------') + Proc.nPhase = EgtGetInfo( ProcId, 'PHASE', 'i') or nil + -- 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 + -- calcolo dati specifici per tipologia di feature / lavorazione + -- se foro 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) + Proc = 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' + -- se taglio + if ID.IsCutting( Proc) then 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') + -- se fresatura + if ID.IsMilling( Proc) then end + -- se svuotatura + if ID.IsPocketing( Proc) then + end + -- se profilatura + if ID.IsProfiling( Proc) then + Proc = FeatureData.GetProfilingData( Proc) + end + + -- inserisco feature in lista + table.insert( vProc, Proc) else Proc.nFlg = 0 table.insert( vProc, Proc) @@ -338,152 +245,30 @@ local function CollectFeatures( Part) end ------------------------------------------------------------------------------------------------------------- -local function GetFeatureInfoAndDependency( vProcSingleRot, Part) +local function GetFeatureInfoAndDependency( vProc, Part) -- ciclo tutte le feature - for i = 1, #vProcSingleRot do - local Proc = vProcSingleRot[i] + for i = 1, #vProc do + local Proc = vProc[i] -- controllo la feature con tutte le altre per recuperare le dipendenze - for j = 1, #vProcSingleRot do + for j = 1, #vProc 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 + local ProcB = vProc[j] 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 + return vProc 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) +-- 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 @@ -494,31 +279,10 @@ local function OrderFeatures( vProc) -- 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 + elseif B1.nPhase and B2.nPhase and B1.nPhase < B2.nPhase 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 + elseif B1.nPhase and B2.nPhase and B2.nPhase < B1.nPhase 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 @@ -551,23 +315,10 @@ local function OrderFeatures( vProc) 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 +-- applica le lavorazioni +local function AddMachinings( Proc, Part) + -- TODO applicare lavorazioni!! + return Proc end ------------------------------------------------------------------------------------------------------------- @@ -575,16 +326,7 @@ 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 + local sOut = string.format( 'Id=%3d Flg=%2d Type=%s', Proc.id, Proc.nFlg, Proc.sType) EgtOutLog( sOut) end end @@ -598,109 +340,29 @@ function WinExec.ProcessFeatures( PARTS) 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 = {} + + -- recupero le feature di lavorazione della trave + vProc = CollectFeatures( PARTS[nPart]) - --- 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) + -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse + vProc = GetFeatureInfoAndDependency( vProc, PARTS[nPart]) -- 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( ' *** AddMachinings ***', 1) + for i = 1, #vProc do + -- aggiunge le lavorazioni + AddMachinings( vProc[i], PARTS[nPart]) + end EgtOutLog( ' *** End AddMachinings ***', 1) -- passo al grezzo successivo @@ -710,29 +372,9 @@ 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 + table.insert( Stats, {nErr = 1, sMsg=sApplErrors}) end return ( nTotErr == 0), Stats diff --git a/CAMAuto/LuaLibs/WinLib.lua b/CAMAuto/LuaLibs/WinLib.lua index 17a21f1..04b370e 100644 --- a/CAMAuto/LuaLibs/WinLib.lua +++ b/CAMAuto/LuaLibs/WinLib.lua @@ -10,6 +10,20 @@ local WinData = require( 'WinData') EgtOutLog( ' WinLib started', 1) +------------------------------------------------------------------------------------------------------------- +function WinLib.GetAddGroup( PartId) + -- recupero il nome del gruppo di lavoro corrente + local sMchGrp = EgtGetMachGroupName( EgtGetCurrMachGroup() or GDB_ID.NULL) + if not sMchGrp then + return nil, nil + end + + -- cerco il gruppo aggiuntivo omonimo nel pezzo e se esiste lo restituisco + local AddGrpId = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, sMchGrp) + + -- restituisco Id e Nome + return AddGrpId, sMchGrp +end ------------------------------------------------------------------------------------------------------------- return WinLib \ No newline at end of file diff --git a/CAMAuto/ProcessWin.lua b/CAMAuto/ProcessWin.lua index 4a4eb6c..88be58f 100644 --- a/CAMAuto/ProcessWin.lua +++ b/CAMAuto/ProcessWin.lua @@ -40,6 +40,7 @@ EgtOutLog( '*** Window Process Start ***', 1) _G.package.loaded.WinData = nil _G.package.loaded.WinExec = nil _G.package.loaded.WinLib = nil +_G.package.loaded.FeatureData = nil -- TODO controllare se c'è un modo migliore per resettare librerie delle strategie caricate precedentemente -- Per ottimizzare potremmo anche ciclare solo fino al numero di strategie raggiunto per il momento. @@ -212,7 +213,33 @@ local function CreateRaws( PARTS) EgtAddPartToRawPart( PARTS[i].id, ORIG(), PARTS[i].idRaw) end end - + +--------------------------------------------------------------------- +-- Allinea i pezzi in base a come devono essere disposti sulla tavola +--------------------------------------------------------------------- +-- TODO in questa fase bisogna già sapere qual è la prima fase e posizionare il pezzo di conseguenza +-- TODO (bassa priorità) adesso allinea sempre in X, ma bisognerebbe farlo in base ad un parametro in WINDATA che dice come si dispongono in macchina +local function AlignRawsToTable( PARTS) + for i = 1, #PARTS do + -- allineo il pezzo all'interno del grezzo + local dRotX, dRotY, dRotZ = GetFixedAxesRotABCFromFrame( PARTS[i].frame) + + -- se devo ruotare + if dRotZ ~= 0 then + EgtRotatePartInRawPart( PARTS[i].id, Z_AX(), -dRotZ) + -- sposto punto in basso a sinistra del pezzo sul punto in basso a sinistra del grezzo + local dPartPosX = EgtGetBBoxGlob( PARTS[i].id, GDB_BB.STANDARD):getMin():getX() + local dPartPosY = EgtGetBBoxGlob( PARTS[i].id, GDB_BB.STANDARD):getMin():getY() + local dRawPosX = EgtGetRawPartBBox( PARTS[i].idRaw):getMin():getX() + local dRawPosY = EgtGetRawPartBBox( PARTS[i].idRaw):getMin():getY() + local vtMove = Vector3d( dRawPosX - dPartPosX, dRawPosY - dPartPosY, 0) + EgtMovePartInRawPart( PARTS[i].id, vtMove) + end + + end + return true +end + ------------------------------------------------------------------------------------------------------------- -- *** Funzione per trovare nome MachGroup *** ------------------------------------------------------------------------------------------------------------- @@ -244,7 +271,7 @@ local function MyProcessPieces() CreateRaws( PARTS) -- allineo i pezzi come orientamento richiesto dalla macchina - WinData.AlignRawsToTable( PARTS) + AlignRawsToTable( PARTS) -- aggiungo sovramateriale ai grezzi AddOverMaterialToRaw( PARTS) @@ -267,7 +294,7 @@ local function MyProcessPieces() end -- si dispongono i pezzi sulla tavola - WinData.Disposition( PARTS) + WinData.ExecDisposition( PARTS) return true end @@ -276,7 +303,7 @@ end -- *** Inserimento delle lavorazioni *** ------------------------------------------------------------------------------------------------------------- local function MyProcessFeatures() - --local bOk = WinExec.ProcessFeatures( PARTS) + local bOk = WinExec.ProcessFeatures( PARTS) return true end diff --git a/CAMAuto/Strategies/Cutting.lua b/CAMAuto/Strategies/Cutting.lua new file mode 100644 index 0000000..9e6ac0b --- /dev/null +++ b/CAMAuto/Strategies/Cutting.lua @@ -0,0 +1,17 @@ +-- Cutting.lua by Egalware s.r.l. 2024/06/13 +-- Libreria esecuzione lavorazioni per Serramenti -> Lavorazione di taglio + +-- Tabella per definizione modulo +local Cutting = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local WinData = require( 'WinData') + +EgtOutLog( ' Cutting started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +return Cutting \ No newline at end of file diff --git a/CAMAuto/Strategies/Drillin.lua b/CAMAuto/Strategies/Drillin.lua new file mode 100644 index 0000000..6e0ed03 --- /dev/null +++ b/CAMAuto/Strategies/Drillin.lua @@ -0,0 +1,17 @@ +-- Drilling.lua by Egalware s.r.l. 2024/06/13 +-- Libreria esecuzione lavorazioni per Serramenti -> Lavorazione di foratura + +-- Tabella per definizione modulo +local Drilling = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local WinData = require( 'WinData') + +EgtOutLog( ' Drilling started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +return Drilling \ No newline at end of file diff --git a/CAMAuto/Strategies/Milling.lua b/CAMAuto/Strategies/Milling.lua new file mode 100644 index 0000000..cb06794 --- /dev/null +++ b/CAMAuto/Strategies/Milling.lua @@ -0,0 +1,17 @@ +-- Milling.lua by Egalware s.r.l. 2024/06/13 +-- Libreria esecuzione lavorazioni per Serramenti -> Lavorazione di fresatura + +-- Tabella per definizione modulo +local Milling = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local WinData = require( 'WinData') + +EgtOutLog( ' Milling started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +return Milling \ No newline at end of file diff --git a/CAMAuto/Strategies/Pocketing.lua b/CAMAuto/Strategies/Pocketing.lua new file mode 100644 index 0000000..944794d --- /dev/null +++ b/CAMAuto/Strategies/Pocketing.lua @@ -0,0 +1,17 @@ +-- Pocketing.lua by Egalware s.r.l. 2024/06/13 +-- Libreria esecuzione lavorazioni per Serramenti -> Lavorazione di svuotatura + +-- Tabella per definizione modulo +local Pocketing = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local WinData = require( 'WinData') + +EgtOutLog( ' Pocketing started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +return Pocketing \ No newline at end of file diff --git a/CAMAuto/Strategies/Profiling.lua b/CAMAuto/Strategies/Profiling.lua new file mode 100644 index 0000000..268cce1 --- /dev/null +++ b/CAMAuto/Strategies/Profiling.lua @@ -0,0 +1,38 @@ +-- Profiling.lua by Egalware s.r.l. 2024/06/13 +-- Libreria esecuzione lavorazioni per Serramenti -> Lavorazione di profilatura + +-- Tabella per definizione modulo +local Profiling = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local WinData = require( 'WinData') + +EgtOutLog( ' Profiling started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +function Profiling.Make( Proc, Part) + local Machining = {} + Machining.LeadIn = {} + Machining.LeadOut = {} + Machining.Steps = {} + + Machining.sDepth = 0 + Machining.dRadialOffset = Proc.dRadialOffset + Machining.dLongitudinalOffset = Proc.dLongitudinalOffset + Machining.Steps.dSideStep = TOOLS[nIndexTool].dSideStep + + Machining.LeadIn.nType = MCH_MILL_LI.TANGENT + Machining.LeadIn.dTangentDistance = TOOLS[nIndexTool].dDiameter + Machining.LeadIn.dPerpDistance = TOOLS[nIndexTool].dDiameter + Machining.LeadOut.nType = MCH_MILL_LI.TANGENT + Machining.LeadOut.dTangentDistance = TOOLS[nIndexTool].dDiameter + Machining.LeadOut.dPerpDistance = 0 + +end + +------------------------------------------------------------------------------------------------------------- +return Profiling \ No newline at end of file