-- Strategia: STR0003 -- Descrizione -- Lama + motosega per slot -- 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 STR0003 = {} local Strategy = {} local Blade = {} local Chainsaw = {} ------------------------------------------------------------------------------------------------------------- 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 - Result[2].dDepthMachined) 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) -- 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 bIsMortising = ( Machining.nType == MCH_OY.MORTISING) local dAddLengthToReduce = 0 if bIsMortising then dAddLengthToReduce = TOOLS[Machining.nToolIndex].dDiameter / 2 else dAddLengthToReduce = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine) end if Machining.bInvert then Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed end local LeadIn = {} local LeadOut = {} LeadIn.dStartAddLength = 0 LeadOut.dEndAddLength = 0 if not bIsMortising then LeadIn.nType = MCH_MILL_LI.LINEAR LeadOut.nType = MCH_MILL_LI.LINEAR LeadIn.dTangentDistance = 0 LeadOut.dTangentDistance = 0 if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC else LeadIn.dPerpDistance = BeamData.CUT_SIC LeadOut.dPerpDistance = BeamData.CUT_SIC 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 else if Machining.bIsStartClosed then LeadIn.dStartAddLength = -dAddLengthToReduce else LeadIn.dStartAddLength = BeamData.CUT_EXTRA end if Machining.bIsEndClosed then LeadOut.dEndAddLength = -dAddLengthToReduce else LeadOut.dEndAddLength = BeamData.CUT_EXTRA end end return LeadIn, LeadOut end local function AddNewMachining( Machining, Part) local sErr = '' local nOperationId = EgtCreateMachining( Machining.sOperationName, Machining.nType, TOOLS[Machining.nToolIndex].sName) -- impostazione parametri lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) EgtSetMachiningGeometry( Machining.Geometry) EgtSetMachiningParam( MCH_MP.DEPTH, Machining.Depth or 0) EgtSetMachiningParam( MCH_MP.FACEUSE, Machining.nFaceuse) EgtSetMachiningParam( MCH_MP.SCC, Machining.nSCC) EgtSetMachiningParam( MCH_MP.INVERT, Machining.bInvert) EgtSetMachiningParam( MCH_MP.WORKSIDE, Machining.nWorkside) EgtSetMachiningParam( MCH_MP.TOOLINVERT, Machining.bToolInvert) EgtSetMachiningParam( MCH_MP.OFFSR, Machining.dRadialOffset) EgtSetMachiningParam( MCH_MP.OFFSL, Machining.dLongitudinalOffset) if Machining.Type ~= MCH_OY.MORTISING then EgtSetMachiningParam( MCH_MP.LEADINTYPE, Machining.LeadIn.nType) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, Machining.LeadOut.nType) EgtSetMachiningParam( MCH_MP.LITANG, Machining.LeadIn.dTangentDistance) EgtSetMachiningParam( MCH_MP.LOTANG, Machining.LeadOut.dTangentDistance) EgtSetMachiningParam( MCH_MP.LIPERP, Machining.LeadIn.dPerpDistance) EgtSetMachiningParam( MCH_MP.LOPERP, Machining.LeadOut.dPerpDistance) EgtSetMachiningParam( MCH_MP.LIELEV, Machining.LeadIn.dElevation) EgtSetMachiningParam( MCH_MP.LOELEV, Machining.LeadOut.dElevation) EgtSetMachiningParam( MCH_MP.LICOMPLEN, Machining.LeadIn.dCompLength) EgtSetMachiningParam( MCH_MP.LOCOMPLEN, Machining.LeadOut.dCompLength) end EgtSetMachiningParam( MCH_MP.STARTADDLEN, Machining.LeadIn.dStartAddLength) EgtSetMachiningParam( MCH_MP.ENDADDLEN, Machining.LeadOut.dEndAddLength) if Machining.Steps then if Machining.Steps.nStepType then EgtSetMachiningParam( MCH_MP.STEPTYPE, Machining.Steps.nStepType) end if Machining.Steps.dStepLength then EgtSetMachiningParam( MCH_MP.STEP, Machining.Steps.dStepLength) end end EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BeamLib.GetBlockedAxis( Machining.nToolIndex, Machining.BlockedAxis.sOrientation, Part.b3Raw, Machining.BlockedAxis.vtN, Machining.BlockedAxis.vtOut)) if Machining.nType == MCH_OY.MORTISING then EgtSetMachiningParam( MCH_MP.INITANGS, BeamLib.GetChainSawInitAngs( Machining.SuggestedAngles.vtN, Machining.SuggestedAngles.vtOrtho, Machining.SuggestedAngles.nIndex)) end EgtSetMachiningParam( MCH_MP.OVERL, Machining.dOverlap) EgtSetMachiningParam( MCH_MP.STARTPOS, max( Machining.dStartSafetyLength, EgtGetMachiningParam( MCH_MP.STARTPOS))) if Machining.dMaxElev then sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', Machining.dMaxElev) end EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) local bIsApplyOk = MachiningLib.ApplyMachining( true, false) if not bIsApplyOk then local nErr nErr, sErr = EgtGetLastMachMgrError() -- se mortasatura e l'errore è compatibile (Axes values not calculable) si prova con l'altra configurazione dell'asse bloccato -- TODO valutare se c'è modo di capire preventivamente la configurazione dell'asse bloccato e quindi rimuovere questa parte di codice if Machining.nType == MCH_OY.MORTISING and nErr == 2507 then if Machining.BlockedAxis.sOrientation == 'perpendicular' then Machining.BlockedAxis.sOrientation = 'parallel' else Machining.BlockedAxis.sOrientation = 'perpendicular' end EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BeamLib.GetBlockedAxis( Machining.nToolIndex, Machining.BlockedAxis.sOrientation, Part.b3Raw, Machining.BlockedAxis.vtN, Machining.BlockedAxis.vtOut)) if Machining.SuggestedAngles.nIndex == 1 then Machining.SuggestedAngles.nIndex = 2 else Machining.SuggestedAngles.nIndex = 1 end EgtSetMachiningParam( MCH_MP.INITANGS, BeamLib.GetChainSawInitAngs( Machining.SuggestedAngles.vtN, Machining.SuggestedAngles.vtOrtho, Machining.SuggestedAngles.nIndex)) sErr = '' bIsApplyOk = EgtApplyMachining( true, false) end if not bIsApplyOk then nErr, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nOperationId, false) return false, sErr end end return true, sErr end function Blade.GetSCC( vtMachiningDirection) -- TODO implementare SCC come per FacesBySaw local nSCC = MCH_SCC.NONE if AreSameVectorApprox( vtMachiningDirection, Z_AX()) then nSCC = MCH_SCC.ADIR_ZP elseif AreOppositeVectorApprox( vtMachiningDirection, Z_AX()) then nSCC = MCH_SCC.ADIR_ZM elseif AreSameVectorApprox( vtMachiningDirection, Y_AX()) then nSCC = MCH_SCC.ADIR_YP elseif AreOppositeVectorApprox( vtMachiningDirection, Y_AX()) then nSCC = MCH_SCC.ADIR_YM elseif AreSameVectorApprox( vtMachiningDirection, X_AX()) then nSCC = MCH_SCC.ADIR_XP elseif AreOppositeVectorApprox( vtMachiningDirection, X_AX()) then nSCC = MCH_SCC.ADIR_XM end return nSCC end function Blade.CalculateMachiningParameters( Proc, FaceToMachine, EdgeToMachine) local Cutting = {} Cutting.bCanApply = true Cutting.dDepthToMachine = 0 Cutting.sMessage = '' Cutting.idProc = Proc.id local dResidualDepth = 0 local dPocketHeight = 0 if Proc.Topology.sFamily == 'Tunnel' then dPocketHeight = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dHeight else if FaceToMachine.Type == 'Long' then dPocketHeight = Proc.MainFaces.BottomFace.MainEdges.SideEdges[1].dLength elseif FaceToMachine.Type == 'Side' then dPocketHeight = Proc.MainFaces.BottomFace.MainEdges.LongEdges[1].dLength end end -- ricerca utensile local ToolSearchParameters = {} ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation) ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection ToolSearchParameters.bAllowTopHead = true ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) Cutting.nToolIndex = ToolInfo.nToolIndex Cutting.nType = MCH_OY.MILLING if not TOOLS[Cutting.nToolIndex].sName then Cutting.sMessage = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - saw blade not found' Cutting.bCanApply = false EgtOutLog( Cutting.sMessage) return Cutting, EdgeToMachine.dElevation end -- verifica dimensioni tasca compatibili -- se tasca meno spessa della lama la strategia non è applicabile if TOOLS[Cutting.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL then Cutting.sMessage = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket too narrow for saw blade thickness' Cutting.bCanApply = false EgtOutLog( Cutting.sMessage) return Cutting, EdgeToMachine.dElevation end if #( Proc.MainFaces.SideFaces) > 1 then -- se tasca più stretta della lama la strategia non è applicabile if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then Cutting.sMessage = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket too narrow for saw blade diameter' Cutting.bCanApply = false EgtOutLog( Cutting.sMessage) return Cutting, EdgeToMachine.dElevation end end -- parametri della lavorazione -- inizio e fine aperti o chiusi Cutting.bIsStartClosed = not EdgeToMachine.bIsStartOpen Cutting.bIsEndClosed = not EdgeToMachine.bIsEndOpen -- lato di lavoro e inversioni if TOOLS[Cutting.nToolIndex].bIsCCW then Cutting.nWorkside = MCH_MILL_WS.RIGHT Cutting.bInvert = true else Cutting.nWorkside = MCH_MILL_WS.LEFT Cutting.bInvert = false end if EdgeToMachine.dElevation < -10 * GEO.EPS_SMALL then Cutting.bInvert = not Cutting.bInvert end -- TODO gestire lama da sotto e lama downUp if FaceToMachine.vtN:getZ() < - 10 * GEO.EPS_SMALL then Cutting.bToolInvert = true Cutting.bInvert = not Cutting.bInvert else Cutting.bToolInvert = false end -- profondità e offset radiale if TOOLS[Cutting.nToolIndex].dMaxDepth > abs( EdgeToMachine.dElevation) - 10 * GEO.EPS_SMALL then -- TODO la depth dovrebbe essere quella del machining Cutting.dDepthToMachine = abs( EdgeToMachine.dElevation) if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then Cutting.dRadialOffset = 0 else Cutting.dRadialOffset = EdgeToMachine.dElevation end else Cutting.dDepthToMachine = TOOLS[Cutting.nToolIndex].dMaxDepth - 1 dResidualDepth = abs( EdgeToMachine.dElevation) - Cutting.dDepthToMachine if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then Cutting.dRadialOffset = EdgeToMachine.dElevation - Cutting.dDepthToMachine else Cutting.dRadialOffset = -Cutting.dDepthToMachine end if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL and not Strategy.Parameters.bFinishWithChainSaw then Cutting.sMessage = 'Feature '.. Proc.idFeature .. ' : sawblade elevation (' .. EgtNumToString( EdgeToMachine.dElevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Cutting.dDepthToMachine, 1) .. ')' EgtOutLog( Cutting.sMessage) end end -- step verticale e offset longitudinale Cutting.Steps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Cutting.nToolIndex].dThickness) Cutting.Steps.StepType = MCH_MILL_ST.ONEWAY Cutting.dMaxElev = Cutting.Steps.dStepLength * Cutting.Steps.nCount - 10 * GEO.EPS_SMALL if Cutting.bToolInvert and Cutting.Steps.nCount > 1 then Cutting.dLongitudinalOffset = - dPocketHeight else Cutting.dLongitudinalOffset = 0 end -- distanza di sicurezza Cutting.dStartSafetyLength = 10 -- overlap Cutting.dOverlap = 0 -- faceuse if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( EdgeToMachine.vtToolDirection) else Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -EdgeToMachine.vtToolDirection) end -- SCC Cutting.nSCC = Blade.GetSCC( EdgeToMachine.vtToolDirection) -- asse bloccato Cutting.BlockedAxis = {} Cutting.BlockedAxis.sOrientation = 'perpendicular' Cutting.BlockedAxis.vtN = FaceToMachine.vtN Cutting.BlockedAxis.vtOut = EgtIf( FaceToMachine.vtN:getX() > 0, X_AX(), -X_AX()) -- approccio e retrazione Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( Cutting, EdgeToMachine) -- eventuale step orizzontale Cutting.HorizontalSteps = {} if TOOLS[Cutting.nToolIndex].dSideStep then Cutting.HorizontalSteps = MachiningLib.GetMachiningSteps( Cutting.dDepthToMachine, TOOLS[Cutting.nToolIndex].dSideStep) else Cutting.HorizontalSteps.nCount = 1 Cutting.HorizontalSteps.dStepLength = 0 end -- geometria Cutting.Geometry = {{Proc.id, FaceToMachine.id}} -- nome operazione Cutting.sOperationName = 'Cut_' .. ( EgtGetName( Cutting.idProc) or tostring( Cutting.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( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength) + TOOLS[Cutting.nToolIndex].dDiameter / 2 + 10 * GEO.EPS_SMALL if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and ( Proc.DistanceToNextPart < dOffsideLength) then local sDamageNextPieceMessage = 'Feature '.. Proc.idFeature .. ' : sawblade can damage next piece.' if #Cutting.sMessage > 0 then Cutting.sMessage = Cutting.sMessage .. '\n' .. sDamageNextPieceMessage else Cutting.sMessage = sDamageNextPieceMessage end EgtOutLog( sDamageNextPieceMessage) end return Cutting, dResidualDepth end function Blade.AddMachiningAllSteps( Cutting, Part) local bIsCuttingOk = false local sCuttingApplyMessage = '' local dOriginalRadialOffset = Cutting.dRadialOffset local dOriginalLeadInPerpDistance = Cutting.LeadIn.dPerpDistance local dOriginalLeadOutPerpDistance = Cutting.LeadOut.dPerpDistance for i = Cutting.HorizontalSteps.nCount, 1, -1 do Cutting.dRadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.dStepLength * ( i - 1) -- update distanza perpendicolare attacco per contemplare l'offset applicato Cutting.LeadIn.dPerpDistance = dOriginalLeadInPerpDistance - Cutting.dRadialOffset Cutting.LeadOut.dPerpDistance = dOriginalLeadOutPerpDistance - Cutting.dRadialOffset -- applicazione lavorazione bIsCuttingOk, sCuttingApplyMessage = AddNewMachining( Cutting, Part) -- update messaggi if sCuttingApplyMessage and #sCuttingApplyMessage > 0 then sCuttingApplyMessage = sCuttingApplyMessage .. 'Apply : ' .. sCuttingApplyMessage .. '\n' end end return bIsCuttingOk, sCuttingApplyMessage end function Chainsaw.CalculateMachiningParameters( Proc, FaceToMachine, EdgeToMachine) local Mortising = {} Mortising.bCanApply = true Mortising.dDepthToMachine = 0 Mortising.sMessage = '' Mortising.idProc = Proc.id -- OneSide | OneSideAndExtend | BothSides | BothSidesAndExtend local sMortisingType local dResidualDepth = 0 local dPocketHeight = 0 if Proc.Topology.sFamily == 'Tunnel' then dPocketHeight = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.dHeight else if FaceToMachine.Type == 'Long' then dPocketHeight = Proc.MainFaces.BottomFace.MainEdges.SideEdges[1].dLength elseif FaceToMachine.Type == 'Side' then dPocketHeight = Proc.MainFaces.BottomFace.MainEdges.LongEdges[1].dLength end end -- ricerca utensile local ToolSearchParameters = {} local ToolInfo = {} ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection ToolSearchParameters.bAllowTopHead = true ToolSearchParameters.bAllowBottomHead = false if Proc.Topology.sFamily == 'Tunnel' then sMortisingType = 'OneSideAndExtend' ToolSearchParameters.bExtendWithCornerRadius = true ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation) + BeamData.CUT_EXTRA ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters) if ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL then sMortisingType = 'BothSidesAndExtend' ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation) / 2 + BeamData.CUT_EXTRA_MIN ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters) end elseif EdgeToMachine.sType == 'Side' and #( Proc.MainFaces.SideFaces) == 0 then sMortisingType = 'BothSidesAndExtend' ToolSearchParameters.bExtendWithCornerRadius = true ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation) / 2 + BeamData.CUT_EXTRA_MIN ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters) else sMortisingType = 'OneSide' ToolSearchParameters.bExtendWithCornerRadius = false ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation) + BeamData.CUT_EXTRA ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters) end if ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL then if sMortisingType == 'BothSidesAndExtend' then sMortisingType = 'BothSides' elseif sMortisingType == 'OneSideAndExtend' then sMortisingType = 'OneSide' end ToolSearchParameters.bExtendWithCornerRadius = false ToolSearchParameters.dElevation = nil ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters) end Mortising.nToolIndex = ToolInfo.nToolIndex Mortising.nType = MCH_OY.MORTISING if not TOOLS[Mortising.nToolIndex].sName then Mortising.sMessage = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - chainsaw not found' Mortising.bCanApply = false EgtOutLog( Mortising.sMessage) return Mortising, EdgeToMachine.dElevation 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 = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket too narrow for chainsaw thickness' Mortising.bCanApply = false EgtOutLog( Mortising.sMessage) return Mortising, EdgeToMachine.dElevation 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 = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket too narrow for chainsaw width' Mortising.bCanApply = false EgtOutLog( Mortising.sMessage) return Mortising, EdgeToMachine.dElevation end end -- parametri della lavorazione -- 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 sMortisingType == 'OneSide' then Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) elseif sMortisingType == 'OneSideAndExtend' then Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) + TOOLS[Mortising.nToolIndex].dCornerRadius + BeamData.CUT_EXTRA_MIN elseif sMortisingType == 'BothSides' then Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) / 2 elseif sMortisingType == 'BothSidesAndExtend' then Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) / 2 + TOOLS[Mortising.nToolIndex].dCornerRadius + BeamData.CUT_EXTRA_MIN end if TOOLS[Mortising.nToolIndex].dMaxMat > Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then 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].dMaxMat - 1 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 -- offset radiale Mortising.dRadialOffset = 0 -- distanza di sicurezza Mortising.dStartSafetyLength = EdgeToMachine.dElevation -- overlap Mortising.dOverlap = 0 -- 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 Mortising.BlockedAxis = {} Mortising.BlockedAxis.sOrientation = 'perpendicular' Mortising.BlockedAxis.vtN = FaceToMachine.vtN Mortising.SuggestedAngles = {} Mortising.SuggestedAngles.nIndex = 1 Mortising.SuggestedAngles.vtN = FaceToMachine.vtN Mortising.SuggestedAngles.vtOrthO = EdgeToMachine.vtToolDirection -- approccio e retrazione Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine) -- 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 local dOffsideLength = max( Mortising.LeadIn.dStartAddLength, Mortising.LeadOut.dEndAddLength) + TOOLS[Mortising.nToolIndex].dWidth / 2 + 10 * GEO.EPS_SMALL if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and ( Proc.DistanceToNextPart < 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, dResidualDepth end function Chainsaw.AddMachiningAllSteps( Mortising, Part) local bIsMortisingOk = false local sMortisingApplyMessage = '' local dOriginalRadialOffsetMortising = Mortising.dRadialOffset for i = Mortising.VerticalSteps.nCount, 1, -1 do Mortising.dRadialOffset = dOriginalRadialOffsetMortising + Mortising.VerticalSteps.dStepLength * ( i - 1) -- applicazione lavorazione bIsMortisingOk, sMortisingApplyMessage = AddNewMachining( Mortising, Part.b3Raw) -- update messaggi if sMortisingApplyMessage and #sMortisingApplyMessage > 0 then Mortising.sMessage = Mortising.sMessage .. '\n' .. 'Apply : ' .. sMortisingApplyMessage end end return bIsMortisingOk, sMortisingApplyMessage end function STR0003.Make( bAddMachining, Proc, Part, CustomParameters) -- TODO da implementare gestione feature lunghe e spezzatura -- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti) local StrategyLib = {} StrategyLib.Config = require( 'STR0003\\STR0003Config') Strategy.sName = StrategyLib.Config.sStrategyId CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters) Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters) Strategy.Result = {} Strategy.Result.sInfo = '' Blade.Result = {} Chainsaw.Result = {} local dResidualDepth = 0 if not IsTopologyOk( Proc) then local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented' EgtOutLog( sErr) return false, Strategy.Result end -- se tasca su faccia sotto la strategia non è applicabile (la sega a catena in generale non può lavorare da sotto) -- TODO se OnlySaw questo test è da rimuovere ma bisogna considerare anche la lama da sotto if Proc.AffectedFaces.Bottom and ( Proc.Fct > 3 or not Proc.AffectedFaces.Top) then local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket on bottom face' EgtOutLog( sErr) return false, Strategy.Result end -- lama -- lavorazione di lama - fondo della tasca o fino a massimo materiale se tunnel table.insert( Blade.Result, {}) local Cutting = {} if Proc.Topology.sFamily == 'Tunnel' then Cutting, dResidualDepth = Blade.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1]) else Cutting, dResidualDepth = Blade.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge) end Blade.Result[#Blade.Result].bCanApply = Cutting.bCanApply Blade.Result[#Blade.Result].sMessage = Cutting.sMessage Blade.Result[#Blade.Result].dDepthMachined = Cutting.dDepthToMachine if bAddMachining and Cutting.bCanApply then Blade.Result[#Blade.Result].bIsApplyOk, Blade.Result[#Blade.Result].sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part) end local dBottomDepthToMachine = dResidualDepth -- lato opposto del tunnel if Proc.Topology.sFamily == 'Tunnel' then Cutting, dResidualDepth = Blade.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2]) table.insert( Blade.Result, {}) Blade.Result[#Blade.Result].bCanApply = Cutting.bCanApply Blade.Result[#Blade.Result].sMessage = Cutting.sMessage Blade.Result[#Blade.Result].dDepthMachined = Cutting.dDepthToMachine if bAddMachining and Cutting.bCanApply then Blade.Result[#Blade.Result].bIsApplyOk, Blade.Result[#Blade.Result].sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part) end else -- se la lama non è arrivata sul fondo e c'è almeno un lato aperto va lavorato if dResidualDepth > 10 * GEO.EPS_SMALL then -- eventuale lavorazione di lama - lato della tasca da cui inizia la lavorazione if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then Cutting, dResidualDepth = Blade.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1]) table.insert( Blade.Result, {}) Blade.Result[#Blade.Result].bCanApply = Cutting.bCanApply Blade.Result[#Blade.Result].sMessage = Cutting.sMessage Blade.Result[#Blade.Result].dDepthMachined = Cutting.dDepthToMachine if bAddMachining and Cutting.bCanApply then Blade.Result[#Blade.Result].bIsApplyOk, Blade.Result[#Blade.Result].sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part) end end -- eventuale lavorazione di lama - lato della tasca in cui finisce la lavorazione if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then Cutting, dResidualDepth = Blade.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2]) table.insert( Blade.Result, {}) Blade.Result[#Blade.Result].bCanApply = Cutting.bCanApply Blade.Result[#Blade.Result].sMessage = Cutting.sMessage Blade.Result[#Blade.Result].dDepthMachined = Cutting.dDepthToMachine if bAddMachining and Cutting.bCanApply then Blade.Result[#Blade.Result].bIsApplyOk, Blade.Result[#Blade.Result].sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part) end end -- la lama è arrivata sul fondo e tasca passante, non servono ulteriori lavorazioni elseif #( Proc.MainFaces.SideFaces) == 0 then Strategy.Parameters.bFinishWithChainSaw = false Strategy.Parameters.bNotCompleteWithBladeRadius = false end end if not Strategy.Parameters.bFinishWithChainSaw then local nCanApplyCount = 0 local nApplyOkCount = 0 local bAreAllApplyOk local dCompletionPercentage = 0 for i = 1, #Blade.Result do Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result[i].sMessage .. '\n' .. ( Blade.Result[i].sApplyMessage or '') if Blade.Result[i].bCanApply then nCanApplyCount = nCanApplyCount + 1 end if Blade.Result[i].bIsApplyOk then nApplyOkCount = nApplyOkCount + 1 end end if bAddMachining then bAreAllApplyOk = ( nApplyOkCount == #Blade.Result) end if nCanApplyCount == 0 then Strategy.Result.sStatus = 'Not-Applicable' else dCompletionPercentage = GetCompletionPercentage( Proc, Blade.Result) if not Strategy.Parameters.bNotCompleteWithBladeRadius and ( ( nCanApplyCount == #Blade.Result) and dCompletionPercentage > 99 + 10 * GEO.EPS_SMALL) then Strategy.Result.sStatus = 'Completed' else Strategy.Result.sStatus = 'Not-Completed' end end Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dCompletionPercentage) Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade') local MrrParameters = { dStep = TOOLS[Cutting.nToolIndex].dThickness, dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength), dFeed = TOOLS[Cutting.nToolIndex].Feeds.dFeed} Strategy.Result.dMRR = MachiningLib.GetToolMRR( MrrParameters) return bAreAllApplyOk, Strategy.Result end -- sega a catena -- parametri lavorazione con sega a catena - fondo della tasca o tunnel local Mortising = {} if Proc.Topology == 'Tunnel' then Mortising, dResidualDepth = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1]) else Mortising = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge) -- si lavora solo quanto non lavorato dalla lama Mortising.MaxElev = dBottomDepthToMachine + BeamData.CUT_EXTRA end local bIsMortisingOk = false if bAddMachining and Mortising.bCanApply then bIsMortisingOk, Mortising.Message = Chainsaw.AddMachiningAllSteps( Mortising, Part) end -- lato opposto del tunnel if Proc.Topology == 'Tunnel' and ( dResidualDepth > 10 * GEO.EPS_SMALL) then Mortising = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2]) bIsMortisingOk = false if bAddMachining and Mortising.bCanApply then bIsMortisingOk, Mortising.Message = Chainsaw.AddMachiningAllSteps( Mortising, Part) end if not bIsMortisingOk then return bIsMortisingOk, Mortising.Message end else -- se la sega a catena non è arrivata sul fondo e c'è almeno un lato aperto va lavorato if Mortising.LongitudinalOffset > 10 * GEO.EPS_SMALL then -- eventuale lavorazione di sega a catena - lato della tasca da cui inizia la lavorazione if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then Mortising = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1]) bIsMortisingOk = false if bAddMachining and Mortising.bCanApply then bIsMortisingOk, Mortising.Message = Chainsaw.AddMachiningAllSteps( Mortising, Part) end if not bIsMortisingOk then return bIsMortisingOk, Mortising.Message end end -- eventuale lavorazione di sega a catena - lato della tasca in cui finisce la lavorazione if Proc.MainFaces.LongFace[1].MainEdges.BottomEdge.bIsEndOpen then Mortising = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].Edges.SideEdges[2]) bIsMortisingOk = false if bAddMachining and Mortising.bCanApply then bIsMortisingOk, Mortising.Message = Chainsaw.AddMachiningAllSteps( Mortising, Part) end if not bIsMortisingOk then return bIsMortisingOk, Mortising.Message end end end end local sFinalMessage = '' if #Cutting.Message > 0 or #Mortising.Message > 0 then sFinalMessage = Cutting.Message .. '\n' .. Mortising.Message end return bIsMortisingOk, sFinalMessage end ------------------------------------------------------------------------------------------------------------- return STR0003