diff --git a/.vscode/settings.json b/.vscode/settings.json index 9ed05cd..f1ae223 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -109,11 +109,33 @@ "EgtReplaceString", "EgtCircle", "EgtArc2PV", + "EgtTdbSetCurrTool", "EgtSurfTmSubtract", "EgtSurfTmIntersect", "GDB_IN", "GEO", - "dist" + "dist", + "EgtSetMachiningParam", + "EgtCreateMachining", + "EgtSetMachiningGeometry", + "EgtGetMachiningParam", + "EgtGetLastMachMgrError", + "EgtSetOperationMode", + "EgtApplyMachining", + "EgtSetCurrPhase", + "EgtApplyAllMachinings", + "EgtGetDebugLevel", + "EgtTdbGetCurrToolParam", + "EgtTdbGetCurrToolThDiam", + "EgtTdbGetCurrToolMaxDepth", + "EgtTdbGetCurrToolThLength", + "EgtFindToolInCurrSetup", + "EgtTdbGetFirstTool", + "EgtTdbGetNextTool", + "EgtMdbSave", + "EgtMoveRawPart", + "EgtCurveThickness", + "EgtSetCurrMachining" ], "Lua.diagnostics.disable": [ "empty-block" diff --git a/CAMAuto/LuaLibs/FeatureData.lua b/CAMAuto/LuaLibs/FeatureData.lua new file mode 100644 index 0000000..3c831a2 --- /dev/null +++ b/CAMAuto/LuaLibs/FeatureData.lua @@ -0,0 +1,67 @@ +-- 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 taglio +function FeatureData.GetCuttingData( Proc) + + return Proc +end + +------------------------------------------------------------------------------------------------------------- +-- Recupero dati foro +function FeatureData.GetPocketingData( Proc) + + return Proc +end + +------------------------------------------------------------------------------------------------------------- +-- Recupero dati foro +function FeatureData.GetMillingData( Proc) + + return Proc +end + +------------------------------------------------------------------------------------------------------------- +-- Recupero dati profilatura +function FeatureData.GetProfilingData( Proc) + -- recupero utensili + Proc.nToolsToUse = EgtGetInfo( Proc.id, 'NTOOLS', 'i') or 0 + Proc.sEntityName = EgtGetInfo( Proc.id, 'N', 's') or nil + Proc.bHeadProfile = Proc.sEntityName == 'Left' or Proc.sEntityName == 'Right' + Proc.bSideProfile = Proc.sEntityName == 'In' or Proc.sEntityName == 'Out' + Proc.Tools = {} + for t = 1, Proc.nToolsToUse do + local Data = {} + Data.sName = EgtGetInfo( Proc.id, 'TOOL_NAME_' .. tostring(t), 's') or 0 + Data.dRadialOffset = EgtGetInfo( Proc.id, 'OFFR_' .. tostring(t), 'd') or 0 + Data.dLongitudinalOffset = EgtGetInfo( Proc.id, 'OFFL_' .. tostring(t), 'd') 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..5437b11 --- /dev/null +++ b/CAMAuto/LuaLibs/Identity.lua @@ -0,0 +1,50 @@ +-- 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 + +--------------------------------------------------------------------- +----------------------------- PIECES ------------------------------ +--------------------------------------------------------------------- +function Identity.GetPieceIndexPart( PARTS, idGeom) + local nIndexPart + for i = 1, #PARTS do + if PARTS[i].id == idGeom then + nIndexPart = i + break + end + end + return nIndexPart +end + +--------------------------------------------------------------------- +return Identity diff --git a/CAMAuto/LuaLibs/MachiningLib.lua b/CAMAuto/LuaLibs/MachiningLib.lua new file mode 100644 index 0000000..133519d --- /dev/null +++ b/CAMAuto/LuaLibs/MachiningLib.lua @@ -0,0 +1,360 @@ +-- 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 WinData = require( 'WinData') +local ID = require( 'Identity') + +EgtOutLog( ' MachiningLib started', 1) + + ------------------------------------------------------------------------------------------------------------- +-- 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 + local dCurrentMaxMatReduction = WinData.COLL_SIC or 5 + + -- 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 + +------------------------------------------------------------------------------------------------------------- +-- funzione che ritorna fase di lavoro +function MachiningLib.GetPhaseMach( Proc) + local nPhase + -- se info già calcolata + if Proc.nPhase then + nPhase = Proc.nPhase + -- altrimenti si calcola il comportamento standard + else + if Proc.sEntityName == 'Left' or Proc.sEntityName == 'Out' then + nPhase = 1 + end + if Proc.sEntityName == 'Right' or Proc.sEntityName == 'In' then + nPhase = 2 + end + end + return nPhase +end + +------------------------------------------------------------------------------------------------------------- +-- salva in lista globale la lavorazione appena calcolata +function MachiningLib.AddNewMachining( ProcToAdd, MachiningToAdd, AuxInfoToAdd) + -- 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)) -- TODO serve scrivere faccia? -->> .. '_' .. 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 + Machining.AuxInfo = AuxInfoToAdd + table.insert( MACHININGS, Machining) + return true +end + +------------------------------------------------------------------------------------------------------------- +-- funzione per aggiungere una nuova lavorazione +function MachiningLib.AddOperation( OperationToInsert) + local nErr + local sErr = '' + local bAreAllMachiningApplyOk = true + + -- creazione lavorazione + local nOperationId = EgtCreateMachining( OperationToInsert.Machining.sOperationName, OperationToInsert.Machining.nType, OperationToInsert.Machining.sToolName) + EgtSetCurrMachining( nOperationId) + + if nOperationId then + -- impostazione geometria + EgtSetMachiningGeometry( OperationToInsert.Machining.Geometry) + + -- impostazione parametri lavorazione + if OperationToInsert.Machining.sDepth then + EgtSetMachiningParam( MCH_MP.DEPTH_STR, OperationToInsert.Machining.sDepth) + end + if OperationToInsert.Machining.bInvert then + EgtSetMachiningParam( MCH_MP.INVERT, OperationToInsert.Machining.bInvert) + end + if OperationToInsert.Machining.nWorkSide then + EgtSetMachiningParam( MCH_MP.WORKSIDE, OperationToInsert.Machining.nWorkSide) + end + if OperationToInsert.Machining.nFaceuse then + EgtSetMachiningParam( MCH_MP.FACEUSE, OperationToInsert.Machining.nFaceuse) + end + if OperationToInsert.Machining.nSCC then + EgtSetMachiningParam( MCH_MP.SCC, OperationToInsert.Machining.nSCC) + end + if OperationToInsert.Machining.bToolInvert then + EgtSetMachiningParam( MCH_MP.TOOLINVERT, OperationToInsert.Machining.bToolInvert) + end + if OperationToInsert.Machining.sBlockedAxis then + EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, OperationToInsert.Machining.sBlockedAxis) + end + if OperationToInsert.Machining.sInitialAngles then + EgtSetMachiningParam( MCH_MP.INITANGS, OperationToInsert.Machining.sInitialAngles) + end + if OperationToInsert.Machining.nHeadSide then + EgtSetMachiningParam( MCH_MP.HEADSIDE, OperationToInsert.Machining.nHeadSide) + end + if OperationToInsert.Machining.nSubType then + EgtSetMachiningParam( MCH_MP.SUBTYPE, OperationToInsert.Machining.nSubType) + end + if OperationToInsert.Machining.dOverlap then + EgtSetMachiningParam( MCH_MP.OVERL, OperationToInsert.Machining.dOverlap) + end + + -- step + if OperationToInsert.Machining.Steps then + if OperationToInsert.Machining.Steps.dStepType then + EgtSetMachiningParam( MCH_MP.STEPTYPE, OperationToInsert.Machining.Steps.dStepType) + end + if OperationToInsert.Machining.Steps.dStep then + EgtSetMachiningParam( MCH_MP.STEP, OperationToInsert.Machining.Steps.dStep) + end + if OperationToInsert.Machining.Steps.dSideStep then + EgtSetMachiningParam( MCH_MP.SIDESTEP, OperationToInsert.Machining.Steps.dSideStep) + end + end + + if OperationToInsert.Machining.dStartPos then + EgtSetMachiningParam( MCH_MP.STARTPOS, OperationToInsert.Machining.dStartPos) + end + if OperationToInsert.Machining.dReturnPos then + EgtSetMachiningParam( MCH_MP.RETURNPOS, OperationToInsert.Machining.dReturnPos) + end + + if OperationToInsert.Machining.dRadialOffset then + EgtSetMachiningParam( MCH_MP.OFFSR, OperationToInsert.Machining.dRadialOffset) + end + if OperationToInsert.Machining.dLongitudinalOffset then + EgtSetMachiningParam( MCH_MP.OFFSL, OperationToInsert.Machining.dLongitudinalOffset) + end + + -- paraemtri attacco + if OperationToInsert.Machining.LeadIn then + if OperationToInsert.Machining.LeadIn.nType then + EgtSetMachiningParam( MCH_MP.LEADINTYPE, OperationToInsert.Machining.LeadIn.nType) + end + if OperationToInsert.Machining.LeadIn.dStartAddLength then + EgtSetMachiningParam( MCH_MP.STARTADDLEN, OperationToInsert.Machining.LeadIn.dStartAddLength) + end + if OperationToInsert.Machining.LeadIn.dTangentDistance then + EgtSetMachiningParam( MCH_MP.LITANG, OperationToInsert.Machining.LeadIn.dTangentDistance) + end + if OperationToInsert.Machining.LeadIn.dPerpDistance then + EgtSetMachiningParam( MCH_MP.LIPERP, OperationToInsert.Machining.LeadIn.dPerpDistance) + end + if OperationToInsert.Machining.LeadIn.dElevation then + EgtSetMachiningParam( MCH_MP.LIELEV, OperationToInsert.Machining.LeadIn.dElevation) + end + if OperationToInsert.Machining.LeadIn.dCompLength then + EgtSetMachiningParam( MCH_MP.LICOMPLEN, OperationToInsert.Machining.LeadIn.dCompLength) + end + end + -- parametri uscita + if OperationToInsert.Machining.LeadOut then + if OperationToInsert.Machining.LeadOut.nType then + EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, OperationToInsert.Machining.LeadOut.nType) + end + if OperationToInsert.Machining.LeadOut.dEndAddLength then + EgtSetMachiningParam( MCH_MP.ENDADDLEN, OperationToInsert.Machining.LeadOut.dEndAddLength) + end + if OperationToInsert.Machining.LeadOut.dTangentDistance then + EgtSetMachiningParam( MCH_MP.LOTANG, OperationToInsert.Machining.LeadOut.dTangentDistance) + end + if OperationToInsert.Machining.LeadOut.dPerpDistance then + EgtSetMachiningParam( MCH_MP.LOPERP, OperationToInsert.Machining.LeadOut.dPerpDistance) + end + if OperationToInsert.Machining.LeadOut.dElevation then + EgtSetMachiningParam( MCH_MP.LOELEV, OperationToInsert.Machining.LeadOut.dElevation) + end + if OperationToInsert.Machining.LeadOut.dCompLength then + EgtSetMachiningParam( MCH_MP.LOCOMPLEN, OperationToInsert.Machining.LeadOut.dCompLength) + end + end + + if OperationToInsert.Machining.dStartSlowLen then + EgtSetMachiningParam( MCH_MP.STARTSLOWLEN, OperationToInsert.Machining.dStartSlowLen) + end + if OperationToInsert.Machining.dEndSlowLen then + EgtSetMachiningParam( MCH_MP.ENDSLOWLEN, OperationToInsert.Machining.dEndSlowLen) + end + if OperationToInsert.Machining.dThrouAddLen then + EgtSetMachiningParam( MCH_MP.THROUADDLEN, OperationToInsert.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 OperationToInsert.Machining.nMachiningOrder then + -- sSystemNotes = EgtSetValInNotes( sSystemNotes, 'MachiningOrder', OperationToInsert.Machining.nMachiningOrder) + --end + EgtSetMachiningParam( MCH_MP.SYSNOTES, sSystemNotes) + + -- parametri da settare nelle note utente + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) + if OperationToInsert.Machining.dMaxElev then + sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', OperationToInsert.Machining.dMaxElev) + end + EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) + + local b3MachEncumbrance = nil + local bIsApplyOk = MachiningLib.ApplyMachining( true, false) + if not bIsApplyOk then + bAreAllMachiningApplyOk = false + nErr, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nOperationId, false) + else + local nClId = EgtGetFirstNameInGroup( nOperationId, 'CL') + local ptMin = EgtGetInfo( nClId, 'MMIN', 'p') + local ptMax = EgtGetInfo( nClId, 'MMAX', 'p') + -- box percorso lavorazione + b3MachEncumbrance = BBox3d( ptMin, ptMax) + end + + return bIsApplyOk, sErr, b3MachEncumbrance + else + return false, 'UNEXPECTED ERROR: Error on creating machining' + end +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 new file mode 100644 index 0000000..786f8c8 --- /dev/null +++ b/CAMAuto/LuaLibs/WinExec.lua @@ -0,0 +1,482 @@ +-- WinExec.lua by Egalware s.r.l. 2024/06/13 +-- Libreria esecuzione lavorazioni per Serramenti + +-- Tabella per definizione modulo +local WinExec = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local WinData = require( 'WinData') +local WinLib = require( 'WinLib') +local ID = require( 'Identity') +local FeatureData = require( 'FeatureData') +local MachiningLib = require( 'MachiningLib') + +-- carico librerie di lavorazione +_G.package.loaded.Drilling = nil +_G.package.loaded.Cutting = nil +_G.package.loaded.Pocketing = nil +_G.package.loaded.Milling = nil +_G.package.loaded.Profiling = nil +local Drilling = require( 'Drilling') +local Cutting = require( 'Cutting') +local Pocketing = require( 'Pocketing') +local Milling = require( 'Milling') +local Profiling = require( 'Profiling') + + +EgtOutLog( ' WinExec started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +-- *** variabili globali *** +------------------------------------------------------------------------------------------------------------- +TOOLS = nil +MACHININGS = nil + +------------------------------------------------------------------------------------------------------------- +-- *** COSTANTI *** TODO -> DA SPOSTARE IN WINDATA??? +------------------------------------------------------------------------------------------------------------- +TH_DIAMETER_HSK63 = 63 +TH_LENGTH_HSK63 = 75 +SIDEANGLE_DOVETAIL = 15 + +------------------------------------------------------------------------------------------------------------- +-- *** funzioni di base *** +------------------------------------------------------------------------------------------------------------- +local function GetToolTypeNameFromToolTypeID( dToolTypeID) + if dToolTypeID == MCH_TY.DRILL_STD then + return 'DRILL_STD', 'DRILLBIT' + elseif dToolTypeID == MCH_TY.DRILL_LONG then + return 'DRILL_LONG', 'DRILLBIT' + elseif dToolTypeID == MCH_TY.SAW_STD then + return 'SAW_STD', 'SAWBLADE' + elseif dToolTypeID == MCH_TY.SAW_FLAT then + return 'SAW_FLAT', 'SAWBLADE' + elseif dToolTypeID == MCH_TY.MILL_STD then + return 'MILL_STD', 'MILL' + elseif dToolTypeID == MCH_TY.MILL_NOTIP then + return 'MILL_NOTIP', 'MILL' + elseif dToolTypeID == MCH_TY.MORTISE_STD then + return 'MORTISE_STD', 'MORTISE' + else + return nil + end +end + +------------------------------------------------------------------------------------------------------------- +local function IsToolOk( Tool) + -- controllo che i dati necessari siano impostati + if Tool.dMaxMaterial and Tool.dDiameter and Tool.dLength and Tool.sHead and Tool.sUUID then + -- se DRILLBIT non ho altri dati + if Tool.sFamily == 'DRILLBIT' then + return true + -- altrimenti controllo dati aggiuntivi altre famiglie di utensili + elseif Tool.sFamily == 'MORTISE' then + if Tool.dCornerRadius then + return true + end + else + if Tool.dThickness then + return true + end + end + end + + return false +end + +------------------------------------------------------------------------------------------------------------- +function WinExec.GetToolsFromDB() + +-- TODO gli utensili profilati devono essere messi in una lista a parte ad accesso diretto TOOLS['Prof1'] in modo da non dover scorrere la lista +-- dato che saranno molti e l'applicazione sarà diretta. Non serve ciclarli + + + -- creo lista globale utensili disponibili + TOOLS = {} + -- lista appoggio utensile + local Tool = {} + + -- recupero tutti gli utensili : punte a forare, lame, frese e motoseghe + Tool.sName = EgtTdbGetFirstTool( MCH_TF.DRILLBIT + MCH_TF.SAWBLADE + MCH_TF.MILL + MCH_TF.MORTISE) + while Tool.sName ~= '' do + -- imposto utensile come corrente per recuperarne i dati + EgtTdbSetCurrTool( Tool.sName) + + -- verifico se utensile disponibile in attrezzaggio attuale e che abbia un tipo ben definito + local bToolLoadedOnSetup, sToolTCPos = EgtFindToolInCurrSetup( Tool.sName) + local nToolTypeId = EgtTdbGetCurrToolParam( MCH_TP.TYPE) + local sToolType, sToolFamily = GetToolTypeNameFromToolTypeID( nToolTypeId) + + -- se verifica condizioni minime, recupero tutti gli altri dati + if bToolLoadedOnSetup and sToolType then + -- TODO Tool.AName -> da rimuovere perchè non serve. Per il momento lo manteniamo solo perchè è più facile vedere e interpretare la lista utensili nella watch di zerobrane + -- Nell'utilizzo, si legge sempre il Tool.Name + Tool.AName = Tool.sName + Tool.sTcPos = sToolTCPos + Tool.sFamily = sToolFamily + Tool.sType = sToolType + Tool.nTypeId = nToolTypeId + Tool.dMaxMaterial = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) + Tool.dDiameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM) + Tool.dLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) + Tool.dSpeed = EgtTdbGetCurrToolParam( MCH_TP.SPEED) + Tool.bIsCCW = Tool.dSpeed < 0 + Tool.Feeds = {} + Tool.Feeds.dFeed = EgtTdbGetCurrToolParam( MCH_TP.FEED) + Tool.Feeds.dStartFeed = EgtTdbGetCurrToolParam( MCH_TP.STARTFEED) + Tool.Feeds.dEndFeed = EgtTdbGetCurrToolParam( MCH_TP.ENDFEED) + Tool.Feeds.dTipFeed = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) + -- TODO serve funzione in WinData che data la posizione dell'utensile e della testa, capisca il montaggio (testa sopra - testa sotto - aggregato - ecc...) + Tool.sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) + Tool.SetupInfo = {} + Tool.SetupInfo = WinData.GetSetupInfo( Tool.sHead) + Tool.sUUID = EgtTdbGetCurrToolParam( MCH_TP.UUID) + Tool.sUserNotes = EgtTdbGetCurrToolParam( MCH_TP.USERNOTES) + Tool.dMaxDepth = EgtTdbGetCurrToolMaxDepth() or Tool.dMaxMaterial + Tool.ToolHolder = {} + Tool.ToolHolder.dDiameter = EgtTdbGetCurrToolThDiam() or TH_DIAMETER_HSK63 -- diametro standard HSK63 + Tool.ToolHolder.dLength = EgtTdbGetCurrToolThLength() or TH_LENGTH_HSK63 -- lunghezza standard HSK63 + -- parametri scritti nelle note + Tool.nDouble = EgtGetValInNotes( Tool.sUserNotes, 'DOUBLE') + + -- lettura parametri non comuni ( famiglia DRILLBIT non ha parametri specifici) + if sToolFamily ~= 'DRILLBIT' then + Tool.dThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK) + Tool.dLongitudinalOffset = EgtTdbGetCurrToolParam( MCH_TP.LONOFFSET) + Tool.dRadialOffset = EgtTdbGetCurrToolParam( MCH_TP.RADOFFSET) + -- recupero parametri propri delle frese + if sToolFamily == 'MILL' then + Tool.dStemDiameter = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or Tool.ToolHolder.dDiameter -- se non settato, considero diametro come ToolHolder + Tool.dSideAngle = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or 0 + -- verifico che parametri siano compatibili con una fresa a coda di rondine ( angolo di fianco standard Coda di rondine -> 15°) + Tool.bIsDoveTail = Tool.Type == 'MILL_NOTIP' and abs( abs( Tool.dSideAngle) - SIDEANGLE_DOVETAIL) < 1 + -- verifico che sia una fresa tipo T-Mill o BlockHaus + Tool.dSideDepth = EgtGetValInNotes( Tool.sUserNotes, 'SIDEDEPTH') or 0 -- se non settato nell'utensile, dico che non ha massimo affondamento laterale + Tool.bIsTMill = Tool.dSideDepth > 0 + Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP') or ( Tool.dMaxMaterial / 3) -- se non settato nell'utensile, considero metà del tagliente + Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP') or floor( Tool.dDiameter / 3) -- se non settato nell'utensile, considero metà del diametro + Tool.bIsPen = abs( Tool.dSpeed) < 5 + -- recupero parametri propri delle lame + elseif sToolFamily == 'SAWBLADE' then + Tool.bIsUsedForLongCut = EgtGetValInNotes( Tool.sUserNotes, 'LONGCUT') == 1 or false -- false coem valore di default + Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP') or Tool.dThickness -- se non settato nell'utensile, considero lo spessore lama + Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP') or Tool.dMaxMaterial -- se non settato nell'utensile, considero un quarto del diametro + -- recupero parametri propri delle motoseghe + elseif sToolFamily == 'MORTISE' then + Tool.dDistance = EgtTdbGetCurrToolParam( MCH_TP.DIST) or 90 -- 90mm dimensione standard aggregato catena + Tool.bIsMortise = EgtGetValInNotes( Tool.sUserNotes, 'MORTISE') == 1 + Tool.bIsChainSaw = not Tool.bIsMortise + Tool.dStep = EgtGetValInNotes( Tool.sUserNotes, 'STEP') or floor( Tool.dMaxMaterial / 3) -- se non settato nell'utensile, considero un terzo della lunghezza + Tool.dSideStep = EgtGetValInNotes( Tool.sUserNotes, 'SIDESTEP') or ( Tool.dThickness - 1) -- se non settato nell'utensile, considero spessore catena meno 1mm di sicurezza + Tool.dCornerRadius = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) + Tool.dWidth = Tool.dDiameter + end + end + + -- se tutti i dati necessari sono disponibili, inserisco utensile nella lista globale degli utensili disponibili + if IsToolOk( Tool) then + table.insert( TOOLS, Tool) + -- altrimenti scrivo nel log che l'utensile non è conforme + else + EgtOutLog( '*** ' .. Tool.sName .. ' : NOT-COMPLIANT ***', 1) + end + + -- reset dati + Tool = {} + end + + -- recupero utensile successivo ( punte a forare, lame, frese e motoseghe) + Tool.sName = EgtTdbGetNextTool( MCH_TF.DRILLBIT + MCH_TF.SAWBLADE + MCH_TF.MILL + MCH_TF.MORTISE) + end +end + + +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle lavorazioni nelle travi *** +------------------------------------------------------------------------------------------------------------- + +local function CollectFeatures( vProc, Part) + -- recupero le feature + local LayerId = {} + LayerId[1] = WinLib.GetAddGroup( Part.id) + LayerId[2] = EgtGetFirstNameInGroup( Part.id or GDB_ID.NULL, 'Processings') + for nInd = 1, 2 do + local ProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL) + while ProcId do + local nEntType = EgtGetType( ProcId) + if nEntType == GDB_TY.SRF_MESH or nEntType == GDB_TY.EXT_TEXT or + nEntType == GDB_TY.CRV_LINE or nEntType == GDB_TY.CRV_ARC or nEntType == GDB_TY.CRV_BEZ or nEntType == GDB_TY.CRV_COMPO then + local sType = EgtGetInfo( ProcId, 'FEATURE_TYPE', 's') + local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1 + if sType and nDo == 1 then + local Proc = {} + Proc.idPart = Part.id + Proc.id = ProcId + Proc.nFlg = 1 + Proc.sType = sType + Proc.b3Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) + Proc.nPhase = EgtGetInfo( ProcId, 'PHASE', 'i') or nil + -- informazioni facce + Proc.AffectedFaces = WinLib.GetAffectedFaces( Proc, Part) + + -- se esiste la geometria + if Proc.b3Box and not Proc.b3Box:isEmpty() then + -- calcolo dati specifici per tipologia di feature / lavorazione + -- se foro + if ID.IsDrilling( Proc) then + Proc = FeatureData.GetDrillingData( Proc) + end + -- se taglio + if ID.IsCutting( Proc) then + Proc = FeatureData.GetCuttingData( Proc) + end + -- se fresatura + if ID.IsMilling( Proc) then + Proc = FeatureData.GetMillingData( Proc) + end + -- se svuotatura + if ID.IsPocketing( Proc) then + Proc = FeatureData.GetPocketingData( Proc) + end + -- se profilatura + if ID.IsProfiling( Proc) then + Proc = FeatureData.GetProfilingData( Proc) + end + + -- inserisco feature in lista + table.insert( vProc, Proc) + else + Proc.nFlg = 0 + table.insert( vProc, Proc) + EgtOutLog( ' Feature ' .. tostring( Proc.idFeature) .. ' is empty (no geometry)') + end + end + end + ProcId = EgtGetNext( ProcId) + end + end + return vProc +end + +------------------------------------------------------------------------------------------------------------- +local function GetFeatureInfoAndDependency( vProc, Part) + -- ciclo tutte le feature + for i = 1, #vProc do + local Proc = vProc[i] + -- controllo la feature con tutte le altre per recuperare le dipendenze + for j = 1, #vProc do + -- non si controlla la feature con se stessa + if i ~= j then + local ProcB = vProc[j] + -- TODO dipendenze da controllare : + -- * gruppo di forature con aggregato 2/3 uscite + -- * Se 'Left' e 'Out' hanno stesso profilo, vanno concatenati (anche 'Right' se consentito dalle dimensioni) + end + end + end + return vProc +end + +------------------------------------------------------------------------------------------------------------- +-- Ordina le feature in base a fase di lavorazione +-- L'ordine è indicativamente: +-- 1) Tagli di testa +-- 2) Fori +-- 3) Scassi serratura/maniglia +-- 4) Profili testa +-- 5) Profili longitudinali +-- 6) Incontri/scontri +-- TODO Ordinamento da fare + +local function OrderMachining( MACHININGS) + + + -- local vProcToSort = vProc + -- -- funzione di confronto. TRUE = B1 prima di B2. FALSE = B2 prima di B1 + -- local function CompareFeatures( B1, B2) + -- -- se secondo disabilitato, va lasciato dopo + -- if B1.nFlg ~= 0 and B2.nFlg == 0 then + -- return true + -- elseif B1.nPhase and B2.nPhase and B1.nPhase < B2.nPhase then + -- return true + -- elseif B1.nPhase and B2.nPhase and B2.nPhase < B1.nPhase then + -- return true + -- -- altrimenti si inverte + -- else + -- return false + -- end + -- end + + -- -- test della funzione di ordinamento + -- if EgtGetDebugLevel() >= 3 then + -- EgtOutLog( ' CompareFeatures Test ') + -- local bCompTest = true + -- for i = 1, #vProcToSort do + -- for j = i + 1, #vProcToSort do + -- local bComp1 = CompareFeatures( vProcToSort[i], vProcToSort[j]) + -- local bComp2 = CompareFeatures( vProcToSort[j], vProcToSort[i]) + -- if bComp1 == bComp2 then + -- bCompTest = false + -- EgtOutLog( string.format( ' ProcId : %d vs %d --> ERROR', vProcToSort[i].id, vProcToSort[j].id)) + -- end + -- end + -- end + -- if bCompTest then + -- EgtOutLog( ' ALL OK') + -- end + -- end + + -- -- eseguo ordinamento + -- table.sort( vProcToSort, CompareFeatures) + + return true +end + +------------------------------------------------------------------------------------------------------------- +-- applica le lavorazioni +local function AddMachinings( vProc, PARTS) + local bMachiningOk = true + for nFeatureIndex = 1, #vProc do + local Proc = vProc[nFeatureIndex] + local Part = PARTS[vProc[nFeatureIndex].nIndexPiece] + if ID.IsDrilling( Proc) then + bMachiningOk = Drilling.Make( Proc, Part) + end + -- se taglio + if ID.IsCutting( Proc) then + bMachiningOk = Cutting.Make( Proc, Part) + end + -- se fresatura + if ID.IsMilling( Proc) then + bMachiningOk = Milling.Make( Proc, Part) + end + -- se svuotatura + if ID.IsPocketing( Proc) then + bMachiningOk = Pocketing.Make( Proc, Part) + end + -- se profilatura + if ID.IsProfiling( Proc) then + bMachiningOk = Profiling.Make( Proc, Part) + end + end + return bMachiningOk +end + +------------------------------------------------------------------------------------------------------------- +local function PrintFeatures( vProc, PARTS) + EgtOutLog( ' === PARTS ====') + for i = 1, #PARTS do + EgtOutLog( ' RawBox(' .. tostring( i) .. ') =' .. tostring( PARTS[i].RawBox)) + end + EgtOutLog( ' === FEATURES ====') + for i = 1, #vProc do + local Proc = vProc[i] + local sOut = string.format( 'Id=%3d Flg=%2d Type=%s', Proc.id, Proc.nFlg, Proc.sType) + EgtOutLog( sOut) + end +end + +------------------------------------------------------------------------------------------------------------- +local function CheckAndMovePawPart( nIdRawToMove, vtMove) + EgtMoveRawPart( nIdRawToMove, vtMove) +end + +------------------------------------------------------------------------------------------------------------- +function WinExec.ProcessFeatures( PARTS) + -- ciclo sui pezzi + local nTotErr = 0 + local Stats = {} + local vProc = {} + MACHININGS = {} + + -- si recuperano tutte le feature di tutti i pezzi in una lista unica + for nPart = 1, #PARTS do + -- recupero le feature di lavorazione della trave + vProc = CollectFeatures( vProc, PARTS[nPart]) + + -- recupero informazioni ausiliarie feature e dipendenze tra feature dello stesso pezzo + vProc = GetFeatureInfoAndDependency( vProc, PARTS[nPart]) + end + + -- debug + if EgtGetDebugLevel() >= 1 then + PrintFeatures( vProc, PARTS) + end + + EgtOutLog( ' *** AddMachinings ***', 1) + + -- esegue le lavorazioni e le salva in lista + AddMachinings( vProc, PARTS) + + -- ordina le lavorazioni + OrderMachining( MACHININGS) + + -- scrivo lavorazioni prima fase + EgtSetCurrPhase( 1) + for i = 1, #MACHININGS do + if MACHININGS[i].AuxInfo.nPhase == 1 then + -- aggiunge effettivamente la lavorazione e restituisce gli ingombri + local bIsApplyOk, sErr, b3MachEncumbrance = MachiningLib.AddOperation( MACHININGS[i]) -- TODO ingombro lavorazione mi restituisce dati sbagliati. C'è un riferimento? + -- se feature di testa, sposto testa in base a ingombro lavorazione + if MACHININGS[i].Proc.bHeadProfile and b3MachEncumbrance then + local nIndexPart = ID.GetPieceIndexPart( PARTS, MACHININGS[i].Proc.idPart) + PARTS[nIndexPart].DispOffsets.Phase1.dOffsetX = b3MachEncumbrance:getMax():getX() - PARTS[nIndexPart].b3FinishedPart:getMin():getX() + 5 + end + end + end + + -- TODO lo spostamento, oltre a controllare le collisioni con il profilo di testa, deve anche considerare il pinzaggio del pezzo nel suo insieme? + -- Es.: basterebbe aggiungere un offset di 50mm per la testa, ma se metto 60mm, posso utilizzare una morsa in più che altrimenti avrei dovuto togliere per una collisione con una svuotatura + + -- sposto pezzo per permettere pinzaggio migliore e non aver colisione in testa + for i = 1, #PARTS do + -- TODO Sbaglia a calcolare ingombro!! + --local vtMove = Vector3d( - PARTS[nIndexPart].DispOffsets.Phase1.dOffsetX, - PARTS[nIndexPart].DispOffsets.Phase1.dOffsetY, PARTS[nIndexPart].DispOffsets.Phase1.dOffsetZ) + local vtMove = Vector3d( -60, 0, 0) + if vtMove ~= V_NULL() then + CheckAndMovePawPart( PARTS[i].idRaw, vtMove) + end + end + + -- scrivo lavorazioni seconda fase + EgtSetCurrPhase( 2) + for i = 1, #MACHININGS do + if MACHININGS[i].AuxInfo.nPhase == 2 then + -- aggiunge effettivamente la lavorazione + local bIsApplyOk, sErr, b3MachEncumbrance = MachiningLib.AddOperation( MACHININGS[i]) -- TODO ingombro lavorazione mi restituisce dati sbagliati. C'è un riferimento? + -- se feature di testa, sposto testa in base a ingombro lavorazione + if MACHININGS[i].Proc.bHeadProfile and b3MachEncumbrance then + local nIndexPart = ID.GetPieceIndexPart( PARTS, MACHININGS[i].Proc.idPart) + PARTS[nIndexPart].DispOffsets.Phase1.dOffsetX = PARTS[nIndexPart].b3FinishedPart:getMax():getX() - b3MachEncumbrance:getMin():getX() + 5 + end + end + end + -- sposto pezzo per permettere pinzaggio migliore e non aver colisione in testa + for i = 1, #PARTS do + -- TODO Sbaglia a calcolare ingombro!! + -- local vtMove = Vector3d( PARTS[nIndexPart].DispOffsets.Phase2.dOffsetX, PARTS[nIndexPart].DispOffsets.Phase2.dOffsetY, PARTS[nIndexPart].DispOffsets.Phase2.dOffsetZ) + local vtMove = Vector3d( 60, 0, 0) + if vtMove ~= V_NULL() then + CheckAndMovePawPart( PARTS[i].idRaw, vtMove) + end + end + + EgtOutLog( ' *** End AddMachinings ***', 1) + + -- Aggiornamento finale di tutto + EgtSetCurrPhase( 1) + local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings() + if not bApplOk then + nTotErr = nTotErr + 1 + table.insert( Stats, {nErr = 1, sMsg=sApplErrors}) + end + + return ( nTotErr == 0), Stats +end + +------------------------------------------------------------------------------------------------------------- +return WinExec diff --git a/CAMAuto/LuaLibs/WinLib.lua b/CAMAuto/LuaLibs/WinLib.lua new file mode 100644 index 0000000..6957512 --- /dev/null +++ b/CAMAuto/LuaLibs/WinLib.lua @@ -0,0 +1,57 @@ +-- WinLib.lua by Egalware s.r.l. 2024/06/14 +-- Libreria globale per Serramenti + +-- Tabella per definizione modulo +local WinLib = {} + +-- Include +require( 'EgtBase') +local WinData = require( 'WinData') + +EgtOutLog( ' WinLib started', 1) + +------------------------------------------------------------------------------------------------------------- +-- restituisce le facce della parte interessate dalla feature Proc +function WinLib.GetAffectedFaces( Proc, Part) + local vtFacesAffected = { bTop = false, bBottom = false, bFront = false, bBack = false, bLeft = false, bRight = false} + if Proc.b3Box and not Proc.b3Box:isEmpty() then + if Proc.b3Box:getMax():getZ() > Part.b3Solid:getMax():getZ() - 500 * GEO.EPS_SMALL then + vtFacesAffected.bTop = true + end + if Proc.b3Box:getMin():getZ() < Part.b3Solid:getMin():getZ() + 500 * GEO.EPS_SMALL then + vtFacesAffected.bBottom = true + end + if Proc.b3Box:getMin():getY() < Part.b3Solid:getMin():getY() + 500 * GEO.EPS_SMALL then + vtFacesAffected.bFront = true + end + if Proc.b3Box:getMax():getY() > Part.b3Solid:getMax():getY() - 500 * GEO.EPS_SMALL then + vtFacesAffected.bBack = true + end + if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + 500 * GEO.EPS_SMALL then + vtFacesAffected.bLeft = true + end + if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - 500 * GEO.EPS_SMALL then + vtFacesAffected.bRight = true + end + end + + return vtFacesAffected +end + +------------------------------------------------------------------------------------------------------------- +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 new file mode 100644 index 0000000..848e826 --- /dev/null +++ b/CAMAuto/ProcessWin.lua @@ -0,0 +1,321 @@ +-- Process.lua by Egalware s.r.l. 2024/06/13 +-- Gestione calcolo disposizione e lavorazioni per serramenti +-- Si opera sulla macchina corrente +-- 2024/06/13 PRIMA VERSIONE + + +-- Intestazioni +require( 'EgtBase') +_ENV = EgtProtectGlobal() +EgtEnableDebug( true) + +-- TODO da cancellare quando verrà passato automaticamente da programma +local WIN = {} +WIN.BASEDIR = 'C:\\EgtData\\EgwWindowLua\\CAMAuto' + +-- Imposto direttorio libreria specializzata per serramenti +EgtAddToPackagePath( WIN.BASEDIR .. '\\LuaLibs\\?.lua') +-- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre +EgtAddToPackagePath( WIN.BASEDIR .. '\\Strategies\\?.lua') + +-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi +local sMachDir = EgtGetCurrMachineDir() +if not sMachDir then + EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Serramenti', 'ERROR') + return +end +if not EgtExistsFile( sMachDir .. '\\Window\\WinData.lua') then + EgtOutBox( 'La macchina corrente non è configurata per lavorare serramenti', 'Lavora Serramenti', 'ERROR') + return +end + +-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie +EgtRemoveBaseMachineDirFromPackagePath() +EgtAddToPackagePath( sMachDir .. '\\Window\\?.lua') + +-- Segnalazione avvio +EgtOutLog( '*** Window Process Start ***', 1) + +-- Carico le librerie +_G.package.loaded.WinData = nil +_G.package.loaded.WinExec = nil +_G.package.loaded.WinLib = nil +_G.package.loaded.FeatureData = nil +_G.package.loaded.MachiningLib = nil + +local WinExec = require( 'WinExec') + +-- Carico i dati globali +local WinData = require( 'WinData') + +-- Variabili globali +PARTS = {} + +-- Colore del grezzo +local ColA = Color3d( 255, 165, 0, 30) + +------------------------------------------------------------------------------------------------------------- +-- *** Recupero i pezzi da processare *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessInputData() + -- Recupero le travi selezionate + local nId = EgtGetFirstSelectedObj() + while nId do + local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL) + if nPartId then + local bFound = false + for i = 1, #PARTS do + if PARTS[i].id == nPartId then + bFound = true + break + end + end + if not bFound then + table.insert( PARTS, { nInd = #PARTS + 1, id = nPartId, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) + end + end + nId = EgtGetNextSelectedObj() + end + if #PARTS == 0 then + EgtOutBox( 'Non sono state selezionati pezzi', 'Lavora Pezzi', 'ERROR') + return false + else + -- recupero tutte le dimensioni necessarie + local sOut = '' + for i = 1, #PARTS do + PARTS[i].b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Solid') or GDB_ID.NULL, GDB_BB.STANDARD) + PARTS[i].b3FinishedPart = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo') or GDB_ID.NULL, GDB_BB.STANDARD) + local idFrame = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo'), 'AuxFrame') or EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo'), 'Frame') + PARTS[i].frame = EgtFR( idFrame) + sOut = sOut .. PARTS[i].sName .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Pezzi selezionati : ' .. sOut, 1) + end + + EgtDeselectAll() + + return true +end + +------------------------------------------------------------------------------------------------------------- +local function GetDataConfig() + -- recupero utensili dal magazzino + WinExec.GetToolsFromDB() + + -- TODO da gestire eventuali errori bloccanti + return true +end + +------------------------------------------------------------------------------------------------------------- +local function UpdateRawPosition( PARTS) + for i = 1, #PARTS do + PARTS[i].b3FinishedPart = EgtGetBBoxGlob( PARTS[i].id or GDB_ID.NULL, GDB_BB.STANDARD) + PARTS[i].b3RawPart = EgtGetBBoxGlob( PARTS[i].idRaw or GDB_ID.NULL, GDB_BB.STANDARD) + end +end + +------------------------------------------------------------------------------------------------------------- +local function GetDispOffsetFromNotes( nPieceIndex) + local bAllOffsetsAreOk = false + + PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetX = 0 -- dovrà essere calcolato in base alle lavorazioni + PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFY_1', 'd') + PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFZ_1', 'd') + PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetX = 0 -- dovrà essere calcolato in base alle lavorazioni + PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFY_2', 'd') + PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFZ_2', 'd') + + -- controllo se tutti gli offset siano settati + if PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY and PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ and + PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY and PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ then + bAllOffsetsAreOk = true + end + + return bAllOffsetsAreOk +end + +------------------------------------------------------------------------------------------------------------- +local function GetDispOffsetFromInput( nPieceIndex) + -- assegno alle stringhe i valori letti, in modo che vengano proposti quelli nel dialogo + local sOffYPh1 = EgtIf( PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY, tostring( PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY), tostring( PARTS[nPieceIndex].dPartWidth / 2)) + local sOffZPh1 = EgtIf( PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ, tostring( PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ), '0') + local sOffYPh2 = EgtIf( PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY, tostring( PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY), tostring( PARTS[nPieceIndex].dPartWidth / 2)) + local sOffZPh2 = EgtIf( PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ, tostring( PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ), '0') + + 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 + return false + end + + -- salvo input nei valori che utilizzerò dopo + PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY = tonumber( vInp[1]) + PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ = tonumber( vInp[2]) + PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY = tonumber( vInp[3]) + PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ = tonumber( vInp[4]) + + return true +end + +--------------------------------------------------------------------- +-- Crea il grezzo che verrà messo in macchina +--------------------------------------------------------------------- +local function AddOverMaterialToRaw( PARTS) + for i = 1, #PARTS do + + -- prima di aggiungere sovramateriale al grezzo, calcolo dimensioni del finito + local b3FinishedPart = EgtGetBBoxGlob( PARTS[i].id or GDB_ID.NULL, GDB_BB.STANDARD) + PARTS[i].b3FinishedPart = b3FinishedPart + PARTS[i].dPartLength = PARTS[i].b3FinishedPart:getDimX() + PARTS[i].dPartWidth = PARTS[i].b3FinishedPart:getDimY() + PARTS[i].dPartHeight = PARTS[i].b3FinishedPart:getDimZ() + + -- recupero e aggiungo offset + PARTS[i].RawOffset = {} + -- recupero info sovramateriale + 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 + + PARTS[i].dRawLength = PARTS[i].RawOffset.dOverMatLeft + PARTS[i].dPartLength + PARTS[i].RawOffset.dOverMatRight + PARTS[i].dRawWidth = PARTS[i].RawOffset.dOverMatOut + PARTS[i].dPartWidth + PARTS[i].RawOffset.dOverMatIn + PARTS[i].dRawHeight = PARTS[i].dPartHeight + + EgtModifyRawPartSize( PARTS[i].idRaw, PARTS[i].dRawLength, PARTS[i].dRawWidth, PARTS[i].dPartHeight) + + local vtMove = Vector3d( PARTS[i].RawOffset.dOverMatLeft, PARTS[i].RawOffset.dOverMatOut, 0) + EgtMovePartInRawPart( PARTS[i].id, vtMove) + + -- TODO da controllare, se ruotato di 180° bisognerebbe prendere dOverMatIn. Lo stesso per la X + PARTS[i].OffsetPartToRaw = {} + PARTS[i].OffsetPartToRaw.X = PARTS[i].RawOffset.dOverMatLeft + PARTS[i].OffsetPartToRaw.Y = PARTS[i].RawOffset.dOverMatOut + end +end + +--------------------------------------------------------------------- +-- Crea il grezzo che verrà messo in macchina +--------------------------------------------------------------------- +local function CreateRaws( PARTS) + for i = 1, #PARTS do + -- si crea un grezzo "finto" (un cubo da 100mm) nell'origine del pezzo, verrà poi dimensionato uan volta adeguato con i vari sovramateriali + PARTS[i].idRaw = EgtAddRawPart( PARTS[i].frame:getOrigin(), 100, 100, 100, ColA) + 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 *** +------------------------------------------------------------------------------------------------------------- +local function NewMachGroupName() +local nMachGroupId = EgtGetFirstMachGroup() + if not nMachGroupId then return 1 end + local nMaxMachGroup = 0 + while nMachGroupId do + local sMachGroupName = EgtGetMachGroupName(nMachGroupId) + local nMachGroupName = tonumber(sMachGroupName) + if nMachGroupName > nMaxMachGroup then + nMaxMachGroup = nMachGroupName + end + nMachGroupId = EgtGetNextMachGroup(nMachGroupId) + end + return nMaxMachGroup + 1 +end + +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle travi nel grezzo *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessPieces() + + -- creo macchinata + local MachGroupName = NewMachGroupName() + local nMachGroup = EgtAddMachGroup( MachGroupName) + + -- si crea il grezzo + CreateRaws( PARTS) + + -- allineo i pezzi come orientamento richiesto dalla macchina + AlignRawsToTable( PARTS) + + -- aggiungo sovramateriale ai grezzi + AddOverMaterialToRaw( PARTS) + + -- recupero offset per posizionamento + for i = 1, #PARTS do + PARTS[i].DispOffsets = {} + PARTS[i].DispOffsets.Phase1 = {} + PARTS[i].DispOffsets.Phase2 = {} + + local bInsertedAllOffs = GetDispOffsetFromNotes( i) + -- se non sono settati nelle note, li chiedo + if not bInsertedAllOffs then + bInsertedAllOffs = GetDispOffsetFromInput( i) + end + -- se non sono stati inseriti o c'è stato un errore esco subito + if not bInsertedAllOffs then + return false + end + end + + -- si dispongono i pezzi sulla tavola + WinData.ExecDisposition( PARTS) + UpdateRawPosition( PARTS) + + -- Impostazione dell'attrezzaggio di default + -- TODO se lascio il campo vuoto non mi carica il default!!!!!!! + local bOk = EgtImportSetup( 'CIAO') + + return true +end + +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle lavorazioni *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessFeatures() + local bOk = WinExec.ProcessFeatures( PARTS) + + return true +end + +------------------------------------------------------------------------------------------------------------- +-- *** Esecuzione *** +------------------------------------------------------------------------------------------------------------- +if not MyProcessInputData() then return end + +if not MyProcessPieces() then return end + +if not GetDataConfig() then return end + +-- Abilito Vmill +EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1') + +if not MyProcessFeatures() then return end diff --git a/CAMAuto/Strategies/Cutting.lua b/CAMAuto/Strategies/Cutting.lua new file mode 100644 index 0000000..ceb4d3d --- /dev/null +++ b/CAMAuto/Strategies/Cutting.lua @@ -0,0 +1,22 @@ +-- 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() + +------------------------------------------------------------------------------------------------------------- +function Cutting.Make( Proc, Part) + return true +end + +------------------------------------------------------------------------------------------------------------- +return Cutting \ No newline at end of file diff --git a/CAMAuto/Strategies/Drilling.lua b/CAMAuto/Strategies/Drilling.lua new file mode 100644 index 0000000..8aaf024 --- /dev/null +++ b/CAMAuto/Strategies/Drilling.lua @@ -0,0 +1,22 @@ +-- 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() + +------------------------------------------------------------------------------------------------------------- +function Drilling.Make( Proc, Part) + return true +end + +------------------------------------------------------------------------------------------------------------- +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..b1dfe09 --- /dev/null +++ b/CAMAuto/Strategies/Milling.lua @@ -0,0 +1,22 @@ +-- 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() + +------------------------------------------------------------------------------------------------------------- +function Milling.Make( Proc, Part) + return true +end + +------------------------------------------------------------------------------------------------------------- +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..1759916 --- /dev/null +++ b/CAMAuto/Strategies/Pocketing.lua @@ -0,0 +1,22 @@ +-- 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() + +------------------------------------------------------------------------------------------------------------- +function Pocketing.Make( Proc, Part) + return true +end + +------------------------------------------------------------------------------------------------------------- +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..6d913c3 --- /dev/null +++ b/CAMAuto/Strategies/Profiling.lua @@ -0,0 +1,62 @@ +-- 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') +local MachiningLib = require( 'MachiningLib') + +EgtOutLog( ' Profiling started', 1) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +function Profiling.Make( Proc, Part) + local ToolInfo = {} + + -- se so che utensili utilizzare, associazione diretta + if Proc.nToolsToUse then + for i = 1, Proc.nToolsToUse do + local Machining = {} + local AuxInfo = {} + Machining.LeadIn = {} + Machining.LeadOut = {} + Machining.Steps = {} + local ToolSearchParameters = {} + ToolSearchParameters.sName = Proc.Tools[i].sName + ToolSearchParameters.dElevation = 0 + ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) + -- se trovato utensile + if ToolInfo.nToolIndex then + Machining.nType = MCH_MY.MILLING + Machining.nWorkSide = MCH_MILL_WS.RIGHT + Machining.nToolIndex = ToolInfo.nToolIndex + Machining.sDepth = 0 + Machining.dRadialOffset = Proc.Tools[i].dRadialOffset + Machining.dLongitudinalOffset = Proc.Tools[i].dLongitudinalOffset + Machining.LeadIn.nType = MCH_MILL_LI.TANGENT + Machining.LeadIn.dTangentDistance = TOOLS[ToolInfo.nToolIndex].dDiameter + Machining.LeadIn.dPerpDistance = TOOLS[ToolInfo.nToolIndex].dDiameter + Machining.LeadOut.nType = MCH_MILL_LO.TANGENT + Machining.LeadOut.dTangentDistance = TOOLS[ToolInfo.nToolIndex].dDiameter + Machining.LeadOut.dPerpDistance = 0 + Machining.Geometry = Proc.id + AuxInfo.nPhase = MachiningLib.GetPhaseMach( Proc) + MachiningLib.AddNewMachining( Proc, Machining, AuxInfo) + else + return false, 'Tool not found' + end + end + -- altrimenti cerco tra quelli disponibili + else + ; --per il momento non serve. Le info sull'utensile arrivano sempre + end + return true +end + +------------------------------------------------------------------------------------------------------------- +return Profiling \ No newline at end of file