-- Strategia: STR0008 -- Descrizione -- Svuotatura tasca -- Feature tipo Mortise (con raggio) -- carico librerie local BeamLib = require( 'BeamLib') local BeamData = require( 'BeamData') 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.nQuality = FeatureLib.GetFeatureQuality( '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 } 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 } 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.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.nCompletionIndex = 0 Strategy.Result.dMRR = 0 Strategy.Result.nQuality = 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 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 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 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 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.nCompletionIndex = 0 Strategy.Result.dMRR = 0 Strategy.Result.nQuality = 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.nCompletionIndex = 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, 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 = {} Pocketing.Steps = {} Pocketing.LeadIn = {} Pocketing.nType = 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