-- Strategia: FACEBYMILL -- Descrizione -- Strategia di base per la lavorazione delle facce con fresa -- carico librerie local BeamLib = require( 'BeamLib') local BeamData = require( 'BeamDataNew') local MachiningLib = require( 'MachiningLib') local PreSimulationLib = require('PreSimulationLib') -- Tabella per definizione modulo local FACEBYMILL = {} ------------------------------------------------------------------------------------------------------------- local function GetLeadInOutType( Machining) local sLeadInOutType = '' if Machining.bIsStartClosed or Machining.bIsEndClosed then sLeadInOutType = 'Perpendicular' else -- testa sopra if TOOLS[Machining.nToolIndex].SetupInfo.HeadType.bTop then if abs( Machining.vtToolDirection:getX()) < 0.7 then if Machining.vtToolDirection:getZ() > -0.087 or abs( Machining.vtToolDirection:getX()) < 0.34202 then sLeadInOutType = 'Perpendicular' else sLeadInOutType = 'Tangent' end elseif abs( Machining.vtEdgeDirection:getZ()) < 0.7 then sLeadInOutType = 'Tangent' else -- TODO qui attacco tangenziale speciale tutto da un lato sLeadInOutType = 'Tangent' end -- testa sotto elseif TOOLS[Machining.nToolIndex].SetupInfo.HeadType.bBottom then if abs( Machining.vtToolDirection:getX()) < 0.7 then if Machining.vtToolDirection:getZ() < -GEO.EPS_SMALL or abs( Machining.vtToolDirection:getX()) < 0.34202 then sLeadInOutType = 'Perpendicular' else sLeadInOutType = 'Tangent' end elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then sLeadInOutType = 'Tangent' else -- TODO qui attacco tangenziale speciale tutto da un lato sLeadInOutType = 'Tangent' end -- se testa senza preferenza Top e Bottom si fa sempre attacco tangenziale else sLeadInOutType = 'Tangent' end end return sLeadInOutType end local function CalculateLeadInOut( Machining, EdgeToMachine, bIsSplitFeature) -- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom) -- si determina l'eventuale riduzione da applicare in caso di inizio o fine chiusi local dAddLengthToReduce = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine) if Machining.bInvert then Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed end local LeadIn = {} local LeadOut = {} Machining.sLeadInOutType = '' LeadIn.dStartAddLength = 0 LeadOut.dEndAddLength = 0 LeadIn.nType = MCH_MILL_LI.LINEAR LeadOut.nType = MCH_MILL_LI.LINEAR LeadIn.dPerpDistance = 0 LeadOut.dPerpDistance = 0 LeadIn.dTangentDistance = 0 LeadOut.dTangentDistance = 0 if Machining.bIsStartClosed or Machining.bIsEndClosed or bIsSplitFeature then Machining.sLeadInOutType = 'Perpendicular' if AreSameVectorApprox( Machining.vtToolDirection, EdgeToMachine.vtN) then LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset else LeadIn.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset LeadOut.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset end else Machining.sLeadInOutType = GetLeadInOutType( Machining) if Machining.sLeadInOutType == 'Perpendicular' then LeadIn.dPerpDistance = 1 LeadOut.dPerpDistance = 1 else LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 end end LeadIn.dElevation = 0 LeadOut.dElevation = 0 LeadIn.dCompLength = 0 LeadOut.dCompLength = 0 if Machining.bIsStartClosed and Machining.bIsEndClosed then LeadIn.dStartAddLength = -dAddLengthToReduce LeadOut.dEndAddLength = -dAddLengthToReduce elseif Machining.bIsStartClosed then LeadIn.dStartAddLength = -dAddLengthToReduce -- eventuale correzione per accorciamento maggiore di larghezza tasca LeadOut.dEndAddLength = max( -LeadIn.dStartAddLength - EdgeToMachine.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA) elseif Machining.bIsEndClosed then LeadOut.dEndAddLength = -dAddLengthToReduce -- eventuale correzione per accorciamento maggiore di larghezza tasca LeadIn.dStartAddLength = max( -LeadOut.dEndAddLength - EdgeToMachine.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA) else LeadIn.dStartAddLength = BeamData.CUT_EXTRA LeadOut.dEndAddLength = BeamData.CUT_EXTRA end -- punti dell'attacco LeadIn.ptPoint = EdgeToMachine.ptStart - EdgeToMachine.vtEdge * ( LeadIn.dStartAddLength + LeadIn.dTangentDistance) + EdgeToMachine.vtN * ( EdgeToMachine.dElevation - Machining.dDepthToMachine + LeadIn.dPerpDistance) LeadOut.ptPoint = EdgeToMachine.ptEnd + EdgeToMachine.vtEdge * ( LeadOut.dEndAddLength + LeadOut.dTangentDistance) + EdgeToMachine.vtN * ( EdgeToMachine.dElevation - Machining.dDepthToMachine + LeadOut.dPerpDistance) -- stima lunghezza reale attacchi per calcolo lunghezza lavorata local dEstimatedLeadInPerpDistance = 0 local dEstimatedLeadInTangentDistance = 0 local dEstimatedLeadOutPerpDistance = 0 local dEstimatedLeadOutTangentDistance = 0 if LeadIn.dPerpDistance > 0 then dEstimatedLeadInPerpDistance = ( Machining.dDepthToMachine + min( TOOLS[Machining.nToolIndex].dSideStep, Machining.dDepthToMachine)) / 2 end if LeadIn.dTangentDistance > 0 then dEstimatedLeadInTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 end if LeadOut.dPerpDistance > 0 then dEstimatedLeadOutPerpDistance = ( Machining.dDepthToMachine + min( TOOLS[Machining.nToolIndex].dSideStep, Machining.dDepthToMachine)) / 2 end if LeadOut.dTangentDistance > 0 then dEstimatedLeadOutTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 end LeadIn.dTotalEstimatedDistance = sqrt( dEstimatedLeadInPerpDistance ^ 2 + dEstimatedLeadInTangentDistance ^ 2) + Machining.dStartSafetyLength LeadOut.dTotalEstimatedDistance = sqrt( dEstimatedLeadOutPerpDistance ^ 2 + dEstimatedLeadOutTangentDistance ^ 2) + Machining.dStartSafetyLength return LeadIn, LeadOut end local function GetSCC( vtMachiningDirection) -- TODO implementare SCC come per FacesBySaw local nSCC = MCH_SCC.NONE if vtMachiningDirection:getZ() < -0.9 then nSCC = MCH_SCC.ADIR_ZM elseif vtMachiningDirection:getZ() > 0.9 then nSCC = MCH_SCC.ADIR_ZP elseif vtMachiningDirection:getY() < -0.707 then nSCC = MCH_SCC.ADIR_YM elseif vtMachiningDirection:getY() > 0.707 then nSCC = MCH_SCC.ADIR_YP elseif vtMachiningDirection:getX() < -0.707 then nSCC = MCH_SCC.ADIR_XM elseif vtMachiningDirection:getX() > 0.707 then nSCC = MCH_SCC.ADIR_XP end return nSCC end -- TODO calcolo area lavorata per completamento function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters) local Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING) Milling.bIsApplicable = true Milling.dDepthToMachine = 0 Milling.sMessage = '' Milling.idProc = Proc.id Milling.dResidualDepth = EdgeToMachine.dElevation Milling.dCompletionPercentage = 0 Milling.dToolMarkLength = 0 Milling.sEdgeType = EdgeToMachine.sType Milling.nFeatureSegment = 1 -- parametri opzionali if not OptionalParameters then OptionalParameters = {} end local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000 local dPocketHeight = OptionalParameters.dPocketHeight or 0 local dDepthToMachine = OptionalParameters.dDepthToMachine or EdgeToMachine.dElevation local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false local OppositeToolDirectionMode = OptionalParameters.OppositeToolDirectionMode or 'Disabled' local sDepth = OptionalParameters.sDepth or 0 local nToolIndex = OptionalParameters.nToolIndex local dLongitudinalOffset = OptionalParameters.dLongitudinalOffset or 0 if OptionalParameters.dPocketHeight then dLongitudinalOffset = 0 end local dRadialStepSpan = OptionalParameters.dRadialStepSpan local dMinNzDownUp = OptionalParameters.dMinNzDownUp local sUserNotes = OptionalParameters.sUserNotes or '' -- lunghezze, direzioni e punti caratteristici della lavorazione e del lato lavorato Milling.dEdgeLength = EdgeToMachine.dLength if OppositeToolDirectionMode == 'Enabled' then Milling.vtToolDirection = -EdgeToMachine.vtN else Milling.vtToolDirection = EdgeToMachine.vtN end Milling.vtEdgeDirection = Vector3d( EdgeToMachine.vtEdge) Milling.ptEdge1, Milling.ptEdge2 = EdgeToMachine.ptStart, EdgeToMachine.ptEnd -- se si conosce il limite downUp (utensile forzato o downUp forzato) si decide se invertire (ToolInvert) if nToolIndex and not dMinNzDownUp then dMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Milling.vtToolDirection, TOOLS[nToolIndex]) end if dMinNzDownUp and FaceToMachine.vtN:getZ() < dMinNzDownUp then Milling.bToolInvert = true else Milling.bToolInvert = false end -- ricerca utensile if nToolIndex then Milling.nToolIndex = nToolIndex else local ToolSearchParameters = {} if OptionalParameters.dPocketHeight then ToolSearchParameters.sMillShape = 'TSHAPEMILL' else ToolSearchParameters.sMillShape = 'STANDARD' end ToolSearchParameters.dElevation = FaceToMachine.dElevation -- TODO qui ToolSearchParameters.vtToolDirection andrà sosituito con vtN!! if Milling.bToolInvert then ToolSearchParameters.vtToolDirection = -FaceToMachine.vtN else ToolSearchParameters.vtToolDirection = FaceToMachine.vtN end ToolSearchParameters.bAllowTopHead = true -- TODO bisognerà implementare anche la lama da sotto ToolSearchParameters.bAllowBottomHead = false local ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) -- ora che l'utensile è scelto, se non era definito l'angolo di DownUp lo verifico per decidere se invertire if ToolInfo.nToolIndex and not dMinNzDownUp then dMinNzDownUp = TOOLS[ToolInfo.nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Milling.vtToolDirection, TOOLS[ToolInfo.nToolIndex]) if FaceToMachine.vtN:getZ() < dMinNzDownUp then Milling.bToolInvert = true end end Milling.nToolIndex = ToolInfo.nToolIndex end if not TOOLS[Milling.nToolIndex] or not TOOLS[Milling.nToolIndex].sName then Milling.sMessage = 'Mill not found' Milling.bIsApplicable = false EgtOutLog( Milling.sMessage) return Milling end -- verifica dimensioni tasca compatibili -- se tasca meno spessa della fresa la lavorazione non è applicabile if OptionalParameters.dPocketHeight and TOOLS[Milling.nToolIndex].dMaxMaterial > dPocketHeight + 10 * GEO.EPS_SMALL then Milling.sMessage = 'Pocket too narrow for blade thickness' Milling.bIsApplicable = false EgtOutLog( Milling.sMessage) return Milling end -- se tasca chiusa da entrambi i lati e più stretta della fresa la lavorazione non è applicabile if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then if TOOLS[Milling.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then Milling.sMessage = 'Pocket too narrow for blade diameter' Milling.bIsApplicable = false EgtOutLog( Milling.sMessage) return Milling end end -- parametri della lavorazione -- profondità (parametro DEPTH) Milling.sDepth = sDepth -- inizio e fine aperti o chiusi Milling.bIsStartClosed = not EdgeToMachine.bIsStartOpen Milling.bIsEndClosed = not EdgeToMachine.bIsEndOpen -- lato di lavoro e inversione if TOOLS[Milling.nToolIndex].bIsCCW then Milling.nWorkside = MCH_MILL_WS.RIGHT Milling.bInvert = true else Milling.nWorkside = MCH_MILL_WS.LEFT Milling.bInvert = false end if OppositeToolDirectionMode == 'Enabled' then Milling.bInvert = not Milling.bInvert end if Milling.bToolInvert then Milling.bInvert = not Milling.bInvert end -- profondità da lavorare e offset radiale if OptionalParameters.dPocketHeight then if TOOLS[Milling.nToolIndex].dSideDepth > dDepthToMachine - 10 * GEO.EPS_SMALL then -- TODO la depth dovrebbe essere quella del machining Milling.dDepthToMachine = dDepthToMachine Milling.dResidualDepth = 0 if OppositeToolDirectionMode == 'Enabled' then Milling.dRadialOffset = -dDepthToMachine else Milling.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine end else Milling.dDepthToMachine = TOOLS[Milling.nToolIndex].dSideDepth - 1 Milling.dResidualDepth = dDepthToMachine - Milling.dDepthToMachine if OppositeToolDirectionMode == 'Enabled' then Milling.dRadialOffset = -Milling.dDepthToMachine else Milling.dRadialOffset = EdgeToMachine.dElevation - Milling.dDepthToMachine end end else Milling.dDepthToMachine = dDepthToMachine Milling.dResidualDepth = 0 if OppositeToolDirectionMode == 'Enabled' then Milling.dRadialOffset = -dDepthToMachine else Milling.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine end end -- completamento Milling.dCompletionPercentage = ( 1 - Milling.dResidualDepth / Milling.dDepthToMachine) * 100 -- step verticale e offset longitudinale if OptionalParameters.dPocketHeight then Milling.Steps = MachiningLib.GetMachiningSteps( true, dPocketHeight, TOOLS[Milling.nToolIndex].dMaxMaterial) Milling.Steps.nStepType = OptionalParameters.nStepType or MCH_MILL_ST.ONEWAY Milling.dMaxElev = Milling.Steps.dStep * Milling.Steps.nCount - 10 * GEO.EPS_SMALL else Milling.Steps = MachiningLib.GetMachiningSteps( false, FaceToMachine.dElevation, TOOLS[Milling.nToolIndex].dStep) Milling.Steps.nStepType = OptionalParameters.nStepType or MCH_MILL_ST.ZIGZAG Milling.dMaxElev = FaceToMachine.dElevation end if Milling.bToolInvert then if Milling.Steps.nCount > 1 then Milling.dLongitudinalOffset = - dPocketHeight else Milling.dLongitudinalOffset = - TOOLS[Milling.nToolIndex].dMaxMaterial - dLongitudinalOffset end else Milling.dLongitudinalOffset = dLongitudinalOffset end -- distanza di sicurezza Milling.dStartSafetyLength = BeamData.CUT_SIC -- overlap Milling.dOverlap = 0 -- faceuse e frame lavorazione if OppositeToolDirectionMode == 'Enabled' then Milling.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Milling.vtToolDirection) --Milling.vtFaceUse = -Milling.vtToolDirection Milling.nEdgesFaceUse = EdgeToMachine.id else Milling.nFaceuse = BeamLib.GetNearestOrthoOpposite( Milling.vtToolDirection) --Milling.vtFaceUse = Milling.vtToolDirection Milling.nEdgesFaceUse = EdgeToMachine.id end -- SCC Milling.nSCC = GetSCC( Milling.vtToolDirection) -- asse bloccato Milling.sBlockedAxis = '' -- eventuale step orizzontale Milling.CloneStepsRadial = {} if not dRadialStepSpan then dRadialStepSpan = Milling.dDepthToMachine end if dRadialStepSpan > 10 * GEO.EPS_SMALL and TOOLS[Milling.nToolIndex].dSideStep then Milling.CloneStepsRadial = MachiningLib.GetMachiningSteps( true, dRadialStepSpan, TOOLS[Milling.nToolIndex].dSideStep) else Milling.CloneStepsRadial.nCount = 1 Milling.CloneStepsRadial.dStep = 0 end -- approccio e retrazione Milling.LeadIn, Milling.LeadOut = CalculateLeadInOut( Milling, EdgeToMachine, bIsSplitFeature) -- check finecorsa nei punti di attacco PointsOnToolTipCenter = { PreSimulationLib.GetPointOnToolTipCenter( Milling.LeadIn.ptPoint, FaceToMachine.vtN, FaceToMachine.vtN, EdgeToMachine.vtN, TOOLS[Milling.nToolIndex]), PreSimulationLib.GetPointOnToolTipCenter( Milling.LeadOut.ptPoint, FaceToMachine.vtN, FaceToMachine.vtN, EdgeToMachine.vtN, TOOLS[Milling.nToolIndex]) } local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, FaceToMachine.vtN, Milling.nSCC, TOOLS[Milling.nToolIndex]) if bOutOfStroke then Milling.sMessage = 'Out of stroke' Milling.bIsApplicable = false return Milling end -- lunghezza lavorata -- TODO per il calcolo del dLengthOnX si deve correggere con allungamento / accorciamento percorso Milling.dLengthToMachine = EdgeToMachine.dLength + Milling.LeadIn.dStartAddLength + Milling.LeadOut.dEndAddLength local b3BoxEdge = BBox3d( Milling.ptEdge1, Milling.ptEdge2) Milling.dLengthOnX = b3BoxEdge:getDimX() Milling.dTimeToMachine, Milling.dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Milling, Part) -- lunghezza impronta lama if Milling.bIsStartClosed and Milling.bIsEndClosed then Milling.dToolMarkLength = abs( min( Milling.LeadIn.dStartAddLength, Milling.LeadOut.dEndAddLength)) elseif Milling.bIsStartClosed then Milling.dToolMarkLength = abs( Milling.LeadIn.dStartAddLength) elseif Milling.bIsEndClosed then Milling.dToolMarkLength = abs( Milling.LeadOut.dEndAddLength) end -- area lavorata Milling.dAreaToMachine = min( EdgeToMachine.dElevation, Milling.dDepthToMachine) * ( min( Milling.dEdgeLength, Milling.dLengthToMachine + 2 * Milling.dToolMarkLength)) -- geometria Milling.Geometry = {{Milling.idProc, FaceToMachine.id}} -- note utente Milling.sUserNotes = sUserNotes -- nome operazione Milling.sOperationName = 'Milling_' .. ( EgtGetName( Milling.idProc) or tostring( Milling.idProc)) .. '_' .. tostring( FaceToMachine.id + 1) -- se lavorazione aperta sulla coda, eventuali aggiustamenti -- TODO valutare se fare funzione a parte if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Milling.vtToolDirection:getX() < 0.707)) then local dLengthOnX = Milling.dLengthOnX -- se feature splittata non si considera la lunghezza della feature per il check spostamento dopo separazione if bIsSplitFeature then dLengthOnX = 0 end local bStartLeft = MachiningLib.StartsLeftSide( Milling) local dAddLengthLeftSide = Milling.LeadOut.dEndAddLength local dAddLengthToReduce = sqrt( Milling.dDepthToMachine * TOOLS[Milling.nToolIndex].dDiameter - Milling.dDepthToMachine * Milling.dDepthToMachine) if bStartLeft then dAddLengthLeftSide = Milling.LeadIn.dStartAddLength end if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then Milling.sStage = 'AfterTail' else Milling.bIsApplicable = false end elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then Milling.sStage = 'AfterTail' else if bStartLeft then Milling.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail else Milling.LeadOut.dEndAddLength = - dAddLengthToReduce + dExtendAfterTail end end end end return Milling end ------------------------------------------------------------------------------------------------------------- return FACEBYMILL