-- 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( Proc, ToolSearchParameters) local ToolInfo = {} if not ToolSearchParameters.dTolerance then ToolSearchParameters.dTolerance = 0 end local nBestToolIndex for i = 1, #TOOLS do local bIsToolCompatible = false -- TODO per il momento si cercano solo le punte. Bisognerebbe valutare anche frese che possono lavorare di testa if TOOLS[i].sFamily == 'DRILLBIT' then bIsToolCompatible = true end if bIsToolCompatible then --TODO per il momento si prende il primo utensile con lo stesso diametro, senza considerare altri parametri tipo lunghezza ecc... if abs( TOOLS[i].dDiameter - ToolSearchParameters.dDiameter) < ToolSearchParameters.dTolerance + GEO.EPS_SMALL * 10 then if not nBestToolIndex then nBestToolIndex = i break end end end end ToolInfo.nToolIndex = nBestToolIndex return ToolInfo end ------------------------------------------------------------------------------------------------------------- -- funzione che ritorna fase di lavoro function MachiningLib.GetPhaseMach( Proc) local nPhase -- se info già calcolata if Proc.nPhase and Proc.nPhase ~= 0 then nPhase = Proc.nPhase -- altrimenti si calcola il comportamento standard else -- se macchina tipo LINEA if WinData.MACH_TYPE == 'LINE' then if Proc.AffectedFaces.bTop then nPhase = 1 end if Proc.AffectedFaces.bFront or Proc.AffectedFaces.bLeft then nPhase = EgtIf( WinData.FIRST_PHASE_LOAD == 'PUSH', 1, 2) end if Proc.AffectedFaces.bBack or Proc.AffectedFaces.bRight then nPhase = EgtIf( WinData.FIRST_PHASE_LOAD == 'PUSH', 2, 1) end -- se macchina tipo PANTOGRAFO else if Proc.AffectedFaces.bTop or Proc.AffectedFaces.bLeft or Proc.AffectedFaces.bRight then nPhase = 1 end if Proc.AffectedFaces.bFront then nPhase = EgtIf( WinData.FIRST_PHASE_LOAD == 'PUSH', 1, 2) end if Proc.AffectedFaces.bBack then nPhase = EgtIf( WinData.FIRST_PHASE_LOAD == 'PUSH', 2, 1) end end end return nPhase end ------------------------------------------------------------------------------------------------------------- -- funzione che ritorna la distanza di sicurezza da aggiungere alla lavorazione di foratura per evitare colisioni in rapido function MachiningLib.GetDrillAdditionalSafeDistanceToRaw( Proc, Part, Machining) -- se non è foro esco subito if Proc.sType ~= 'Hole' then return 0 end local bVirtualToolOk = EgtCAvSetStdTool( TOOLS[Machining.nToolIndex].dLength, TOOLS[Machining.nToolIndex].dDiameter, 0) local dStartSafetyLength = EgtCAvToolPosBox( Proc.ptCentre, Proc.vtDir, Part.b3RawPart, Proc.vtDir) -- si riporta valore calcolato sulla punta utensile dStartSafetyLength = dStartSafetyLength - TOOLS[Machining.nToolIndex].dLength return dStartSafetyLength + 5 -- si aggiungono 5mm di sicurezza extra end ------------------------------------------------------------------------------------------------------------- -- salva in lista globale la lavorazione appena calcolata function MachiningLib.AddNewMachining( ProcToAdd, MachiningToAdd, AuxiliaryDataToAdd) -- 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.AuxiliaryData = AuxiliaryDataToAdd table.insert( MACHININGS, Machining) return true end ------------------------------------------------------------------------------------------------------------- -- funzione per aggiungere una nuova lavorazione function MachiningLib.AddOperation( OperationToInsert) local nErr local sErr = '' local bAreAllMachiningApplyOk = true -- parametri generali lavorazione local MachiningParameters = { { sName = 'sDepth', nMchParam = MCH_MP.DEPTH_STR}, { sName = 'bInvert', nMchParam = MCH_MP.INVERT}, { sName = 'nWorkside', nMchParam = MCH_MP.WORKSIDE}, { sName = 'nFaceuse', nMchParam = MCH_MP.FACEUSE}, { sName = 'nSCC', nMchParam = MCH_MP.SCC}, { sName = 'bToolInvert', nMchParam = MCH_MP.TOOLINVERT}, { sName = 'sBlockedAxis', nMchParam = MCH_MP.BLOCKEDAXIS}, { sName = 'sInitialAngles', nMchParam = MCH_MP.INITANGS}, { sName = 'nHeadSide', nMchParam = MCH_MP.HEADSIDE}, { sName = 'nSubType', nMchParam = MCH_MP.SUBTYPE}, { sName = 'dOverlap', nMchParam = MCH_MP.OVERL}, { sName = 'nStepType', nMchParam = MCH_MP.STEPTYPE}, { sName = 'dStartSafetyLength', nMchParam = MCH_MP.STARTPOS}, { sName = 'dReturnPos', nMchParam = MCH_MP.RETURNPOS}, { sName = 'dRadialOffset', nMchParam = MCH_MP.OFFSR}, { sName = 'dLongitudinalOffset', nMchParam = MCH_MP.OFFSL}, { sName = 'dStartSlowLen', nMchParam = MCH_MP.STARTSLOWLEN}, { sName = 'dEndSlowLen', nMchParam = MCH_MP.ENDSLOWLEN}, { sName = 'dThrouAddLen', nMchParam = MCH_MP.THROUADDLEN}, { sName = 'sSystemNotes', nMchParam = MCH_MP.SYSNOTES}, { sName = 'sUserNotes', nMchParam = MCH_MP.USERNOTES} } -- parametri relativi allo step MachiningParameters.Steps = { { sName = 'nStepType', nMchParam = MCH_MP.STEPTYPE}, { sName = 'dStep', nMchParam = MCH_MP.STEP}, { sName = 'dSideStep', nMchParam = MCH_MP.SIDESTEP} } -- parametri relativi all'approccio MachiningParameters.LeadIn = { { sName = 'nType', nMchParam = MCH_MP.LEADINTYPE}, { sName = 'dStartAddLength', nMchParam = MCH_MP.STARTADDLEN}, { sName = 'dTangentDistance', nMchParam = MCH_MP.LITANG}, { sName = 'dPerpDistance', nMchParam = MCH_MP.LIPERP}, { sName = 'dElevation', nMchParam = MCH_MP.LIELEV}, { sName = 'dCompLength', nMchParam = MCH_MP.LICOMPLEN} } -- parametri relativi alla retrazione MachiningParameters.LeadOut = { { sName = 'nType', nMchParam = MCH_MP.LEADOUTTYPE}, { sName = 'dEndAddLength', nMchParam = MCH_MP.ENDADDLEN}, { sName = 'dTangentDistance', nMchParam = MCH_MP.LOTANG}, { sName = 'dPerpDistance', nMchParam = MCH_MP.LOPERP}, { sName = 'dElevation', nMchParam = MCH_MP.LOELEV}, { sName = 'dCompLength', nMchParam = MCH_MP.LOCOMPLEN} } -- parametri da scrivere nelle note utente local UserNotes = { { sName = 'dMaxElev', sMchParam = 'MaxElev'} } -- parametri da scrivere nelle note di sistema local SystemNotes = { } local nClonesToAdd = 1 if OperationToInsert.AuxiliaryData.Clones then nClonesToAdd = #OperationToInsert.AuxiliaryData.Clones end for j = 1, nClonesToAdd do -- creazione lavorazione local nOperationId = EgtCreateMachining( OperationToInsert.Machining.sOperationName, OperationToInsert.Machining.nType, OperationToInsert.Machining.sToolName) if nOperationId then -- impostazione geometria EgtSetMachiningGeometry( OperationToInsert.Machining.Geometry) -- impostazione parametri lavorazione -- TODO scrivere sempre Steps, LeadIn, LeadOut nelle tabelle in modo da non dover controllare ogni volta che ci siano for k = 1, #MachiningParameters do local sValue if OperationToInsert.AuxiliaryData.Clones and OperationToInsert.AuxiliaryData.Clones[j][MachiningParameters[k].sName] then sValue = OperationToInsert.AuxiliaryData.Clones[j][MachiningParameters[k].sName] elseif OperationToInsert.Machining[MachiningParameters[k].sName] then sValue = OperationToInsert.Machining[MachiningParameters[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters[k].nMchParam, sValue) end end for k = 1, #MachiningParameters.Steps do local sValue if OperationToInsert.AuxiliaryData.Clones and OperationToInsert.AuxiliaryData.Clones[j].Steps and OperationToInsert.AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName] then sValue = OperationToInsert.AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName] elseif OperationToInsert.Machining.Steps and OperationToInsert.Machining.Steps[MachiningParameters.Steps[k].sName] then sValue = OperationToInsert.Machining.Steps[MachiningParameters.Steps[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters.Steps[k].nMchParam, sValue) end end for k = 1, #MachiningParameters.LeadIn do local sValue if OperationToInsert.AuxiliaryData.Clones and OperationToInsert.AuxiliaryData.Clones[j].LeadIn and OperationToInsert.AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName] then sValue = OperationToInsert.AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName] elseif OperationToInsert.Machining.LeadIn and OperationToInsert.Machining.LeadIn[MachiningParameters.LeadIn[k].sName] then sValue = OperationToInsert.Machining.LeadIn[MachiningParameters.LeadIn[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters.LeadIn[k].nMchParam, sValue) end end for k = 1, #MachiningParameters.LeadOut do local sValue if OperationToInsert.AuxiliaryData.Clones and OperationToInsert.AuxiliaryData.Clones[j].LeadOut and OperationToInsert.AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName] then sValue = OperationToInsert.AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName] elseif OperationToInsert.Machining.LeadOut and OperationToInsert.Machining.LeadOut[MachiningParameters.LeadOut[k].sName] then sValue = OperationToInsert.Machining.LeadOut[MachiningParameters.LeadOut[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters.LeadOut[k].nMchParam, sValue) end end for k = 1, #UserNotes do local sValue if OperationToInsert.AuxiliaryData.Clones and OperationToInsert.AuxiliaryData.Clones[j][UserNotes[k].sName] then sValue = OperationToInsert.AuxiliaryData.Clones[j][UserNotes[k].sName] elseif OperationToInsert.Machining[UserNotes[k].sName] then sValue = OperationToInsert.Machining[UserNotes[k].sName] end if sValue then local sUserNotes = '' sUserNotes = EgtSetValInNotes( sUserNotes, UserNotes[k].sMchParam, sValue) EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) end 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 --if OperationToInsert.Machining.nMachiningOrder then -- sSystemNotes = EgtSetValInNotes( sSystemNotes, 'MachiningOrder', OperationToInsert.Machining.nMachiningOrder) --end for k = 1, #SystemNotes do local sValue if OperationToInsert.AuxiliaryData.Clones and OperationToInsert.AuxiliaryData.Clones[j][SystemNotes[k].sName] then sValue = OperationToInsert.AuxiliaryData.Clones[j][SystemNotes[k].sName] elseif OperationToInsert.Machining[SystemNotes[k].sName] then sValue = OperationToInsert.Machining[SystemNotes[k].sName] end if sValue then local sSystemNotes = '' sSystemNotes = EgtSetValInNotes( sSystemNotes, SystemNotes[k].sMchParam, sValue) EgtSetMachiningParam( MCH_MP.SYSNOTES, sSystemNotes) end end 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 if ptMin and ptMax then local dToolRadius = TOOLS[OperationToInsert.Machining.nToolIndex].dTotDiameter / 2 if dToolRadius then ptMin = ptMin - Vector3d( dToolRadius, 0, 0) ptMax = ptMax + Vector3d( dToolRadius, 0, 0) end end b3MachEncumbrance = BBox3d( ptMin, ptMax) end return bIsApplyOk, sErr, b3MachEncumbrance else return false, 'UNEXPECTED ERROR: Error on creating machining' end end end ------------------------------------------------------------------------------------------------------------- function MachiningLib.ApplyMachining( bRecalc, bApplyPost) local bResult = EgtApplyMachining( bRecalc, bApplyPost) return bResult end ------------------------------------------------------------------------------------------------------------- return MachiningLib