Files
databeamnew/Strategies/STR0003/STR0003.lua
T
luca.mazzoleni 0e634c7f0d - per STR0002 gestite anche Groove-3-blind e Rabbet-2-Through
- GetAffectedFaces modificata per utilizzare Part
- la profonfdità di lavorazione si passa ora sempre come DEPTH_STR
- aggiunti box con tempi di calcolo collect e machining
- corretti typo in nome variabili
2024-05-31 17:47:15 +02:00

829 lines
38 KiB
Lua

-- 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 = {}
Blade.Result = {}
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 - 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 AddResult( Machining, Result)
table.insert( Result, {})
Result[#Result].bCanApply = Machining.bCanApply
Result[#Result].sMessage = Machining.sMessage
Result[#Result].dDepthMachined = Machining.dDepthToMachine
Result[#Result].bIsApplyOk = Machining.bIsApplyOk
Result[#Result].sApplyMessage = Machining.sApplyMessage
return Result
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_STR, Machining.sDepth)
EgtSetMachiningParam( MCH_MP.FACEUSE, Machining.nFaceuse)
EgtSetMachiningParam( MCH_MP.SCC, Machining.nSCC or MCH_SCC.STD)
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.nType ~= 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
-- profondità (parametro DEPTH) non usata
Cutting.sDepth = 0
-- 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à da lavorare 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.nStepType = 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.bTail or Proc.bAdvTail) and Proc.AffectedFaces.bLeft and ( Proc.dDistanceToNextPart < 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.AddResult( Cutting)
AddResult( Cutting, Blade.Result)
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.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 = {}
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
-- 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 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].dMaxMaterial > 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].dMaxMaterial - 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
-- step
Mortising.Steps = {}
if Strategy.Parameters.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
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
-- 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, dResidualDepth
end
function Chainsaw.AddResult( Mortising)
AddResult( Mortising, Chainsaw.Result)
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 = ''
local dResidualDepth = 0
if not IsTopologyOk( Proc) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented'
EgtOutLog( sErr)
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.sInfo = 'Topology'
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.bBottom and ( Proc.nFct > 3 or not Proc.AffectedFaces.bTop) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket on bottom face'
EgtOutLog( sErr)
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.sInfo = 'Direction'
return false, Strategy.Result
end
-- lama
-- lavorazione di lama - fondo della tasca o fino a massimo materiale se tunnel
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
if bAddMachining and Cutting.bCanApply then
Cutting.bIsApplyOk, Cutting.sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part)
end
Blade.AddResult( Cutting)
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])
if bAddMachining and Cutting.bCanApply then
Cutting.bIsApplyOk, Cutting.sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part)
end
Blade.AddResult( Cutting)
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])
if bAddMachining and Cutting.bCanApply then
Cutting.bIsApplyOk, Cutting.sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part)
end
Blade.AddResult( Cutting)
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])
if bAddMachining and Cutting.bCanApply then
Cutting.bIsApplyOk, Cutting.sApplyMessage = Blade.AddMachiningAllSteps( Cutting, Part)
end
Blade.AddResult( Cutting)
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
-- TODO da migliorare / refactoring in funzione
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.sFamily == 'Tunnel' then
Mortising, dResidualDepth = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1])
else
Mortising, dResidualDepth = 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
if bAddMachining and Mortising.bCanApply then
Mortising.bIsApplyOk, Mortising.sApplyMessage = Chainsaw.AddMachiningAllSteps( Mortising, Part)
end
Chainsaw.AddResult( Mortising)
-- lato opposto del tunnel
if Proc.Topology.sFamily == 'Tunnel' and ( dResidualDepth > 10 * GEO.EPS_SMALL) then
Mortising, dResidualDepth = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2])
if bAddMachining and Mortising.bCanApply then
Mortising.bIsApplyOk, Mortising.sApplyMessage = Chainsaw.AddMachiningAllSteps( Mortising, Part)
end
Chainsaw.AddResult( Mortising)
else
-- se la sega a catena non è arrivata sul fondo e c'è almeno un lato aperto va lavorato
if Mortising.dLongitudinalOffset > 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, dResidualDepth = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1])
if bAddMachining and Mortising.bCanApply then
Mortising.bIsApplyOk, Mortising.sApplyMessage = Chainsaw.AddMachiningAllSteps( Mortising, Part)
end
Chainsaw.AddResult( Mortising)
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, dResidualDepth = Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2])
if bAddMachining and Mortising.bCanApply then
Mortising.bIsApplyOk, Mortising.sApplyMessage = Chainsaw.AddMachiningAllSteps( Mortising, Part)
end
Chainsaw.AddResult( Mortising)
end
end
end
-- TODO da migliorare / refactoring in funzione
local nCanApplyCount = 0
local nApplyOkCount = 0
local bAreAllApplyOk
local dCompletionPercentage = 0
for i = 1, #Chainsaw.Result do
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result[i].sMessage .. '\n' .. ( Chainsaw.Result[i].sApplyMessage or '')
if Chainsaw.Result[i].bCanApply then
nCanApplyCount = nCanApplyCount + 1
end
if Chainsaw.Result[i].bIsApplyOk then
nApplyOkCount = nApplyOkCount + 1
end
end
if bAddMachining then
bAreAllApplyOk = ( nApplyOkCount == #Chainsaw.Result)
end
if nCanApplyCount == 0 then
Strategy.Result.sStatus = 'Not-Applicable'
else
dCompletionPercentage = GetCompletionPercentage( Proc, Chainsaw.Result)
if ( nCanApplyCount == #Chainsaw.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( 'Chainsaw')
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
-------------------------------------------------------------------------------------------------------------
return STR0003