Files
databeamnew/StrategyLibs/FACEBYBLADE.lua
T

702 lines
30 KiB
Lua

-- Strategia: FACEBYBLADE
-- Descrizione
-- Strategia di base per la lavorazione delle facce con lama
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local FaceData = require( 'FaceData')
-- Tabella per definizione modulo
local FACEBYBLADE = {}
-------------------------------------------------------------------------------------------------------------
local function GetLeadInOutType( Machining)
local sLeadInOutType = ''
if Machining.bIsStartClosed or Machining.bIsEndClosed
or Machining.sEdgeUsage == 'Guillotine'
or Machining.sEdgeUsage == 'Reduced' 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 and abs( Machining.vtToolDirection:getZ()) < 0.7) then
sLeadInOutType = 'Perpendicular'
else
sLeadInOutType = 'Tangent'
end
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
sLeadInOutType = 'Perpendicular'
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 and abs( Machining.vtToolDirection:getZ()) < 0.7) then
sLeadInOutType = 'Perpendicular'
else
sLeadInOutType = 'Tangent'
end
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
sLeadInOutType = 'Perpendicular'
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)
-- accorciamento per lati chiusi (è sempre l'impronta utensile)
local dToolMarkLength = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine)
-- allungamento per faccia singola (aperta in tutte le direzioni)
local dAddedLengthOpenFace = BeamData.CUT_EXTRA
if Machining.sEdgeUsage == 'Guillotine' then
local dGuillotineLengthToMachine = 1
dAddedLengthOpenFace = ( - EdgeToMachine.dLength + dGuillotineLengthToMachine) / 2
elseif Machining.sEdgeUsage == 'Reduced' then
dAddedLengthOpenFace = - FACEBYBLADE.GetPathReductionLength( Machining.nToolIndex, Machining.dMaxRadialOffset)
end
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 Machining.CloneStepsRadial.nCount > 1
or Machining.Steps.nCount > 1
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
-- TODO da rimuovere, già inserito in GetLeadInOutType
if abs( Machining.vtEdgeDirection:getZ()) > 0.707 then
LeadIn.dPerpDistance = 1
LeadOut.dPerpDistance = 1
else
LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
end
end
end
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
if Machining.bIsStartClosed and Machining.bIsEndClosed then
LeadIn.dStartAddLength = -dToolMarkLength
LeadOut.dEndAddLength = -dToolMarkLength
elseif Machining.bIsStartClosed then
LeadIn.dStartAddLength = -dToolMarkLength
-- 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 = -dToolMarkLength
-- 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 = dAddedLengthOpenFace
LeadOut.dEndAddLength = dAddedLengthOpenFace
end
-- 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 + BeamData.CUT_SIC
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 + BeamData.CUT_SIC
end
LeadIn.dTotalEstimatedDistance = sqrt( dEstimatedLeadInPerpDistance ^ 2 + dEstimatedLeadInTangentDistance ^ 2) + Machining.dStartSafetyLength
LeadOut.dTotalEstimatedDistance = sqrt( dEstimatedLeadOutPerpDistance ^ 2 + dEstimatedLeadOutTangentDistance ^ 2) + Machining.dStartSafetyLength
return LeadIn, LeadOut
end
-- TODO implementare SCC in funzione macchina
local function GetSCC( vtMachiningDirection, vtEdgeDirection, vtNFace)
local nSCC = MCH_SCC.NONE
if abs( vtMachiningDirection:getX()) > abs( vtMachiningDirection:getY()) - GEO.EPS_SMALL then
-- se il taglio è orizzontale, si gira aggregato lama per facilitare caduta del legno
if abs( vtEdgeDirection:getZ()) < 10 * GEO.EPS_SMALL and not AreSameOrOppositeVectorApprox( vtNFace, Z_AX()) then
nSCC = EgtIf( ( vtMachiningDirection:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
else
nSCC = EgtIf( ( vtMachiningDirection:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM)
end
else
-- se il taglio è orizzontale, si gira aggregato lama per facilitare caduta del legno
if abs( vtEdgeDirection:getZ()) < 10 * GEO.EPS_SMALL and not AreSameOrOppositeVectorApprox( vtNFace, Z_AX()) then
nSCC = EgtIf( ( vtMachiningDirection:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
else
nSCC = EgtIf( ( vtMachiningDirection:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
end
end
return nSCC
end
-- in base a tipo testa e angolo soglia, verifica se la faccia è troppo inclinata per il taglio scelto (Standard o DownUp)
local function IsFaceZOutOfRange ( vtNFace, Tool)
-- lama sotto: angolo negativo troppo basso
if Tool.SetupInfo.HeadType.Top and vtNFace:getZ() < Tool.SetupInfo.GetMinNz( vtNFace, Tool) - GEO.EPS_ZERO then
return true
end
-- lama sopra: angolo positivo troppo elevato
if Tool.SetupInfo.HeadType.Bottom and vtNFace:getZ() > Tool.SetupInfo.GetMaxNz( vtNFace, Tool) + GEO.EPS_ZERO then
return true
end
return false
end
local function IsOrientationOkForDownUp( Face, Edge, b3Raw)
-- se l'utensile lavora perpendicolarmente, l'orientamento è sempre valido per DownUp
if AreSameVectorApprox( Face.vtN, Edge) then
return true
end
-- orientamento 3d della faccia: non lavorabile in DownUp
-- TODO implementare gestione DownUp in 3d
local FaceOrientation = BeamLib.GetPlaneOrientation( Face.vtN)
if FaceOrientation[1].dRelativeMagnitude < 1 - 10 * GEO.EPS_SMALL then
return false
end
-- orientamento 2d: si determinano il piano della faccia e la direzione perpendicolare
local sPlane = FaceOrientation[1].sPlane
local vtPerpendicularToPlane
if sPlane == 'XY' then
vtPerpendicularToPlane = Z_AX()
elseif sPlane == 'XZ' then
vtPerpendicularToPlane = Y_AX()
elseif sPlane == 'YZ' then
vtPerpendicularToPlane = X_AX()
end
-- se l'utensile è in direzione perpendicolare al piano, l'orientamento è sempre valido per DownUp
if AreSameOrOppositeVectorApprox( Edge.vtN, vtPerpendicularToPlane) then
return true
end
-- se tutte le condizioni precedenti sono soddisfatte, il DownUp si può fare se lungo l'asse in cui Face.vtN e Edge.vtN sono discordi il punto iniziale del lato è sul box
-- in pratica, ciò significa che il braccio non entrerà in collisione con la trave
-- TODO in realtà così si escludono dei casi di faccia non troncante in cui aumenterebbe l'elevation ma si potrebbe comunque lavorare
local _, ptOnBox = EgtSurfTmFacetOppositeSide( Face.idTrimesh, Face.id, -Edge.vtN, GDB_ID.ROOT)
-- Helper function: verifica se i vettori sono discordi lungo l'asse indicato e, se sì, se il punto iniziale della lavorazione è sul box oppure no, nella direzione dell'utensile
local function IsDiscordantAndOnBox( sAxis)
-- si compongono i metodi getX, getY, getZ in base all'asse in arrivo (Face.vtN[getX] equivale a Face.vtN:getX())
local dFaceComponent = Face.vtN["get" .. sAxis](Face.vtN)
local dEdgeComponent = Edge.vtN["get" .. sAxis](Edge.vtN)
local dPtonboxComponent = ptOnBox["get" .. sAxis](ptOnBox)
local dMaxb3rawComponent = b3Raw:getMax()["get" .. sAxis](b3Raw:getMax())
local dMinb3rawComponent = b3Raw:getMin()["get" .. sAxis](b3Raw:getMin())
if dFaceComponent * dEdgeComponent < 10 * GEO.EPS_SMALL then
if dEdgeComponent > GEO.EPS_SMALL then
return dPtonboxComponent > dMaxb3rawComponent - 500 * GEO.EPS_SMALL
else
return dPtonboxComponent < dMinb3rawComponent + 500 * GEO.EPS_SMALL
end
end
return false
end
-- in base all'orientamento, si verifica se il DownUp è fattibile
if sPlane == 'XY' then
if IsDiscordantAndOnBox( "X") then
return true
elseif IsDiscordantAndOnBox( "Y") then
return true
end
elseif sPlane == 'XZ' then
if IsDiscordantAndOnBox( "X") then
return true
elseif IsDiscordantAndOnBox( "Z") then
return true
end
elseif sPlane == 'YZ' then
if IsDiscordantAndOnBox( "Y") then
return true
elseif IsDiscordantAndOnBox( "Z") then
return true
end
end
return false
end
-- ritorna se la faccia e il lato sono lavorabili e, se sì, il modo di lavorare (standard/DownUp) e l'elevazione corretta (in DownUp può cambiare)
function FACEBYBLADE.GetBladeEngagement( Face, Edge, b3Raw, Tool)
local sBladeEngagement = 'Standard'
local dDownUpElevation = Edge.dElevation
-- la normale della faccia permette di lavorare in modo standard, ma potrebbero esserci altre condizioni che fanno fallire il taglio
if not IsFaceZOutOfRange( Face.vtN, Tool) then
-- TODO verifica collisione carro Z, collisione traversa PF, collisione 'C' Fast... La riduzione percorso cambia questo test?
return true, sBladeEngagement
end
-- faccia non lavorabile in modo standard: si verifica se il DownUp è fattibile
-- la normale della faccia non permette il DownUp: non lavorabile in DownUp (se taglio DownUp la faccia è lavorata al contrario, vtN opposta)
if IsFaceZOutOfRange( -Face.vtN, Tool) then
return false
end
-- faccia non rettangolare: non lavorabile in DownUp
if not FaceData.IsFaceRectangular( Face) then
return false
end
-- orientamento faccia / utensile compatibili con DownUp: lavorabile, si calcola l'elevazione reale per DownUp e si ritorna
if IsOrientationOkForDownUp( Face, Edge, b3Raw) then
sBladeEngagement = 'DownUp'
dDownUpElevation = FaceData.GetEdgeElevationInBBox( Face, Edge, b3Raw )
return true, sBladeEngagement, dDownUpElevation
end
return false
end
-- dato un certo offset radiale (uscente) e la distanza da mantenere dallo spigolo, calcola di quanto la lama deve arretrare lateralmente rispetto al centro per lavorare il lato
function FACEBYBLADE.GetPathReductionLength( nToolIndex, dRadialOffset, OptionalParameters)
local Tool = TOOLS[nToolIndex]
local dToolRadius = Tool.dDiameter / 2
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local dExtra = OptionalParameters.dExtra or BeamData.CUT_EXTRA
-- calcolo
local dReductionLength = -dExtra
if dRadialOffset > dExtra + 10 * GEO.EPS_SMALL then
dReductionLength = sqrt( ( dToolRadius - dExtra)^2 - ( dToolRadius - dRadialOffset)^2)
end
return dReductionLength
end
-- data la lunghezza del lato da lavorare e la distanza da mantenere dallo spigolo, calcola di quanto la lama deve andare oltre per lavorare il lato
function FACEBYBLADE.GetRadialOffsetForGuillotine( nToolIndex, dEdgeLength, OptionalParameters)
local Tool = TOOLS[nToolIndex]
local dToolRadius = Tool.dDiameter / 2
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local dExtra = OptionalParameters.dExtra or BeamData.CUT_EXTRA
-- calcolo
local dRadialOffset = dToolRadius - sqrt( ( dToolRadius - dExtra)^2 - ( dEdgeLength / 2)^2)
if dRadialOffset < dExtra + 10 * GEO.EPS_SMALL then
dRadialOffset = GEO.INFINITO
end
return dRadialOffset
end
function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
local Cutting = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
Cutting.bIsApplicable = true
Cutting.dDepthToMachine = 0
Cutting.sMessage = ''
Cutting.idProc = Proc.id
Cutting.dResidualDepth = EdgeToMachine.dElevation
Cutting.dCompletionPercentage = 0
Cutting.dToolMarkLength = 0
Cutting.sEdgeType = EdgeToMachine.sType
Cutting.nFeatureSegment = 1
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false
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 bReduceBladePath = OptionalParameters.bReduceBladePath or false
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 sUserNotes = OptionalParameters.sUserNotes or ''
-- lunghezze, direzioni e punti caratteristici della lavorazione e del lato lavorato
Cutting.dEdgeLength = EdgeToMachine.dLength
if OppositeToolDirectionMode == 'Enabled' then
Cutting.vtToolDirection = -EdgeToMachine.vtN
else
Cutting.vtToolDirection = EdgeToMachine.vtN
end
Cutting.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
-- TODO conviene spostare questi calcoli nel FaceData?
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Cutting.vtToolDirection, GDB_ID.ROOT)
-- ricerca utensile
if nToolIndex then
Cutting.nToolIndex = nToolIndex
local dDownUpElevation = dDepthToMachine
-- si determina se il taglio è fattibile e il modo di lavorare della lama
Cutting.bIsApplicable, Cutting.sBladeEngagement, dDownUpElevation = FACEBYBLADE.GetBladeEngagement( FaceToMachine, EdgeToMachine, Part.b3Raw, TOOLS[nToolIndex])
-- orientamento non raggiungibile o elevazione eccessiva per DownUp: non applicabile
if not Cutting.bIsApplicable
or ( Cutting.sBladeEngagement == 'DownUp'
and ( dDownUpElevation - ( EdgeToMachine.dElevation - dDepthToMachine)) > TOOLS[nToolIndex].dMaxMaterial - 10 * GEO.EPS_SMALL) then
Cutting.sMessage = 'Orientation not reachable'
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
-- si prende la lama migliore che può effettuare questo taglio, senza particolari analisi
else
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = dDepthToMachine
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = true
ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade
ToolSearchParameters.FaceToMachine = FaceToMachine
ToolSearchParameters.EdgeToMachine = EdgeToMachine
local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
Cutting.nToolIndex = ToolInfo.nToolIndex
Cutting.sBladeEngagement = ToolInfo.sBladeEngagement
end
if not TOOLS[Cutting.nToolIndex] then
Cutting.sMessage = 'Blade not found'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
-- verifica dimensioni tasca compatibili
-- se tasca meno spessa della lama la lavorazione non è applicabile
if OptionalParameters.dPocketHeight and ( TOOLS[Cutting.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL) then
Cutting.sMessage = 'Pocket too narrow for blade thickness'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
-- se tasca chiusa da entrambi i lati e più stretta della lama la lavorazione non è applicabile
if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
Cutting.sMessage = 'Pocket too narrow for blade diameter'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
end
-- parametri della lavorazione
-- profondità (parametro DEPTH)
Cutting.sDepth = sDepth
-- inizio e fine aperti o chiusi
Cutting.bIsStartClosed = not EdgeToMachine.bIsStartOpen
Cutting.bIsEndClosed = not EdgeToMachine.bIsEndOpen
-- lato di lavoro e inversione per avere taglio concorde
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
-- se OppositeToolDirectionMode è Optimized, se possibile e necessario, si attiva la lavorazione dal lato opposto per garantire taglio concorde e verso l'alto (massima qualità)
if ( OppositeToolDirectionMode == 'Optimized') and ( Proc.nFct == 1) and ( FaceData.IsFaceRhomboid( FaceToMachine)) then
OppositeToolDirectionMode = 'Disabled'
-- la direzione di percorrenza del lato deve essere verso l'alto; bInvert va considerata perchè inverte la direzione di percorrenza
if ( Cutting.bInvert and Cutting.vtEdgeDirection:getZ() > 100 * GEO.EPS_SMALL)
or ( ( not Cutting.bInvert) and Cutting.vtEdgeDirection:getZ() < -100 * GEO.EPS_SMALL) then
-- si attiva OppositeToolDirection solo se il taglio è fattibile anche in direzione opposta
local EdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( FaceToMachine.Edges, -Cutting.vtToolDirection)
local bIsApplicableOpposite, sBladeEngagementOpposite, dDownUpElevationOpposite = FACEBYBLADE.GetBladeEngagement( FaceToMachine, EdgeToMachineOpposite, Part.b3Raw, TOOLS[nToolIndex])
if bIsApplicableOpposite and ( sBladeEngagementOpposite == Cutting.sBladeEngagement) then
if sBladeEngagementOpposite ~= 'DownUp'
or ( ( dDownUpElevationOpposite - ( EdgeToMachine.dElevation - dDepthToMachine)) > TOOLS[nToolIndex].dMaxMaterial - 10 * GEO.EPS_SMALL) then
OppositeToolDirectionMode = 'Enabled'
Cutting.sBladeEngagement = sBladeEngagementOpposite
Cutting.vtToolDirection = -EdgeToMachine.vtN
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Cutting.vtToolDirection, GDB_ID.ROOT)
Cutting.bInvert = not Cutting.bInvert
end
-- se non possibile taglio opposto, si setta per tagliare verso l'alto
else
if Cutting.nWorkside == MCH_MILL_WS.RIGHT then
Cutting.nWorkside = MCH_MILL_WS.LEFT
Cutting.bInvert = false
else
Cutting.nWorkside = MCH_MILL_WS.RIGHT
Cutting.bInvert = true
end
end
end
elseif OppositeToolDirectionMode == 'Enabled' then
Cutting.bInvert = not Cutting.bInvert
end
-- ToolInvert
if Cutting.sBladeEngagement == 'DownUp' then
Cutting.bToolInvert = true
Cutting.bInvert = not Cutting.bInvert
end
-- profondità da lavorare e offset radiale
if OptionalParameters.dPocketHeight then
if TOOLS[Cutting.nToolIndex].dMaxDepth > dDepthToMachine - 10 * GEO.EPS_SMALL then
-- TODO la depth dovrebbe essere quella del machining
Cutting.dDepthToMachine = dDepthToMachine
Cutting.dResidualDepth = 0
if OppositeToolDirectionMode == 'Enabled' then
Cutting.dRadialOffset = -dDepthToMachine
else
Cutting.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
end
else
Cutting.dDepthToMachine = TOOLS[Cutting.nToolIndex].dMaxDepth - 1
Cutting.dResidualDepth = dDepthToMachine - Cutting.dDepthToMachine
if OppositeToolDirectionMode == 'Enabled' then
Cutting.dRadialOffset = -Cutting.dDepthToMachine
else
Cutting.dRadialOffset = EdgeToMachine.dElevation - Cutting.dDepthToMachine
end
end
else
Cutting.dDepthToMachine = dDepthToMachine
Cutting.dResidualDepth = 0
Cutting.sEdgeUsage = 'Standard'
if bReduceBladePath
and ( Proc.nFct == 1)
and FaceData.IsFaceRectangular( FaceToMachine) then
local bIsTopBlade = TOOLS[nToolIndex].SetupInfo.HeadType.bTop
Cutting.dMaxRadialOffset = TOOLS[nToolIndex].dMaxMaterial - Cutting.dDepthToMachine - BeamData.CUT_SIC
Cutting.dRadialOffsetGuillotine = FACEBYBLADE.GetRadialOffsetForGuillotine( nToolIndex, EdgeToMachine.dLength)
if Cutting.dMaxRadialOffset > 10 * GEO.EPS_SMALL then
-- taglio a ghigliottina
if bIsTopBlade and ( Cutting.dRadialOffsetGuillotine < Cutting.dMaxRadialOffset - 10 * GEO.EPS_SMALL) then
dDepthToMachine = Cutting.dDepthToMachine + Cutting.dRadialOffsetGuillotine
Cutting.sEdgeUsage = 'Guillotine'
-- taglio ridotto
else
dDepthToMachine = Cutting.dDepthToMachine + Cutting.dMaxRadialOffset
Cutting.sEdgeUsage = 'Reduced'
end
end
end
if OppositeToolDirectionMode == 'Enabled' then
Cutting.dRadialOffset = -dDepthToMachine
else
Cutting.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
end
end
-- completamento
Cutting.dCompletionPercentage = ( 1 - Cutting.dResidualDepth / Cutting.dDepthToMachine) * 100
-- 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.dStep * Cutting.Steps.nCount - 10 * GEO.EPS_SMALL
if Cutting.bToolInvert then
if Cutting.Steps.nCount > 1 then
Cutting.dLongitudinalOffset = - dPocketHeight
else
Cutting.dLongitudinalOffset = - TOOLS[Cutting.nToolIndex].dThickness - dLongitudinalOffset
end
else
Cutting.dLongitudinalOffset = dLongitudinalOffset
end
-- distanza di sicurezza
Cutting.dStartSafetyLength = BeamData.CUT_SIC
-- overlap
Cutting.dOverlap = 0
-- EdgeUse e frame lavorazione
if OppositeToolDirectionMode == 'Enabled' then
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Cutting.vtToolDirection)
--Cutting.vtFaceUse = -Cutting.vtToolDirection
Cutting.nEdgesFaceUse = EdgeToMachine.id
else
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( Cutting.vtToolDirection)
--Cutting.vtFaceUse = Cutting.vtToolDirection
Cutting.nEdgesFaceUse = EdgeToMachine.id
end
-- SCC
Cutting.nSCC = GetSCC( Cutting.vtToolDirection, Cutting.vtEdgeDirection, FaceToMachine.vtN)
-- asse bloccato
Cutting.sBlockedAxis = BeamLib.GetBlockedAxis( Cutting.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN, EgtIf( FaceToMachine.vtN:getX() > 0, X_AX(), -X_AX()))
-- eventuale step orizzontale
Cutting.CloneStepsRadial = {}
if not dRadialStepSpan then
dRadialStepSpan = Cutting.dDepthToMachine
end
if dRadialStepSpan > 10 * GEO.EPS_SMALL and TOOLS[Cutting.nToolIndex].dSideStep then
Cutting.CloneStepsRadial = MachiningLib.GetMachiningSteps( dRadialStepSpan, TOOLS[Cutting.nToolIndex].dSideStep)
else
Cutting.CloneStepsRadial.nCount = 1
Cutting.CloneStepsRadial.dStep = Cutting.dDepthToMachine
end
-- approccio e retrazione
Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( Cutting, EdgeToMachine, bIsSplitFeature)
-- lunghezza lavorata
-- TODO per il calcolo del dLengthOnX si deve correggere con allungamento / accorciamento percorso
Cutting.dLengthToMachine = EdgeToMachine.dLength + Cutting.LeadIn.dStartAddLength + Cutting.LeadOut.dEndAddLength
local b3BoxEdge = BBox3d( Cutting.ptEdge1, Cutting.ptEdge2)
Cutting.dLengthOnX = b3BoxEdge:getDimX()
Cutting.dTimeToMachine, Cutting.dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Cutting, Part)
-- lunghezza impronta lama
if Cutting.bIsStartClosed and Cutting.bIsEndClosed then
Cutting.dToolMarkLength = abs( min( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength))
elseif Cutting.bIsStartClosed then
Cutting.dToolMarkLength = abs( Cutting.LeadIn.dStartAddLength)
elseif Cutting.bIsEndClosed then
Cutting.dToolMarkLength = abs( Cutting.LeadOut.dEndAddLength)
end
-- area lavorata
Cutting.dAreaToMachine = min( EdgeToMachine.dElevation, Cutting.dDepthToMachine) * ( min( Cutting.dEdgeLength, Cutting.dLengthToMachine + 2 * Cutting.dToolMarkLength))
-- geometria
Cutting.Geometry = {{Cutting.idProc, FaceToMachine.id}}
-- note utente
Cutting.sUserNotes = sUserNotes
-- nome operazione
Cutting.sOperationName = 'Cut_' .. ( EgtGetName( Cutting.idProc) or tostring( Cutting.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
-- TODO valutare se fare funzione a parte
local bIsTruncatingCutOnTail = Proc.Topology and ( Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'TailCut') and Proc.AffectedFaces.bLeft
if bIsTruncatingCutOnTail then
Cutting.sStage = 'AfterTail'
elseif Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Cutting.vtToolDirection:getX() < 0.707)) then
local dLengthOnX = Cutting.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( Cutting)
local dAddLengthLeftSide = Cutting.LeadOut.dEndAddLength
local dAddLengthToReduce = sqrt( Cutting.dDepthToMachine * TOOLS[Cutting.nToolIndex].dDiameter - Cutting.dDepthToMachine * Cutting.dDepthToMachine)
if bStartLeft then
dAddLengthLeftSide = Cutting.LeadIn.dStartAddLength
end
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Cutting.sStage = 'AfterTail'
else
Cutting.bIsApplicable = false
end
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Cutting.sStage = 'AfterTail'
else
if bStartLeft then
Cutting.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
else
Cutting.LeadOut.dEndAddLength = - dAddLengthToReduce + dExtendAfterTail
end
end
end
end
return Cutting
end
-------------------------------------------------------------------------------------------------------------
return FACEBYBLADE