-- Strategia: STR0002 -- Descrizione -- Svuotatura tasca -- Feature tipo LapJoint ------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------- -- TODO -- 1 - Inserire antischeggia (fresa o lama) -- 2 - Modalità svuotatura con fresa grande e spigoli con fresa piccola -- 3 - Smusso a V -- 4 - Finitura con motosega (se la fresa non completa) ------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------- -- carico librerie local BeamLib = require( 'BeamLib') local BeamData = require( 'BeamDataNew') local MachiningLib = require( 'MachiningLib') local FeatureLib = require( 'FeatureLib') local AntiSplintOnFace = require( 'ANTISPLINTONFACE') -- Tabella per definizione modulo local STR0002 = {} local Strategy = {} ------------------------------------------------------------------------------------------------------------- local function IsTopologyOk( Proc) if Proc.Topology.sName == 'Pocket-5-Blind' or Proc.Topology.sName == 'RafterNotch-5-Through' or Proc.Topology.sName == 'Tunnel-4-Through' or Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Groove-3-Blind' or Proc.Topology.sName == 'Bevel-3-Blind' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'DoubleBevel-2-Through' or Proc.Topology.sName == 'VGroove-2-Through' or Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'Bevel-1-Through' then return true else return false end end ------------------------------------------------------------------------------------------------------------- local function GetSCC( Proc, Pocketing) local nSCC if Pocketing.vtToolDirection:getY() > 0 then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end return nSCC end ------------------------------------------------------------------------------------------------------------- local function CalcMachinedPercentage( Proc, Machining) -- se non ci sono lavorazioni esco subito if Machining.sTypeMachining == 'None' then return 0 end local dTotalPercentage = 0 local dPercentageBottom = 0 if Machining[1].bIsApplicable then dTotalPercentage = ( Machining[1].dElevation - Machining[1].ToolInfo.dResidualDepth) / Machining[1].dElevation dPercentageBottom = dTotalPercentage end if Machining[2].bIsApplicable then local dAbsPercentage = ( Machining[2].dElevation - Machining[2].ToolInfo.dResidualDepth) / Machining[2].dElevation dTotalPercentage = dTotalPercentage + ( 1 - dTotalPercentage) * dAbsPercentage end if Machining[3].bIsApplicable then local dAbsPercentage if Machining[3].bMachAppliedToTunnelFace then dAbsPercentage = ( Machining[3].dElevation - Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation) / Machining[3].dElevation else dAbsPercentage = ( Machining[3].dElevation - Machining[3].ToolInfo.dResidualDepth) / Machining[3].dElevation end dTotalPercentage = dTotalPercentage + ( 1 - dPercentageBottom) * dAbsPercentage end if Machining[4].bIsApplicable then local dAbsPercentage if Machining[3].bMachAppliedToTunnelFace then dAbsPercentage = ( Machining[4].dElevation - Machining[4].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation) / Machining[4].dElevation else dAbsPercentage = ( Machining[4].dElevation - Machining[4].ToolInfo.dResidualDepth) / Machining[4].dElevation end dTotalPercentage = dTotalPercentage + ( 1 - dPercentageBottom) * dAbsPercentage end return dTotalPercentage * 100 end ------------------------------------------------------------------------------------------------------------- -- TODO va gestita meglio la decisione delle facce da lavorare local function GetBestPocketingStrategy( Proc, Part) -- imposto parametri di ricerca utensile in base a topologia local Machining = {} local Milling = {} local ToolSearchParameters = {} ToolSearchParameters.sMillShape = 'STANDARD' Machining.sTypeMachining = 'None' -- Bottom-Side1-Side2\ Bottom-Bottom2\ Bottom-Side1\ Bottom-Side2\ Side1-Side2\ Bottom\ Side1 \ Side2 \ None Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'STD') -- caso speciale Tunnel che non ha faccia bottom if Proc.Topology.sName == 'Tunnel-4-Through' then local dFaceLength = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dLMinRectangle local dFaceWidth = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dWMinRectangle ToolSearchParameters.sType = 'MILL_STD' ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceLength, dFaceWidth) elseif Proc.Topology.sName == 'RafterNotch-5-Through' then ToolSearchParameters.sType = 'MILL_STD' ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, Proc.FeatureInfo.dFaceLength / 2) -- imposto dati per cercare la fresa migliore elseif Proc.Topology.sName == 'Pocket-5-Blind' then local dFaceWidth, dFaceLength if Proc.MainFaces.BottomFaces[1].MainEdges then dFaceWidth = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength dFaceLength = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength else dFaceWidth = Proc.MainFaces.BottomFaces[1].dWMinRectangle dFaceLength = Proc.MainFaces.BottomFaces[1].dLMinRectangle end ToolSearchParameters.sType = 'MILL_STD' ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceLength, dFaceWidth) -- cerco fresa che può anche non lavorare di testa elseif Proc.Topology.sName == 'Groove-4-Blind' then local dFaceLength if Proc.MainFaces.BottomFaces[2].MainEdges then dFaceLength = Proc.MainFaces.BottomFaces[2].MainEdges.BottomEdge.dLength else dFaceLength = Proc.MainFaces.BottomFaces[2].dLMinRectangle end ToolSearchParameters.sType = 'MILL_NOTIP' ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceLength) elseif Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Bevel-3-Blind' then local dFaceLength if Proc.MainFaces.BottomFaces[1].MainEdges then dFaceLength = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength else dFaceLength = Proc.MainFaces.BottomFaces[1].dLMinRectangle end ToolSearchParameters.sType = 'MILL_NOTIP' ToolSearchParameters.dMaxToolDiameter = dFaceLength elseif Proc.Topology.sName == 'Groove-3-Blind' then ToolSearchParameters.sType = 'MILL_NOTIP' ToolSearchParameters.dMaxToolDiameter = Strategy.Parameters.dMaxCornerRadius * 2 elseif Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'DoubleBevel-2-Through' or Proc.Topology.sName == 'VGroove-2-Through' or Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'Bevel-1-Through' then ToolSearchParameters.sType = 'MILL_NOTIP' ToolSearchParameters.dMaxToolDiameter = 9999 else return nil end -- ===== RICERCA UTENSILE ===== -- cerco utensile per lavorare faccia Bottom Milling.bIsApplicable = false if Proc.Topology.sName ~= 'Tunnel-4-Through' then -- TODO in caso che la faccia crei un piano asportando tutto il materiale, si potrebbe forzare elevazione a zero e scegliere quindi fresa di diametro maggiore. -- Il discorso non vale se la feature viene spezzata o se non ancora separata, in quanto ci sarebbe comunque del materiale da considerare nell'elevazione. -- In quel caso, un 'Bevel-1-Through' è come se fosse un 'Bevel-2-Blind', quindi l'elevazione deve essere considerata. ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[1].dElevation ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[1].vtN ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing') Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[1].id Milling.bAddAntiSplint = Strategy.Parameters.bAntiSplint Milling.idProc = Proc.id Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[1].vtN Milling.dElevation = Proc.MainFaces.BottomFaces[1].dElevation Milling.ToolInfo = {} Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) if Milling.ToolInfo.nToolIndex then -- se faccia singola e feature lavorata in unica lavorazione si può sempre affondare if Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'Bevel-1-Through' then -- eventuali punti di spezzatura local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part) local bIsSplitFeature = false if #FeatureSplittingPoints > 0 then bIsSplitFeature = true end if not bIsSplitFeature then Milling.ToolInfo.dResidualDepth = 0 end end Milling.bIsApplicable = true local ParametersMRR = {} ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR) end end table.insert( Machining, Milling) -- caso speciale 'Rabbet-2-Through' seconda faccia principale Milling = {} Milling.bIsApplicable = false if Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'DoubleBevel-2-Through' or Proc.Topology.sName == 'VGroove-2-Through' then ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[2].dElevation ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[2].vtN ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing') Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[2].vtN Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id Milling.bAddAntiSplint = Strategy.Parameters.bAntiSplint Milling.idProc = Proc.id Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation Milling.ToolInfo = {} Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) if Milling.ToolInfo.nToolIndex then Milling.bIsApplicable = true local ParametersMRR = {} ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR) end end table.insert( Machining, Milling) -- cerco utensile per lavorare di fianco 1 Milling = {} Milling.bIsApplicable = false if Proc.Topology.sName ~= 'DoubleBevel-2-Through' and Proc.Topology.sName ~= 'Pocket-5-Blind' and Proc.Topology.sName ~= 'RafterNotch-5-Through' then if Proc.Topology.sName == 'Groove-4-Blind' then ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[2].dElevation ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[2].vtN Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[2].vtN Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id Milling.idProc = Proc.id Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation elseif Proc.Topology.sName == 'Groove-3-Blind' or Proc.Topology.sName == 'Bevel-3-Blind' then if Proc.MainFaces.LongFaces and Proc.MainFaces.LongFaces[1] then ToolSearchParameters.dElevation = Proc.MainFaces.LongFaces[1].dElevation ToolSearchParameters.vtToolDirection = Proc.MainFaces.LongFaces[1].vtN Milling.vtFaceNormal = Proc.MainFaces.LongFaces[1].vtN Milling.idFaceToMachine = Proc.MainFaces.LongFaces[1].id Milling.idProc = Proc.id Milling.dElevation = Proc.MainFaces.LongFaces[1].dElevation elseif Proc.MainFaces.BottomFaces[2] then ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[2].dElevation ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[2].vtN Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[2].vtN Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id Milling.idProc = Proc.id Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation end elseif Proc.MainFaces.TunnelAddedFaces then -- 'Tunnel-4-Through', 'Groove-3-Through', 'Rabbet-2-Through', 'VGroove-2-Through', 'Bevel-2-Blind' -- se lavoro di fianco, devo comunque rispettare il raggio massimo ToolSearchParameters.dMaxToolDiameter = min( ToolSearchParameters.dMaxToolDiameter, Strategy.Parameters.dMaxCornerRadius * 2) ToolSearchParameters.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP ToolSearchParameters.vtToolDirection = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN Milling.vtFaceNormal = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN Milling.idFaceToMachine = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].id Milling.idProc = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id Milling.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP Milling.bMachAppliedToTunnelFace = true else ToolSearchParameters.vtToolDirection = nil end ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing') Milling.ToolInfo = {} Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) if Milling.ToolInfo.nToolIndex then Milling.bIsApplicable = true local ParametersMRR = {} ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR) -- se la faccia tunnel è troppo piccola non si lavora if Milling.bMachAppliedToTunnelFace then local dLongestEdgeLength = 0 for i = 1, #Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges do if Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength > dLongestEdgeLength + 10 * GEO.EPS_SMALL then dLongestEdgeLength = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength end end if dLongestEdgeLength < TOOLS[Milling.ToolInfo.nToolIndex].dDiameter then Milling.bIsApplicable = false ParametersMRR = {} end end end end table.insert( Machining, Milling) -- cerco utensile per lavorare di fianco 2 Milling = {} Milling.bIsApplicable = false if Proc.Topology.sName ~= 'DoubleBevel-2-Through' and Proc.Topology.sName ~= 'Pocket-5-Blind' and Proc.Topology.sName ~= 'RafterNotch-5-Through' and Proc.Topology.sName ~= 'Groove-4-Blind' and Proc.Topology.sName ~= 'Bevel-3-Blind' then if Proc.MainFaces.TunnelAddedFaces then -- Tunnel-4-Through, Groove-3-Through, Rabbet-2-Through, VGroove-2-Through, 'Bevel-2-Blind' -- se lavoro di fianco, devo comunque rispettare il raggio massimo ToolSearchParameters.dMaxToolDiameter = min( ToolSearchParameters.dMaxToolDiameter, Strategy.Parameters.dMaxCornerRadius * 2) ToolSearchParameters.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP ToolSearchParameters.vtToolDirection = -Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN Milling.vtFaceNormal = -Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN Milling.idFaceToMachine = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].id Milling.idProc = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id Milling.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP Milling.bToolInvert = true Milling.bMachAppliedToTunnelFace = true elseif #Proc.MainFaces.SideFaces > 0 then -- 'Groove-3-Blind' ToolSearchParameters.dElevation = Proc.MainFaces.SideFaces[1].dElevation ToolSearchParameters.vtToolDirection = Proc.MainFaces.SideFaces[1].vtN Milling.vtFaceNormal = Proc.MainFaces.SideFaces[1].vtN Milling.idFaceToMachine = Proc.MainFaces.SideFaces[1].id Milling.idProc = Proc.id Milling.dElevation = Proc.MainFaces.SideFaces[1].dElevation else ToolSearchParameters.vtToolDirection = nil end ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing') Milling.ToolInfo = {} Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) if Milling.ToolInfo.nToolIndex then Milling.bIsApplicable = true local ParametersMRR = {} ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR) -- se la faccia tunnel è troppo piccola non si lavora if Milling.bMachAppliedToTunnelFace then local dLongestEdgeLength = 0 for i = 1, #Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges do if Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength > dLongestEdgeLength + 10 * GEO.EPS_SMALL then dLongestEdgeLength = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength end end if dLongestEdgeLength < TOOLS[Milling.ToolInfo.nToolIndex].dDiameter then Milling.bIsApplicable = false ParametersMRR = {} end end end end table.insert( Machining, Milling) -- ===== SCELTA LAVORAZIONI ===== -- TODO per DoubleBevel-2-Through si potrebbe lavorare la faccia tunnel su ogni faccia. Bisogna calcolarla!! -- caso speciale DoubleBevel-2-Through bisogna lavorare entrambe le bottom if Proc.Topology.sName == 'DoubleBevel-2-Through' then -- se entrambe applicabili significa che è completo if Machining[1].bIsApplicable and Machining[2].bIsApplicable then Machining.sTypeMachining = 'Bottom-Bottom2' Strategy.Result.sStatus = 'Completed' Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) Strategy.Result.dMRR = Machining[1].dMRR + Machining[2].dMRR / 2 Machining[1].ToolInfo.dResidualDepth = 0 Machining[2].ToolInfo.dResidualDepth = 0 return Machining else local dMachinedPrercentage = 0 -- se applicabile solo Bottom if Machining[1].bIsApplicable then Machining.sTypeMachining = 'Bottom' Strategy.Result.sStatus = 'Not-Completed' Machining[1].ToolInfo.dResidualDepth = 0 Strategy.Result.dMRR = Machining[1].dMRR dMachinedPrercentage = ( Machining[1].dElevation / ( Machining[1].dElevation + Machining[2].dElevation)) * 100 Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage) -- se applicabile solo Bottom2 elseif Machining[2].bIsApplicable then Machining.sTypeMachining = 'Bottom2' Strategy.Result.sStatus = 'Not-Completed' Machining[2].ToolInfo.dResidualDepth = 0 Strategy.Result.dMRR = Machining[2].dMRR dMachinedPrercentage = ( Machining[2].dElevation / ( Machining[1].dElevation + Machining[2].dElevation)) * 100 Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage) end Strategy.Result.sInfo = 'Machining not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%' end return Machining -- se bottom completa tutto elseif Machining[1].bIsApplicable and Machining[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then Machining.sTypeMachining = 'Bottom' Strategy.Result.sStatus = 'Completed' Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) Strategy.Result.dMRR = Machining[1].dMRR Machining[1].ToolInfo.dResidualDepth = 0 Machining[3].bIsApplicable = false Machining[4].bIsApplicable = false -- caso speciale in cui si devono lavorare due facce if ( Proc.nFct == 2 and Proc.AdjacencyMatrix[1][2] >= -89.9) and Machining[2].bIsApplicable and Machining[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then Machining.sTypeMachining = 'Bottom-Bottom2' Strategy.Result.sStatus = 'Completed' Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) Strategy.Result.dMRR = Machining[1].dMRR + Machining[2].dMRR / 2 Machining[2].ToolInfo.dResidualDepth = 0 else Machining[2].bIsApplicable = false end return Machining -- caso speciale 'Rabbet-2-Through' che ha la seconda faccia come se fosse una seconda bottom elseif ( Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' ) and Machining[2].bIsApplicable and Machining[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then Machining.sTypeMachining = 'Bottom2' Strategy.Result.sStatus = 'Completed' Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) Strategy.Result.dMRR = Machining[2].dMRR Machining[2].ToolInfo.dResidualDepth = 0 Machining[1].bIsApplicable = false Machining[3].bIsApplicable = false Machining[4].bIsApplicable = false return Machining -- se la 3 completa tutto elseif Machining[3].bIsApplicable and Machining[3].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then Machining.sTypeMachining = 'Side1' Strategy.Result.sStatus = 'Completed' Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) -- si cambia qualità perchè è rimasto il raggio sullo spigolo. E' giusto considerare non completo? if Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' then Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SEMI') end Strategy.Result.dMRR = Machining[3].dMRR if Proc.MainFaces.TunnelAddedFaces then Machining[3].ToolInfo.dResidualDepth = -( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP) else Machining[3].ToolInfo.dResidualDepth = 0 end Machining[1].bIsApplicable = false Machining[2].bIsApplicable = false Machining[4].bIsApplicable = false return Machining -- se la 4 completa tutto elseif Machining[4].bIsApplicable and Machining[4].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then Machining.sTypeMachining = 'Side2' Strategy.Result.sStatus = 'Completed' Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) -- si cambia qualità perchè è rimasto il raggio sullo spigolo. E' giusto considerare non completo? if Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' then Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SEMI') end Strategy.Result.dMRR = Machining[4].dMRR if Proc.MainFaces.TunnelAddedFaces then Machining[4].ToolInfo.dResidualDepth = -( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP) else Machining[4].ToolInfo.dResidualDepth = 0 end Machining[1].bIsApplicable = false Machining[2].bIsApplicable = false Machining[3].bIsApplicable = false return Machining -- se tunnel 3+4 completa tutto elseif Proc.MainFaces.TunnelAddedFaces and Machining[3].bIsApplicable and Machining[4].bIsApplicable and Machining[3].ToolInfo.dResidualDepth + Machining[4].ToolInfo.dResidualDepth < (Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP then Machining.sTypeMachining = 'Side1-Side2' Strategy.Result.sStatus = 'Completed' -- si suddivide l'extra lavorabile sulle due frese local dExtraMachDepth = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2 - Machining[3].ToolInfo.dResidualDepth - Machining[4].ToolInfo.dResidualDepth - BeamData.MILL_OVERLAP) / 2 Machining[3].ToolInfo.dResidualDepth = Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + dExtraMachDepth Machining[4].ToolInfo.dResidualDepth = Machining[4].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + dExtraMachDepth Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100) -- si cambia qualità perchè è rimasto il raggio sullo spigolo. E' giusto considerare non completo? if Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' then Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SEMI') end Strategy.Result.dMRR = ( Machining[3].dMRR + Machining[4].dMRR) / 2 Machining[1].bIsApplicable = false Machining[2].bIsApplicable = false return Machining end Strategy.Result.sStatus = 'Not-Completed' Strategy.Result.dMRR = 0 if Machining[1].bIsApplicable then Machining.sTypeMachining = 'Bottom' Strategy.Result.dMRR = Machining[1].dMRR end if Machining[2].bIsApplicable then Machining.sTypeMachining = EgtIf( Machining.sTypeMachining == 'None', 'Bottom2', Machining.sTypeMachining .. '-Bottom2') Strategy.Result.dMRR = ( Strategy.Result.dMRR + Machining[2].dMRR) / EgtIf( Strategy.Result.dMRR == 0, 1, 2) end if Machining[3].bIsApplicable then if Proc.MainFaces.TunnelAddedFaces then Machining[3].ToolInfo.dResidualDepth = Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP end Machining.sTypeMachining = EgtIf( Machining.sTypeMachining == 'None', 'Side1', Machining.sTypeMachining .. '-Side1') Strategy.Result.dMRR = ( Strategy.Result.dMRR + Machining[3].dMRR) / EgtIf( Strategy.Result.dMRR == 0, 1, 2) end if Machining[4].bIsApplicable then if Proc.MainFaces.TunnelAddedFaces then Machining[4].ToolInfo.dResidualDepth = Machining[4].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP end Machining.sTypeMachining = EgtIf( Machining.sTypeMachining == 'None', 'Side2', Machining.sTypeMachining .. '-Side2') Strategy.Result.dMRR = ( Strategy.Result.dMRR + Machining[4].dMRR) / EgtIf( Strategy.Result.dMRR == 0, 1, 2) end local dMachinedPrercentage = CalcMachinedPercentage( Proc, Machining) Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage) Strategy.Result.sInfo = 'Machining not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%' -- se non ho trovato neanche una lavorazione if Machining.sTypeMachining == 'None' then Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Mill not found') end return Machining end ------------------------------------------------------------------------------------------------------------- local function GetSplitSurfaces( Proc, Part, bAddMachining) local vAddId = {} local vAddIdTunnel = {} local idAddGroup if bAddMachining then idAddGroup = BeamLib.GetAddGroup( Part.id) else idAddGroup = Part.idTempGroup end local nOriginalTmIdTunnel = GDB_ID.NULL if Proc.MainFaces.TunnelAddedFaces then nOriginalTmIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id end -- recupero punti di spezzatura - da destra a sinistra local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part) if #FeatureSplittingPoints == 0 then local nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) or GDB_ID.NULL table.insert( vAddId, nAddId) table.insert( vAddIdTunnel, nAddIdTunnel) else for i = 1, #FeatureSplittingPoints do local nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) or GDB_ID.NULL if i == 1 then -- prima superficie, va tagliata solo a sinistra local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0) EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB) EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB) else -- taglio della superficie corrente - lato sinistro local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0) EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB) EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB) -- taglio della superficie corrente - lato destro ptSplit = FeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0) EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB) EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB) end table.insert( vAddId, nAddId) table.insert( vAddIdTunnel, nAddIdTunnel) end -- taglio ultima superficie, va tagliata solo a destra local nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) or GDB_ID.NULL local ptSplit = FeatureSplittingPoints[#FeatureSplittingPoints] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0) EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB) EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB) table.insert( vAddId, nAddId) table.insert( vAddIdTunnel, nAddIdTunnel) end return vAddId, vAddIdTunnel end ------------------------------------------------------------------------------------------------------------- -- TODO rimuovere il calcolo MRR dove non serve, è fatto tutto alla fine. function STR0002.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 = {} Strategy.Result.dTimeToMachine = 0 -- se la lavorazione ostacola il pinzaggio, non posso farla 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 -- se la lavorazione ostacola il pinzaggio, non posso farla, serve una lavorazioen che lasci il testimone if MachiningLib.IsFeatureHinderingClamping( Proc, Part) then local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable ( Feature hinders clamping)' EgtOutLog( sErr) Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sErr) return false, Strategy.Result end local bAreAllMachiningsAdded = true local dFeatureVolume = Proc.dVolume local ToolInfo = {} local Pocketing = {} Strategy.Machining = GetBestPocketingStrategy( Proc, Part) if Strategy.Result.sStatus ~= 'Not-Applicable' then local vAddId = {} local vAddIdTunnel = {} -- recupero superficie, se necessario trimmata sugli spezzoni vAddId, vAddIdTunnel = GetSplitSurfaces( Proc, Part, bAddMachining) -- si applicano le lavorazioni for i = 1, #vAddId do for j = 1, #Strategy.Machining do if Strategy.Machining[j].bIsApplicable then Pocketing = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING) Pocketing.Steps = {} Pocketing.LeadIn = {} Pocketing.nType = MCH_MY.POCKETING Pocketing.nSubType = EgtIf( Proc.Topology.sName == 'Pocket-5-Blind' or Proc.Topology.sName == 'Tunnel-4-Through', MCH_POCK_SUB.SPIRALOUT, MCH_POCK_SUB.SPIRALIN) Pocketing.LeadIn.nType = MCH_POCK_LI.ZIGZAG Pocketing.Steps.dStep = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dStep Pocketing.Steps.dSideStep = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dSideStep Pocketing.nToolIndex = Strategy.Machining[j].ToolInfo.nToolIndex Pocketing.LeadIn.dTangentDistance = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter / 2 Pocketing.LeadIn.dElevation = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter / 2 Pocketing.sDepth = -Strategy.Machining[j].ToolInfo.dResidualDepth Pocketing.dResidualDepth = Strategy.Machining[j].ToolInfo.dResidualDepth -- TODO vedere se questo parametro con svuotature nuove si può rimuovere Pocketing.dOpenMinSafe = Strategy.Parameters.dOpenMinSafe -- il quarto ciclo è la lavorazione opposta sulla faccia Tunnel if Strategy.Machining[j].bToolInvert then Pocketing.bToolInvert = true end -- eventuali antischeggia if Strategy.Machining[j].bAddAntiSplint then local OptionalParametersAntiSplint = { bIsSplitFeature = ( #vAddId > 1), dExtendAfterTail = Strategy.Parameters.dExtendAfterTail } local AntiSplints = AntiSplintOnFace.Make( Proc, Part, Proc.Faces[ Strategy.Machining[j].idFaceToMachine + 1], OptionalParametersAntiSplint) local bAreAllAntisplintsApplicable = true for k = 1, #AntiSplints do if AntiSplints[k].bIsApplicable then if bAddMachining then bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, AntiSplints[k]) end else bAreAllAntisplintsApplicable = false end end if bAreAllAntisplintsApplicable then -- TODO qui si dovrà distinguere tra antischeggia di lama e di fresa; al momento è solo di lama if Strategy.Result.dQuality == FeatureLib.GetStrategyQuality( 'STD') then Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'BEST') end end end -- se ho una sola trimesh, sto lavorando la Proc direttamente e non ho spezzato. Applico direttamente alla geometria calcolata prima if #vAddId == 1 then Pocketing.Geometry = {{ Strategy.Machining[j].idProc, Strategy.Machining[j].idFaceToMachine}} Pocketing.vtToolDirection = Strategy.Machining[j].vtFaceNormal -- TODO controllare parametro danneggiamento ammesso per decidere se spostare dopo taglio seprazione -- se è aperta sulla coda, dico che deve essere fatta dopo la separazione if Proc.AffectedFaces.bLeft then Pocketing.sStage = 'AfterTail' end Pocketing.nSCC = GetSCC( Proc, Pocketing) Pocketing.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Pocketing, Part) Strategy.Result.dTimeToMachine = Strategy.Result.dTimeToMachine + Pocketing.dTimeToMachine if bAddMachining then bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Pocketing) end else -- TODO controllare parametro danneggiamento ammesso per decidere se spostare dopo taglio seprazione -- se è aperta sulla coda, dico che deve essere fatta dopo la separazione if Proc.AffectedFaces.bLeft and i == #vAddId then Pocketing.sStage = 'AfterTail' end for k = 1, Proc.nFct do local vtNSplitFace local nIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i]) Pocketing.ptCenter, vtNSplitFace = EgtSurfTmFacetCenter( nIdTm, k - 1, GDB_ID.ROOT) Pocketing.vtToolDirection = vtNSplitFace or Strategy.Machining[j].vtFaceNormal if Pocketing.bToolInvert then Pocketing.vtToolDirection = -Pocketing.vtToolDirection end if vtNSplitFace and AreSameVectorApprox( vtNSplitFace * EgtIf( Pocketing.bToolInvert, -1, 1), Strategy.Machining[j].vtFaceNormal) then Pocketing.Geometry = {{ nIdTm, k - 1}} Pocketing.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Pocketing, Part) Strategy.Result.dTimeToMachine = Strategy.Result.dTimeToMachine + Pocketing.dTimeToMachine if bAddMachining then bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddMachinings( Proc, Pocketing) end break end end end end end end -- TODO se incompleta il volume non è corretto, ma conta? L'MRR ha senso nelle incomplete?? Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6) else bAreAllMachiningsAdded = false end return bAreAllMachiningsAdded, Strategy.Result end ------------------------------------------------------------------------------------------------------------- return STR0002