-- BLADETOWASTE.lua by Egalware s.r.l. 2025/01/08 -- Libreria di supporto a strategie con funzioni comune a strategie diverse. -- Tabella per definizione modulo local BLADETOWASTE = {} -- Include require( 'EgtBase') -- Carico i dati globali local BeamData = require( 'BeamData') local BeamLib = require( 'BeamLib') local FaceData = require( 'FaceData') local FeatureLib = require( 'FeatureLib') local MachiningLib = require( 'MachiningLib') local DiceCut = require( 'DiceCut') -- strategie di base local FaceByBlade = require('FACEBYBLADE') EgtOutLog( ' BLADETOWASTE started', 1) ------------------------------------------------------------------------------------------------------------- local function GetBestBladeForDicing( Proc, Part, Face, OptionalParameters) local nChosenToolIndex -- parametri opzionali local dMinNzTopBladeIfEqual = OptionalParameters.dMinNzTopBlade or sin(-5) local dMaxNyTopBlade = OptionalParameters.dMaxNyTopBlade or sin(1) local dShortPartLength = OptionalParameters.dShortPartLength or BeamData.LEN_SHORT_PART -- ricerca lama testa sopra local ToolSearchParameters = {} ToolSearchParameters.vtN = Face.vtN ToolSearchParameters.bAllowTopHead = true ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = false ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) local nToolIndexTop = ToolInfo.nToolIndex -- ricerca lama testa sotto ToolSearchParameters = {} ToolSearchParameters.vtN = Face.vtN ToolSearchParameters.bAllowTopHead = false ToolSearchParameters.bAllowBottomHead = true ToolSearchParameters.bForceLongcutBlade = false ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) local nToolIndexBottom = ToolInfo.nToolIndex -- lama sopra e sotto if nToolIndexTop and nToolIndexBottom then -- angolo minimo che determina la preferenza tra lama sopra e sotto local dMinNzTopBlade -- entrambe le lame senza aggregato o entrambe con aggregato if TOOLS[nToolIndexTop].SetupInfo.bIsCSymmetrical == TOOLS[nToolIndexBottom].SetupInfo.bIsCSymmetrical then dMinNzTopBlade = dMinNzTopBladeIfEqual -- lama sopra con aggregato - preferenza testa sopra elseif not TOOLS[nToolIndexTop].SetupInfo.bIsCSymmetrical then dMinNzTopBlade = OptionalParameters.dMinNzTopBlade or TOOLS[nToolIndexTop].SetupInfo.dMinNz / 2 -- lama sotto con aggregato - preferenza testa sotto elseif not TOOLS[nToolIndexBottom].SetupInfo.bIsCSymmetrical then dMinNzTopBlade = OptionalParameters.dMinNzTopBlade or TOOLS[nToolIndexBottom].SetupInfo.dMaxNz / 2 else error( 'GetBestBladeForDicing : unknown blade type') end -- se la Z della faccia è sotto all'angolo minimo e inclinata in Y oppure il pezzo è corto, si preferisce la lama sotto if Face.vtN:getZ() < dMinNzTopBlade - GEO.EPS_SMALL and ( abs( Face.vtN:getY()) > dMaxNyTopBlade or Part.b3Raw:getDimX() < dShortPartLength - 10 * GEO.EPS_SMALL) then nChosenToolIndex = nToolIndexBottom else nChosenToolIndex = nToolIndexTop end -- solo lama sopra elseif nToolIndexTop then nChosenToolIndex = nToolIndexTop -- solo lama sotto elseif nToolIndexBottom then nChosenToolIndex = nToolIndexBottom end -- se non trovata alcuna lama ritorna nil return nChosenToolIndex end function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) local Machinings = {} local Result = {} local dCompletionPercentage = 0 -- disambiguazione feature vs id trimesh local Proc = {} if type( ProcOrId) == "table" then Proc = ProcOrId elseif type( ProcOrId) == "number" then Proc.id = ProcOrId Proc.nFct = EgtSurfTmFacetCount( Proc.id) or 0 Proc.b3Box = EgtGetBBoxGlob( ProcOrId or GDB_ID.NULL, GDB_BB.STANDARD) Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc) Proc.Faces = FaceData.GetFacesInfo( Proc, Part) else error( 'BLADETOWASTE : Only feature or trimesh supported') end -- controlli preventivi if Proc.nFct > 2 then error( 'BladeToWaste : max 2 faces supported') elseif Proc.nFct == 2 then if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then error( 'BladeToWaste : angle between faces must be concave and >= 90deg') end end -- parametri opzionali e default if not OptionalParameters then OptionalParameters = {} end local nToolIndex = OptionalParameters.nToolIndex local bDropWholeWaste = OptionalParameters.bDropWholeWaste or false local dMaxWasteVolume = OptionalParameters.dMaxWasteVolume or 0 local dMaxWasteLength = OptionalParameters.dMaxWasteLength or 0 -- dimensioni feature local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) local dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) local bIsFeatureSmall = dFeatureVolume < dMaxWasteVolume + 10 * GEO.EPS_SMALL and dFeatureMaxDimension < dMaxWasteLength + 10 * GEO.EPS_SMALL -- si taglia tutto lo scarto in una sola lavorazione if Proc.nFct == 1 and ( bIsFeatureSmall or bDropWholeWaste) then local Cutting = {} local EdgeToMachine = {} local dDepthToMachine = 0 local ToolInfo = {} -- ricerca utensile if not nToolIndex then local ToolSearchParameters = {} for i = 1, #Proc.Faces[1].Edges do if ( i == 1) or Proc.Faces[1].Edges[i].dElevation < EdgeToMachine.dElevation - 10 * GEO.EPS_SMALL then EdgeToMachine = Proc.Faces[1].Edges[i] end end dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA ToolSearchParameters.dElevation = dDepthToMachine ToolSearchParameters.vtN = Proc.Faces[1].vtN ToolSearchParameters.bAllowTopHead = true -- TODO bisognerà implementare anche la lama da sotto ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = false ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) nToolIndex = ToolInfo.nToolIndex end -- TODO qui gestire il caso in cui si può tagliare da due lati (inizialmente solo se vtN:Y è ~= 0?) if ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex} Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) end if Cutting.bIsApplicable or bDropWholeWaste then table.insert( Machinings, Cutting) dCompletionPercentage = Cutting.dCompletionPercentage or dCompletionPercentage end -- risultati del calcolo -- TODO funzione? if Cutting.bIsApplicable then if dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then Result.sStatus = 'Completed' else Result.sStatus = 'Not-Completed' end else Result.sStatus = 'Not-Applicable' end Result.dCompletionPercentage = dCompletionPercentage Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dCompletionPercentage) Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade') local dMRR = dFeatureVolume / ( EdgeToMachine.dLength / TOOLS[nToolIndex].Feeds.dFeed) Result.dMRR = dMRR / pow( 10, 6) return Machinings, Result end -- lavorazione con cubetti -- se due facce, la faccia principale è la più grande local Face1 = Proc.Faces[1] local Face2 = {} if Proc.nFct == 2 then Face2 = Proc.Faces[2] end -- scelta lama da sopra o da sotto if not nToolIndex then nToolIndex = GetBestBladeForDicing( Proc, Part, Face1, OptionalParameters) end -- se non trovata lama la lavorazione non è fattibile if not nToolIndex then return Machinings, Result end -- calcolo dimensione cubetto e eventuale cubetto ridotto (tagli orizzontali con affondamento verticale) local dDiceDimension = min( TOOLS[nToolIndex].dMaxMaterial, BeamData.MAX_DIM_DICE) local dDiceDimensionReduced = dDiceDimension if TOOLS[nToolIndex].SetupInfo.dMaxMatDecrease then dDiceDimensionReduced = min( dDiceDimension, dDiceDimension - TOOLS[nToolIndex].SetupInfo.dMaxMatDecrease) end -- calcolo cubetti local OptionalParametersDiceCut = {} OptionalParametersDiceCut.dOffsetParallel = dDiceDimension OptionalParametersDiceCut.dOffsetOrthogonal = dDiceDimension OptionalParameters.dOffsetOrthogonalReduced = dDiceDimensionReduced local vCuts = DiceCut.GetDice( Part, Face1, Face2, OptionalParametersDiceCut) -- lavorazione cubetti -- calcolo vtToolDirection -- risultati del calcolo -- restituire tabella contenente lavorazioni, già con cloni se necessari return Machinings, Result end ------------------------------------------------------------------------------------------------------------- return BLADETOWASTE