353 lines
18 KiB
Lua
353 lines
18 KiB
Lua
-- Strategia: STR0008
|
|
-- Descrizione
|
|
-- Svuotatura tasca
|
|
-- Feature tipo Mortise (con raggio)
|
|
|
|
|
|
-- carico librerie
|
|
local BeamLib = require( 'BeamLib')
|
|
local BeamData = require( 'BeamDataNew')
|
|
local MachiningLib = require( 'MachiningLib')
|
|
local FeatureLib = require( 'FeatureLib')
|
|
-- strategie di base
|
|
local BladeToWaste = require('BLADETOWASTE')
|
|
|
|
-- Tabella per definizione modulo
|
|
local STR0008 = {}
|
|
local Strategy = {}
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function IsTopologyOk( Proc)
|
|
if Proc.Topology.sName == 'Pocket-Round' or
|
|
Proc.Topology.sName == 'Pocket-Round-Through' or
|
|
Proc.Topology.sName == 'Pocket-Round-Front' then
|
|
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- TODO vedere se leggere direttamente la quality dell'utensile e mediarle nel caso di utensile doppio
|
|
local function GetBestPocketingStrategy( Proc, Part)
|
|
local Machining = { Cutting = {}, Pocketing = {}}
|
|
local Result = { Cutting = {}, Pocketing = {}}
|
|
local ToolSearchParameters = {}
|
|
|
|
Machining.sTypeMachining = 'None' -- Bottom\ Side1\ Side2\ Side1-Side2\ None
|
|
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
|
|
|
|
-- in caso sia una mortasa frontale, bisogna lavorare il taglio
|
|
if Proc.FeatureInfo.bIsFrontMortise then
|
|
-- scelta automatica lavorazione. Non viene mai scelta la motosega
|
|
if Strategy.Parameters.sCuttingStrategy == 'AUTO' then
|
|
-- creo piano di taglio sulla testa del tenone
|
|
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
|
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
|
|
bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
|
}
|
|
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idMortiseCutPlane, Part, OptionalParameters)
|
|
-- se presente almeno una lavorazione e completo, il taglio è applicabile
|
|
if #Machining.Cutting > 0 and Result.Cutting and Result.Cutting.sStatus == 'Completed' then
|
|
Machining.Cutting.bIsApplicable = true
|
|
end
|
|
-- se non possibile di lama si prova con fresa
|
|
if not Machining.Cutting or #Machining.Cutting == 0 then
|
|
Machining.bCuttingWithMill = true
|
|
end
|
|
-- lavorazione forzata con utensile lama
|
|
elseif Strategy.Parameters.sCuttingStrategy == 'BLADE_FORCED' then
|
|
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
|
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
|
|
bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
|
}
|
|
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idMortiseCutPlane, Part, OptionalParameters)
|
|
-- se presente almeno una lavorazione e completo, il taglio è applicabile
|
|
if #Machining.Cutting > 0 and Result.Cutting.sStatus == 'Completed' then
|
|
Machining.Cutting.bIsApplicable = true
|
|
else
|
|
Machining.Cutting.bIsApplicable = false
|
|
end
|
|
-- lavorazione forzata con utensile fresa
|
|
elseif Strategy.Parameters.sCuttingStrategy == 'MILL_FORCED' then
|
|
Machining.bCuttingWithMill = true
|
|
-- lavorazione forzata con utensile motosega
|
|
elseif Strategy.Parameters.sCuttingStrategy == 'CHAINSAW_FORCED' then
|
|
-- DA FARE!!
|
|
end
|
|
|
|
-- === ricerca utensile per svuotare taglio iniziale, se taglio non possibile ===
|
|
if Machining.bCuttingWithMill then
|
|
-- se può essere fatto di fresa
|
|
if not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit then
|
|
ToolSearchParameters = {}
|
|
ToolSearchParameters.dElevation = 0
|
|
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtMortiseN
|
|
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
|
|
ToolSearchParameters.sMillShape = 'STANDARD'
|
|
Machining.Cutting.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
|
if Machining.Cutting.ToolInfo.nToolIndex then
|
|
Machining.Cutting.bIsApplicable = true
|
|
local ParametersMRR = {}
|
|
ParametersMRR.nToolIndex = Machining.Cutting.ToolInfo.nToolIndex
|
|
Strategy.Result.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
|
Strategy.Result.sStatus = 'Completed'
|
|
end
|
|
-- alterimenti esco subito
|
|
else
|
|
Strategy.Result.sStatus = 'Not-Applicable'
|
|
Strategy.Result.dCompletionIndex = 0
|
|
Strategy.Result.dMRR = 0
|
|
Strategy.Result.dQuality = 0
|
|
Strategy.Result.sInfo = 'Mill not found'
|
|
return Machining
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ===== RICERCA UTENSILE =====
|
|
-- cerco utensile per lavorare faccia Bottom
|
|
local Milling = {}
|
|
Milling.bIsApplicable = false
|
|
ToolSearchParameters = {}
|
|
ToolSearchParameters.sMillShape = 'STANDARD'
|
|
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dMortiseMinRadius * 2
|
|
ToolSearchParameters.dElevation = Proc.FeatureInfo.dMortiseDepth + EgtIf( Proc.Topology.sName == 'Pocket-Round-Through', BeamData.CUT_EXTRA, 0)
|
|
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtMortiseN
|
|
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Pocketing')
|
|
Milling.ToolInfo = {}
|
|
-- si cerca prima utensile per lavorare in accordo con normale mortasa
|
|
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
|
Milling.idFaceToMachine = 0 -- ATTENZIONE: Per convenzione, la faccia di fondo della mortasa ha sempre indice 0
|
|
Milling.idProc = Proc.id
|
|
Milling.vtFaceNormal = Proc.FeatureInfo.vtMortiseN
|
|
Milling.dElevation = Proc.FeatureInfo.dMortiseDepth
|
|
if Milling.ToolInfo.nToolIndex then
|
|
Milling.bIsApplicable = true
|
|
end
|
|
table.insert( Machining.Pocketing, Milling)
|
|
|
|
-- si cerca utensile che lavora dal lato opposto
|
|
Milling = {}
|
|
Milling.bIsApplicable = false
|
|
if Proc.Topology.sName == 'Pocket-Round-Through' then
|
|
ToolSearchParameters = {}
|
|
ToolSearchParameters.sMillShape = 'STANDARD'
|
|
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dMortiseMinRadius * 2
|
|
ToolSearchParameters.dElevation = Proc.FeatureInfo.dMortiseDepth + BeamData.CUT_EXTRA
|
|
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtMortiseN
|
|
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Pocketing')
|
|
Milling.ToolInfo = {}
|
|
-- si cerca prima utensile per lavorare in accordo con normale mortasa
|
|
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
|
Milling.idFaceToMachine = 0 -- ATTENZIONE: Per convenzione, la faccia di fondo della mortasa ha sempre indice 0
|
|
Milling.idProc = Proc.id
|
|
Milling.vtFaceNormal = -Proc.FeatureInfo.vtMortiseN
|
|
Milling.bToolInvert = true
|
|
Milling.dElevation = Proc.FeatureInfo.dMortiseDepth
|
|
if Milling.ToolInfo.nToolIndex then
|
|
Milling.bIsApplicable = true
|
|
end
|
|
end
|
|
table.insert( Machining.Pocketing, Milling)
|
|
|
|
|
|
-- tipo di lavorazione
|
|
-- solo svuotatura diretta come normale mortasa, completa
|
|
if Machining.Pocketing[1].bIsApplicable and Machining.Pocketing[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
|
if Proc.Topology.sName == 'Pocket-Round-Through' then
|
|
Machining.sTypeMachining = 'Side1'
|
|
Machining.Pocketing[1].sDepth = BeamData.CUT_EXTRA
|
|
else
|
|
Machining.sTypeMachining = 'Bottom'
|
|
Machining.Pocketing[1].sDepth = -Strategy.Parameters.dOverMatOnLength
|
|
end
|
|
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo)
|
|
Machining.dResidual = 0
|
|
Machining.Pocketing[2].bIsApplicable = false
|
|
-- solo svuotatura diretta opposta alla normale mortasa, completa
|
|
elseif Machining.Pocketing[2].bIsApplicable and Machining.Pocketing[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
|
Machining.sTypeMachining = 'Side2'
|
|
Machining.dResidual = 0
|
|
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth + BeamData.CUT_EXTRA
|
|
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo)
|
|
Machining.Pocketing[1].bIsApplicable = false
|
|
-- solo svuotatura diretta come normale mortasa, incompleta
|
|
elseif Machining.Pocketing[1].bIsApplicable and not Machining.Pocketing[2].bIsApplicable then
|
|
Machining.sTypeMachining = 'Side1'
|
|
Machining.dResidual = Machining.Pocketing[1].ToolInfo.dResidualDepth
|
|
Machining.Pocketing[1].sDepth = -Machining.dResidual
|
|
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo)
|
|
-- solo svuotatura diretta come normale mortasa, incompleta
|
|
elseif Machining.Pocketing[2].bIsApplicable and not Machining.Pocketing[1].bIsApplicable then
|
|
Machining.sTypeMachining = 'Side2'
|
|
Machining.dResidual = Machining.Pocketing[2].ToolInfo.dResidualDepth
|
|
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth - Machining.dResidual
|
|
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo)
|
|
-- lavorazione da entrambi i lati
|
|
elseif Machining.Pocketing[1].bIsApplicable and Machining.Pocketing[2].bIsApplicable then
|
|
Machining.sTypeMachining = 'Side1-Side2'
|
|
local dResidualMach = Machining.Pocketing[1].ToolInfo.dResidualDepth + Machining.Pocketing[2].ToolInfo.dResidualDepth - Proc.FeatureInfo.dMortiseDepth
|
|
Machining.dResidual = max( 0, dResidualMach)
|
|
-- se lavorazione non copmpleta, si entra il massimio possibile
|
|
if dResidualMach > 0 then
|
|
Machining.Pocketing[1].sDepth = -Machining.Pocketing[1].ToolInfo.dResidualDepth
|
|
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth - Machining.Pocketing[2].ToolInfo.dResidualDepth
|
|
else
|
|
Machining.Pocketing[1].sDepth = -Machining.Pocketing[1].ToolInfo.dResidualDepth + dResidualMach/2 + BeamData.CUT_EXTRA_MIN
|
|
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth - ( Machining.Pocketing[2].ToolInfo.dResidualDepth - dResidualMach/2 - BeamData.CUT_EXTRA_MIN)
|
|
end
|
|
Strategy.Result.dMRR = min( MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo), MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo))
|
|
-- altrimenti non applicabile
|
|
else
|
|
-- TODO per feature frontale, ha senso voler applicare solo il taglio e non la lavorazione della mortasatura? Adesso non fa nulla
|
|
Strategy.Result.sStatus = 'Not-Applicable'
|
|
Strategy.Result.dCompletionIndex = 0
|
|
Strategy.Result.dMRR = 0
|
|
Strategy.Result.dQuality = 0
|
|
Strategy.Result.sInfo = 'Mill not found'
|
|
return Machining
|
|
end
|
|
|
|
-- se completo
|
|
if Machining.dResidual < 10 * GEO.EPS_SMALL then
|
|
Strategy.Result.sStatus = 'Completed'
|
|
Strategy.Result.dCompletionPercentage = 100
|
|
else
|
|
Strategy.Result.sStatus = 'Not-Completed'
|
|
Strategy.Result.sInfo = 'Mortise not complete, left ' .. ceil( Machining.dResidual) .. 'mm'
|
|
Strategy.Result.dCompletionPercentage = ( 1 - Machining.dResidual / Proc.FeatureInfo.dMortiseDepth) * 100
|
|
end
|
|
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
|
|
|
|
return Machining
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function STR0008.Make( bAddMachining, Proc, Part, CustomParameters)
|
|
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
|
|
local StrategyLib = {}
|
|
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
|
|
Strategy.sName = StrategyLib.Config.sStrategyId
|
|
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
|
|
Strategy.Machining = {}
|
|
Strategy.Result = {}
|
|
|
|
if not IsTopologyOk( Proc) then
|
|
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not implemented'
|
|
EgtOutLog( sErr)
|
|
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
|
|
return false, Strategy.Result
|
|
end
|
|
|
|
local bAreAllMachiningsAdded = true
|
|
local Pocketing = {}
|
|
|
|
-- controllo conformità offset mortasa
|
|
Strategy.Parameters.dOverMatOnRadius = EgtClamp( Strategy.Parameters.dOverMatOnRadius, -5, 5)
|
|
Strategy.Parameters.dOverMatOnLength = EgtClamp( Strategy.Parameters.dOverMatOnLength, -2, 2)
|
|
|
|
-- calcolo se la lavorazione della mortasa può essere spostata dopo taglio di coda
|
|
local dLengthOnX = Proc.b3Box:getDimX()
|
|
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
|
|
|
|
-- se mortasa frontale, verifico che esista faccia di taglio
|
|
if Proc.FeatureInfo.bIsFrontMortise then
|
|
-- verifico esista la faccia di taglio
|
|
local ptCutC, vtCutN = EgtSurfTmFacetCenter( Proc.id, 1, GDB_ID.ROOT)
|
|
if ptCutC and vtCutN and AreSameVectorApprox( Proc.FeatureInfo.vtMortiseN, vtCutN) then
|
|
-- recupero gruppo per geometria addizionale
|
|
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
|
|
Strategy.idMortiseCutPlane = EgtSurfTmPlaneInBBox( nAddGrpId, ptCutC, vtCutN, Part.b3Part, GDB_RT.GLOB)
|
|
end
|
|
end
|
|
|
|
Strategy.Machining = GetBestPocketingStrategy( Proc, Part)
|
|
|
|
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
|
|
-- se mortasa frontale si fa taglio di lama
|
|
if Proc.FeatureInfo.bIsFrontMortise then
|
|
-- taglio in lunghezza sulla faccia frontale
|
|
if Strategy.Machining.Cutting.bIsApplicable then
|
|
OptionalParameters = {}
|
|
|
|
-- se cutting da fare come svuotatura
|
|
if Strategy.Machining.bCuttingWithMill then
|
|
Strategy.Machining.Cutting.Steps = {}
|
|
Strategy.Machining.Cutting.LeadIn = {}
|
|
Strategy.Machining.Cutting.nType = MCH_MY.POCKETING
|
|
Strategy.Machining.Cutting.nSubType = MCH_POCK_SUB.SPIRALIN
|
|
Strategy.Machining.Cutting.LeadIn.nType = MCH_POCK_LI.ZIGZAG
|
|
Strategy.Machining.Cutting.Steps.dStep = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dStep
|
|
Strategy.Machining.Cutting.Steps.dSideStep = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dSideStep
|
|
Strategy.Machining.Cutting.nToolIndex = Strategy.Machining.Cutting.ToolInfo.nToolIndex
|
|
Strategy.Machining.Cutting.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
|
|
Strategy.Machining.Cutting.LeadIn.dElevation = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
|
|
Strategy.Machining.Cutting.sDepth = 0
|
|
Strategy.Machining.Cutting.Geometry = {{ Strategy.idMortiseCutPlane, 0}}
|
|
Strategy.Machining.Cutting.vtToolDirection = Proc.FeatureInfo.vtMortiseN
|
|
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
|
Strategy.Machining.Cutting.sStage = 'AfterTail'
|
|
end
|
|
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting)
|
|
|
|
-- taglio di lama
|
|
else
|
|
for i = 1, #Strategy.Machining.Cutting do
|
|
if Strategy.Machining.Cutting.bIsApplicable then
|
|
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
|
Strategy.Machining.Cutting[i].sStage = 'AfterTail'
|
|
end
|
|
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting[i])
|
|
if not bIsMachiningAdded then
|
|
bAreAllMachiningsAdded = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- si applicano le lavorazioni di svuotatura
|
|
for i = 1, #Strategy.Machining.Pocketing do
|
|
if Strategy.Machining.Pocketing[i].bIsApplicable then
|
|
Pocketing = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
|
|
Pocketing.nSubType = MCH_POCK_SUB.SPIRALOUT
|
|
Pocketing.LeadIn.nType = MCH_POCK_LI.ZIGZAG
|
|
Pocketing.Steps.dStep = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dStep
|
|
Pocketing.Steps.dSideStep = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dSideStep
|
|
Pocketing.nToolIndex = Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex
|
|
Pocketing.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dDiameter/2
|
|
Pocketing.LeadIn.dElevation = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dDiameter/2
|
|
Pocketing.sDepth = Strategy.Machining.Pocketing[i].sDepth
|
|
Pocketing.dRadialOffset = Strategy.Parameters.dOverMatOnRadius
|
|
Pocketing.bToolInvert = Strategy.Machining.Pocketing[i].bToolInvert
|
|
|
|
if Proc.FeatureInfo.bIsFrontMortise then
|
|
Pocketing.dMaxElev = Proc.FeatureInfo.dMortiseDepth
|
|
end
|
|
-- se feature passante, si applica la lavorazione alla curva
|
|
if Proc.Topology.sName == 'Pocket-Round-Through' then
|
|
Pocketing.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
|
else
|
|
Pocketing.Geometry = {{ Strategy.Machining.Pocketing[i].idProc, Strategy.Machining.Pocketing[i].idFaceToMachine}}
|
|
end
|
|
Pocketing.vtToolDirection = Strategy.Machining.Pocketing[i].vtFaceNormal
|
|
|
|
-- se è aperta sulla coda, dico che deve essere fatta dopo la separazione
|
|
if Proc.AffectedFaces.bLeft then
|
|
Pocketing.sStage = 'AfterTail'
|
|
end
|
|
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Pocketing)
|
|
end
|
|
end
|
|
else
|
|
bAreAllMachiningsAdded = false
|
|
end
|
|
|
|
return bAreAllMachiningsAdded, Strategy.Result
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
|
|
return STR0008 |