-- Strategia: SLOTBYCHAINSAW -- Descrizione -- Strategia di base per la lavorazione delle slot o tasche con sega a catena -- Feature: tipo lapjoint -- carico librerie local BeamLib = require( 'BeamLib') local BeamData = require( 'BeamData') local MachiningLib = require( 'MachiningLib') local FeatureData = require( 'FeatureData') -- Tabella per definizione modulo local SLOTBYCHAINSAW = {} local Strategy = {} local Chainsaw = {} Result = {} ------------------------------------------------------------------------------------------------------------- local function IsTopologyOk( Proc) if Proc.Topology.bAllRightAngles and ( Proc.Topology.sName == 'Pocket-5-Blind' or Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Tunnel-4-Through') then return true else return false end end local function GetCompletionPercentage( Proc, Result) local dNotMachinedArea = 0 local dCompletionPercentage = 0 if Proc.Topology.sFamily == 'Tunnel' then dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined) if #Result == 2 then dNotMachinedArea = dNotMachinedArea - Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[2].dDepthMachined) end else if #Result == 1 then dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined) elseif #Result == 2 then dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined) elseif #Result == 3 then dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined - Result[3].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined) end end dCompletionPercentage = 100 - dNotMachinedArea / Proc.MainFaces.LongFaces[1].dArea * 100 return dCompletionPercentage end local function CalculateLeadInOut( Machining, EdgeToMachine, sSideToMachine, dLengthToMachine) -- 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 = 0 dAddLengthToReduce = TOOLS[Machining.nToolIndex].dDiameter / 2 if Machining.bInvert then Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed end local LeadIn = {} local LeadOut = {} LeadIn.dStartAddLength = 0 LeadOut.dEndAddLength = 0 if Machining.bIsStartClosed then if sSideToMachine == 'Start' then LeadIn.dStartAddLength = -dAddLengthToReduce - dLengthToMachine - BeamData.CUT_EXTRA + EdgeToMachine.dLength else LeadIn.dStartAddLength = -dAddLengthToReduce end else LeadIn.dStartAddLength = BeamData.CUT_EXTRA end if Machining.bIsEndClosed then if sSideToMachine == 'End' then LeadOut.dEndAddLength = -dAddLengthToReduce - dLengthToMachine - BeamData.CUT_EXTRA + EdgeToMachine.dLength else LeadOut.dEndAddLength = -dAddLengthToReduce end else LeadOut.dEndAddLength = BeamData.CUT_EXTRA end return LeadIn, LeadOut end -- TODO calcolo area lavorata function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters) local Mortising = {} Mortising.bIsApplicable = true Mortising.dDepthToMachine = 0 Mortising.dResidualDepth = abs( EdgeToMachine.dElevation) Mortising.sMessage = '' Mortising.idProc = Proc.id Mortising.sEdgeType = EdgeToMachine.sType -- parametri opzionali local bUseZigZagMortising = OptionalParameters.bUseZigZagMortising or false local sSideToMachine = OptionalParameters.sSideToMachine or '' local dLengthToMachine = OptionalParameters.dLengthToMachine or EdgeToMachine.dLength local dCustomMaxElev = OptionalParameters.dMaxElev or abs( EdgeToMachine.dElevation) local bStopAtHalfElevation = OptionalParameters.bStopAtHalfElevation or false -- altezza tasca, in base alla topologia local dPocketHeight = 0 if Proc.Topology.sFamily == 'Tunnel' then dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength else if FaceToMachine.sType == 'Long' then dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength elseif FaceToMachine.sType == 'Side' then dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength end end -- ricerca utensile local bExtendWithCornerRadius = false if not bStopAtHalfElevation then if ( EdgeToMachine.sType == 'Side' and Proc.Topology.sName == 'Groove-3-Through') or ( EdgeToMachine.sType == 'Opposite' and Proc.Topology.sFamily == 'Tunnel') then bExtendWithCornerRadius = true Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) + BeamData.CUT_EXTRA else Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) end else bExtendWithCornerRadius = true Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) / 2 + BeamData.CUT_EXTRA_MIN end local ToolSearchParameters = {} local ToolInfo = {} ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection ToolSearchParameters.bAllowTopHead = true ToolSearchParameters.bAllowBottomHead = true ToolSearchParameters.dElevation = Mortising.dDepthToMachine ToolSearchParameters.bExtendWithCornerRadius = bExtendWithCornerRadius ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters) Mortising.nToolIndex = ToolInfo.nToolIndex Mortising.nType = MCH_OY.MORTISING if not TOOLS[Mortising.nToolIndex] or not TOOLS[Mortising.nToolIndex].sName then Mortising.sMessage = 'Chainsaw not found' Mortising.bIsApplicable = false EgtOutLog( Mortising.sMessage) return Mortising end -- verifica dimensioni tasca compatibili -- se tasca meno spessa della sega a catena la strategia non è applicabile if TOOLS[Mortising.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL then Mortising.sMessage = 'Pocket too narrow for chainsaw thickness' Mortising.bIsApplicable = false EgtOutLog( Mortising.sMessage) return Mortising end if #( Proc.MainFaces.SideFaces) > 1 then -- se tasca più stretta della sega a catena la strategia non è applicabile if TOOLS[Mortising.nToolIndex].dWidth > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then Mortising.sMessage = 'Pocket too narrow for chainsaw width' Mortising.bIsApplicable = false EgtOutLog( Mortising.sMessage) return Mortising end end -- parametri della lavorazione -- TODO gestire ToolInvert per rispettare direzione migliore di lavorazione -- profondità (parametro DEPTH) non usata Mortising.sDepth = 'TH' -- inizio e fine aperti o chiusi Mortising.bIsStartClosed = not EdgeToMachine.bIsStartOpen Mortising.bIsEndClosed = not EdgeToMachine.bIsEndOpen -- lato di lavoro e inversioni Mortising.bInvert = false if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then Mortising.nWorkside = MCH_MILL_WS.RIGHT Mortising.bToolInvert = false else Mortising.nWorkside = MCH_MILL_WS.LEFT Mortising.bToolInvert = true end -- profondità e offset longitudinale if bExtendWithCornerRadius then Mortising.dDepthToMachine = Mortising.dDepthToMachine + TOOLS[Mortising.nToolIndex].dCornerRadius end if TOOLS[Mortising.nToolIndex].dMaxMaterial > Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then Mortising.dResidualDepth = 0 if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then Mortising.dLongitudinalOffset = 0 else Mortising.dLongitudinalOffset = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine end else Mortising.dDepthToMachine = TOOLS[Mortising.nToolIndex].dMaxMaterial - 1 Mortising.dResidualDepth = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - Mortising.dDepthToMachine else Mortising.dLongitudinalOffset = 0 end Mortising.sMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw elevation (' .. EgtNumToString( EdgeToMachine.dElevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Mortising.dDepthToMachine, 1) .. ')' EgtOutLog( Mortising.sMessage) end -- completamento Mortising.dCompletionPercentage = 100 - Mortising.dResidualDepth / Mortising.dDepthToMachine -- massima elevazione if dCustomMaxElev < Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then Mortising.dMaxElev = dCustomMaxElev end -- offset radiale Mortising.dRadialOffset = 0 -- distanza di sicurezza Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, 10) -- overlap Mortising.dOverlap = 0 -- step Mortising.Steps = {} if bUseZigZagMortising then Mortising.Steps.nStepType = MCH_MILL_ST.ZIGZAG else Mortising.Steps.nStepType = MCH_MILL_ST.ONEWAY end -- faceuse if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( EdgeToMachine.vtToolDirection) else Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -EdgeToMachine.vtToolDirection) end -- SCC Mortising.SCC = MCH_SCC.NONE -- asse bloccato e angoli suggeriti local vtRes = FaceToMachine.vtN ^ EdgeToMachine.vtToolDirection if abs( vtRes:getZ()) < 10 * GEO.EPS_SMALL then Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN) Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 1) elseif EdgeToMachine.vtToolDirection:getZ() < 10 * GEO.EPS_SMALL then Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'parallel', Part.b3Raw, FaceToMachine.vtN) Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 2) end -- approccio e retrazione Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine, sSideToMachine, dLengthToMachine) -- eventuale step verticale Mortising.VerticalSteps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Mortising.nToolIndex].dThickness) -- geometria Mortising.Geometry = {{Proc.id, FaceToMachine.id}} -- nome operazione Mortising.sOperationName = 'Chainsaw_' .. ( EgtGetName( Mortising.idProc) or tostring( Mortising.idProc)) .. '_' .. tostring( FaceToMachine.id + 1) -- eventuale avviso di danneggiamento pezzo successivo -- TODO da sostituire con check se si riesce a separare e il grezzo dietro è lungo a sufficienza -- local dOffsideLength = max( Mortising.LeadIn.dStartAddLength, Mortising.LeadOut.dEndAddLength) + TOOLS[Mortising.nToolIndex].dWidth / 2 + 10 * GEO.EPS_SMALL -- if ( not Proc.bTail or Proc.bAdvTail) and Proc.AffectedFaces.bLeft and ( Proc.dDistanceToNextPart < dOffsideLength) then -- local sDamageNextPieceMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw can damage next piece.' -- if #Mortising.sMessage > 0 then -- Mortising.sMessage = Mortising.sMessage .. '\n' .. sDamageNextPieceMessage -- else -- Mortising.sMessage = sDamageNextPieceMessage -- end -- EgtOutLog( sDamageNextPieceMessage) -- end return Mortising end ------------------------------------------------------------------------------------------------------------- return SLOTBYCHAINSAW