-- 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') -- tabella per definizione modulo local FeatureInfo = {} ------------------------------------------------------------------------------------------------------------- local function CompareEdgesTopHead( EdgeA, EdgeB) -- prima i lati a minore elevazione (se entro 5 mm si considerano uguali) if EdgeA.dElevation < EdgeB.dElevation - 5 then return true elseif EdgeA.dElevation > EdgeB.dElevation + 5 then return false -- se stessa elevazione si preferiscono i lati più in basso (testa sopra) else if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then return true elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then return false -- se stessa Z si preferiscono i lati verso il fronte della trave else if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then return true elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 10 * GEO.EPS_SMALL then return false else return false end end end end local function CompareEdgesBottomHead( EdgeA, EdgeB) -- prima i lati a minore elevazione (se entro 5 mm si considerano uguali) if EdgeA.dElevation < EdgeB.dElevation - 5 then return true elseif EdgeA.dElevation > EdgeB.dElevation + 5 then return false -- se stessa elevazione si preferiscono i lati più in alto (testa sotto) else if EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then return true elseif EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then return false -- se stessa Z si preferiscono i lati verso il fronte della trave else if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then return true elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 10 * GEO.EPS_SMALL then return false else return false end end end end local function CompareEdgesNoPreference( EdgeA, EdgeB) -- prima i lati a minore elevazione if EdgeA.dElevation < EdgeB.dElevation then return true elseif EdgeA.dElevation > EdgeB.dElevation then return false -- se stessa elevazione si preferiscono i lati più in basso (testa sopra) else if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then return true elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then return false -- se stessa Z si preferiscono i lati verso il fronte della trave else if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then return true elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 10 * GEO.EPS_SMALL then return false else return false end end end end local function GetEdgeToMachine( Edges, vtNFace, sBladeType) local EdgeToMachine = {} local EdgesSorted = {} for i = 1, #Edges do table.insert( EdgesSorted, Edges[i]) end if sBladeType == 'Top' then table.sort( EdgesSorted, CompareEdgesTopHead) EdgeToMachine = EdgesSorted[1] elseif sBladeType == 'Bottom' then table.sort( EdgesSorted, CompareEdgesBottomHead) EdgeToMachine = EdgesSorted[1] elseif sBladeType == 'TopDownUp' then local vtEdgeDirection if vtNFace:getY() > -0.02 then vtEdgeDirection = -Y_AX() else vtEdgeDirection = Y_AX() end EdgeToMachine = BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtEdgeDirection) else table.sort( EdgesSorted, CompareEdgesNoPreference) EdgeToMachine = EdgesSorted[1] end return EdgeToMachine end local function GetBestBlade( Proc, Part, Face, OptionalParameters) local nChosenToolIndex local sChosenBladeType -- parametri opzionali e default if not OptionalParameters then OptionalParameters = {} end local dMinNzTopBladeIfEqual = OptionalParameters.dMinNzTopBlade or sin(-5) local dMaxNyTopBlade = OptionalParameters.dMaxNyTopBlade or sin(1) local dShortPartLength = OptionalParameters.dShortPartLength or BeamData.LEN_SHORT_PART local dElevationTop = OptionalParameters.dElevationTopBlade local dElevationBottom = OptionalParameters.dElevationBottomBlade local dElevationTopDownUp = OptionalParameters.dElevationTopBladeDownUp or 0 -- ricerca lama testa sopra local ToolSearchParameters = {} ToolSearchParameters.vtN = Face.vtN ToolSearchParameters.bAllowTopHead = true ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = false ToolSearchParameters.dElevation = dElevationTop ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) local nToolIndexTop if ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then nToolIndexTop = ToolInfo.nToolIndex end -- ricerca lama testa sotto ToolSearchParameters = {} ToolSearchParameters.vtN = Face.vtN ToolSearchParameters.bAllowTopHead = false ToolSearchParameters.bAllowBottomHead = true ToolSearchParameters.bForceLongcutBlade = false ToolSearchParameters.dElevation = dElevationBottom ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) local nToolIndexBottom if ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then nToolIndexBottom = ToolInfo.nToolIndex end -- 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.GetMinNz( Face.vtN) / 2 -- lama sotto con aggregato - preferenza testa sotto elseif not TOOLS[nToolIndexBottom].SetupInfo.bIsCSymmetrical then dMinNzTopBlade = OptionalParameters.dMinNzTopBlade or TOOLS[nToolIndexBottom].SetupInfo.GetMaxNz( Face.vtN) / 2 else error( 'GetBestBlade : 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 -- assegnazione tipo lama if nChosenToolIndex == nToolIndexBottom then sChosenBladeType = 'Bottom' -- se lama sopra va verificato se va usata in DownUp elseif nChosenToolIndex == nToolIndexTop then local dMinNzDownUp = TOOLS[nToolIndexTop].SetupInfo.GetMinNzDownUp( Part.b3Raw, Face.vtN) local dCurrentResidualDepth = dElevationTopDownUp - TOOLS[nToolIndexTop].dMaxDepth if Face.vtN:getZ() < dMinNzDownUp then if ( dCurrentResidualDepth > 10 * GEO.EPS_SMALL) then -- TODO serve messaggio per motivare il non applicabile?? nChosenToolIndex = nil end sChosenBladeType = 'TopDownUp' else sChosenBladeType = 'Top' end end -- se non trovata alcuna lama ritorna nil return nChosenToolIndex, sChosenBladeType end local function SetDiceFaceInfo( Proc, idDiceFace, bSaveAddedGeometries) EgtSetName( idDiceFace, 'Face' .. tostring( Proc.idFeature) .. '_Dice') -- TODO la scrittura del TaskId probabilmente non serve (è fatta nell'AddOperations) EgtSetInfo( idDiceFace, 'TASKID', Proc.idTask) if not bSaveAddedGeometries then EgtSetLevel( idDiceFace, GDB_LV.TEMP) end end local function CutWholeWaste( Proc, Part, OptionalParameters) local Machinings = {} local Cutting = {} local Result = {} local EdgeToMachine = {} local sChosenBladeType = '' local dDepthToMachine = 0 local dCompletionPercentage = 0 -- parametri opzionali e default if not OptionalParameters then OptionalParameters = {} end local nToolIndex = OptionalParameters.nToolIndex local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000 -- lato da lavorare in base al tipo di lama local EdgeToMachineTopBlade = GetEdgeToMachine( Proc.Faces[1].Edges, Proc.Faces[1].vtN, 'Top') local EdgeToMachineBottomBlade = GetEdgeToMachine( Proc.Faces[1].Edges, Proc.Faces[1].vtN, 'Bottom') local EdgeToMachineTopBladeDownUp = GetEdgeToMachine( Proc.Faces[1].Edges, Proc.Faces[1].vtN, 'TopDownUp') -- scelta lama da sopra o da sotto if nToolIndex then nToolIndex = OptionalParameters.nToolIndex else local OptionalParametersGetBestBlade = { dElevationTop = EdgeToMachineTopBlade.dElevation + BeamData.CUT_EXTRA, dElevationBottom = EdgeToMachineBottomBlade.dElevation + BeamData.CUT_EXTRA, dElevationTopDownUp = EdgeToMachineTopBladeDownUp.dElevation + BeamData.CUT_EXTRA } nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Proc.Faces[1], OptionalParametersGetBestBlade) end -- utensile non trovato if not nToolIndex then Result = FeatureLib.GetStrategyResultNotApplicable( 'Blade not found') return Machinings, Result end -- lato da lavorare definitivo if sChosenBladeType == 'Top' then EdgeToMachine = EdgeToMachineTopBlade elseif sChosenBladeType == 'Bottom' then EdgeToMachine = EdgeToMachineBottomBlade elseif sChosenBladeType == 'TopDownUp' then EdgeToMachine = EdgeToMachineTopBladeDownUp end dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA local dResidualDepth = dDepthToMachine - TOOLS[nToolIndex].dMaxMaterial -- TODO qui gestire il caso in cui si può tagliare da due lati (inizialmente solo se vtN:Y è ~= 0?). Andranno ricercati gli utensili di nuovo con l'elevazione a metà?? if dResidualDepth < 10 * GEO.EPS_SMALL then local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex, dExtendAfterTail = dExtendAfterTail} Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) end if Cutting.bIsApplicable 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 = TOOLS[nToolIndex].nQuality Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( {Cutting}) Result.dMRR = ( FeatureInfo.dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6) return Machinings, Result end local function CutWithDicing( Proc, Part, OptionalParameters) local Machinings = {} local Result = {} -- parametri opzionali e default if not OptionalParameters then OptionalParameters = {} end local nToolIndex = OptionalParameters.nToolIndex local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000 local b3BoxDicing = OptionalParameters.b3BoxDicing local bSaveAddedGeometries = OptionalParameters.bSaveAddedGeometries if bSaveAddedGeometries == nil then bSaveAddedGeometries = true end -- scelta faccia da lavorare -- se due facce, la faccia principale Face1 è la più grande local Face1 = Proc.Faces[1] local Face2 = {} if Proc.nFct == 2 then Face2 = Proc.Faces[2] if Face2.dArea > Face1.dArea then Face1, Face2 = Face2, Face1 end end -- scelta lama da sopra o da sotto local sChosenBladeType = '' if not nToolIndex then nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Face1) end -- se non trovata lama la lavorazione non è fattibile if not nToolIndex then Result = FeatureLib.GetStrategyResultNotApplicable( 'Blade not found') return Machinings, Result end -- limite per taglio DownUp local dMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, Face1.vtN) -- 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 dDiceDimensionReduced = min( dDiceDimension, dDiceDimension - TOOLS[nToolIndex].SetupInfo.dMaxMatDecrease) dDiceDimension = dDiceDimension - BeamData.CUT_EXTRA dDiceDimensionReduced = dDiceDimensionReduced - BeamData.CUT_EXTRA -- calcolo cubetti local OptionalParametersDiceCut = {} OptionalParametersDiceCut.dOffsetParallel = dDiceDimension OptionalParametersDiceCut.dOffsetOrthogonal = dDiceDimension OptionalParametersDiceCut.dOffsetOrthogonalReduced = dDiceDimensionReduced OptionalParametersDiceCut.dMinNzDownUp = dMinNzDownUp OptionalParametersDiceCut.b3BoxDicing = b3BoxDicing local vCuts = DiceCut.GetDice( Part, Face1, Face2, OptionalParametersDiceCut) -- se nessun cubetto trovato, si richiama il taglio singolo if #vCuts == 0 then Machinings, Result = CutWholeWaste( Proc, Part, OptionalParameters) return Machinings, Result end -- lavorazione cubetti local bIsDicingOk = true local bMoveAfterSplit = false -- eventuale inversione tagli ortogonali e aggiunta informazioni alla geometria local bAreOrthogonalCutsInverted = false for i = 1, #vCuts do for j = 1, #vCuts[i] do SetDiceFaceInfo( Proc, vCuts[i][j], bSaveAddedGeometries) if ( i % 2) == 1 then local vtO = EgtSurfTmFacetNormVersor( vCuts[i][j], 0, GDB_ID.ROOT) if ( Face1.vtN:getY() > 0.766 and vtO:getY() < -0.05) or ( Face1.vtN:getY() < -0.766 and vtO:getY() > 0.05) then EgtInvertSurf( vCuts[i][j]) bAreOrthogonalCutsInverted = true end end end end -- calcolo lavorazioni for i = 1, #vCuts do -- determinazione direzione di taglio local vtToolDirection local bNoPerpCuts = false if i % 2 == 1 then vtToolDirection = Vector3d( Face1.vtN) else local vtO if #vCuts[i-1] > 0 then vtO = EgtSurfTmFacetNormVersor( vCuts[i-1][1], 0, GDB_ID.ROOT) elseif vCuts[i+1] and #vCuts[i+1] > 0 then -- lunghezza faccia nell'eventuale direzione ortogonale local asseX = EgtSurfTmFacetNormVersor( vCuts[i+1][1], 0, GDB_ID.ROOT) local asseY = asseX ^ Face1.vtN local Frame = Frame3d( Face1.ptCenter, Face1.ptCenter + asseX, Face1.ptCenter + asseY) local b3Fac = EgtGetBBoxRef( vCuts[i][1], GDB_BB.STANDARD, Frame) -- se lunghezza inferiore al limite, accetto la direzione if b3Fac:getDimX() < TOOLS[nToolIndex].dMaxDepth - BeamData.CUT_EXTRA then vtO = asseX else bNoPerpCuts = true end else bNoPerpCuts = true end if vtO then vtToolDirection = Vector3d( vtO) * EgtIf( bAreOrthogonalCutsInverted, -1, 1) else -- scelta lato da lavorare per stabilire la vtToolDirection local EdgeToMachine = {} local _, Edges = FaceData.GetEdgesInfo( vCuts[i][1], 0) local vtNCurrentFace = EgtSurfTmFacetNormVersor( vCuts[i][1], 0, GDB_ID.ROOT) EdgeToMachine = GetEdgeToMachine( Edges, vtNCurrentFace, sChosenBladeType) vtToolDirection = EdgeToMachine.vtN end end -- calcolo lavorazione della singola faccia for j = 1, #vCuts[i] do local Cutting = {} local _, Edges = FaceData.GetEdgesInfo( vCuts[i][1], 0) local vtNCurrentFace = EgtSurfTmFacetNormVersor( vCuts[i][j], 0, GDB_ID.ROOT) local FaceToMachine = { id = 0, vtN = vtNCurrentFace} -- se taglio DownUp e strato pari composto da 1 o 2 elementi (tutti gli altri casi vengono saltati) if ( vtNCurrentFace:getZ() < dMinNzDownUp) and ( ( i % 2) == 0) and ( #vCuts[i] <= 2) then -- il primo elemento prende la direzione prevista, il secondo quella opposta local vtToolDirectionNew = Vector3d( vtToolDirection) if j ~= 1 then vtToolDirectionNew = -vtToolDirection end -- lavorazione local ProcTrimesh = FeatureLib.GetProcFromTrimesh( vCuts[i][j], Part) local EdgeToMachine = BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtToolDirectionNew) local dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex, dRadialStepSpan = 0, dExtendAfterTail = dExtendAfterTail } Cutting = FaceByBlade.Make( ProcTrimesh, Part, FaceToMachine, EdgeToMachine, OptionalParametersFaceByBlade) Cutting.ptCenter = Point3d( ProcTrimesh.Faces[1].ptCenter:getX(), 0, 0) if Cutting.bIsApplicable then table.insert( Machinings, Cutting) else bIsDicingOk = false end if Cutting.sStage == 'AfterTail' then bMoveAfterSplit = true end -- caso generale else -- in generale sta sollevato di pochissimo local dExtraCut = -0.1 -- se tagli paralleli if ( i % 2) == 0 then -- se non ci sono tagli ortogonali devo affondare if bNoPerpCuts then dExtraCut = BeamData.CUT_EXTRA -- se altrimenti tagli ortogonali invertiti, devo approfondire dello spessore lama elseif bAreOrthogonalCutsInverted then dExtraCut = TOOLS[nToolIndex].dThickness -- se ultimo taglio, devo affondare elseif j == #vCuts[i] then dExtraCut = BeamData.CUT_EXTRA end end local ProcTrimesh = FeatureLib.GetProcFromTrimesh( vCuts[i][j], Part) local EdgeToMachine = BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtToolDirection) local EdgeToMachineAlternative = {} if ( i % 2 == 0) and ( Proc.Fct == 1) and bNoPerpCuts then EdgeToMachineAlternative = BeamLib.FindEdgeBestOrientedAsDirection( Edges, -EdgeToMachine.vtN) end local dDepthToMachine = EdgeToMachine.dElevation + dExtraCut local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex, EdgeToMachineAlternative = EdgeToMachineAlternative, dRadialStepSpan = 0, dExtendAfterTail = dExtendAfterTail } Cutting = FaceByBlade.Make( ProcTrimesh, Part, FaceToMachine, EdgeToMachine, OptionalParametersFaceByBlade) Cutting.ptCenter = Point3d( ProcTrimesh.Faces[1].ptCenter:getX(), 0, 0) if Cutting.bIsApplicable then table.insert( Machinings, Cutting) else bIsDicingOk = false end if Cutting.sStage == 'AfterTail' then bMoveAfterSplit = true end end end end -- se presente anche solo una lavorazione AfterTail si spostano tutte if bMoveAfterSplit then for i = 1, #Machinings do Machinings[i].sStage = 'AfterTail' end end -- risultati del calcolo if bIsDicingOk then Result.sStatus = 'Completed' Result.dCompletionPercentage = 100 else Result = FeatureLib.GetStrategyResultNotApplicable() end Result.nQuality = TOOLS[nToolIndex].nQuality Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Machinings) Result.dMRR = ( FeatureInfo.dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6) return Machinings, Result end local function MakeOneFace( ProcOrId, Part, OptionalParameters) local Machinings = {} local Result = {} -- disambiguazione feature vs id trimesh local Proc = {} if type( ProcOrId) == "table" then Proc = ProcOrId elseif type( ProcOrId) == "number" then Proc = FeatureLib.GetProcFromTrimesh( ProcOrId, Part) else error( 'BLADETOWASTE : Only feature or trimesh supported') end -- parametri opzionali e default if not OptionalParameters then OptionalParameters = {} end local bForceDicing = OptionalParameters.bForceDicing or false -- si taglia tutto lo scarto in una sola lavorazione -- TODO qui si deve entrare anche se lo spessore lama è maggiore dell'elevazione delle faccia if FeatureInfo.bIsFeatureSmall and not bForceDicing then Machinings, Result = CutWholeWaste( Proc, Part, OptionalParameters) end -- se non completata con taglio singolo, lavorazione con cubetti if not Result.sStatus or Result.sStatus ~= 'Completed' then Machinings, Result = CutWithDicing( Proc, Part, OptionalParameters) end return Machinings, Result end function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) local Machinings = {} local Result = {} -- disambiguazione feature vs id trimesh local Proc = {} if type( ProcOrId) == "table" then Proc = ProcOrId elseif type( ProcOrId) == "number" then Proc = FeatureLib.GetProcFromTrimesh( ProcOrId, Part) else error( 'BLADETOWASTE : Only feature or trimesh supported') end -- controlli preventivi if Proc.nFct > 2 then error( 'BladeToWaste : max 2 faces supported') end -- parametri opzionali e default -- quelli non censiti sono gestiti direttamente nelle funzioni sotto e devono quindi solo transitare if not OptionalParameters then OptionalParameters = {} end local dMaxWasteVolume = OptionalParameters.dMaxWasteVolume or 0 local dMaxWasteLength = OptionalParameters.dMaxWasteLength or 0 local bSaveAddedGeometries = OptionalParameters.bSaveAddedGeometries if bSaveAddedGeometries == nil then bSaveAddedGeometries = true end -- dimensioni feature if OptionalParameters.b3BoxDicing then FeatureInfo.dFeatureVolume = OptionalParameters.b3BoxDicing:getDimX() * OptionalParameters.b3BoxDicing:getDimY() * OptionalParameters.b3BoxDicing:getDimZ() FeatureInfo.dFeatureMaxDimension = max( OptionalParameters.b3BoxDicing:getDimX(), OptionalParameters.b3BoxDicing:getDimY()) else FeatureInfo.dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) FeatureInfo.dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) end FeatureInfo.bIsFeatureSmall = FeatureInfo.dFeatureVolume < dMaxWasteVolume + 10 * GEO.EPS_SMALL and FeatureInfo.dFeatureMaxDimension < dMaxWasteLength + 10 * GEO.EPS_SMALL -- calcolo lavorazioni if Proc.nFct == 1 then Machinings, Result = MakeOneFace( Proc, Part, OptionalParameters) elseif Proc.nFct == 2 then local dAngleBetweenFaces = Proc.AdjacencyMatrix[1][2] -- feature convessa: lavorata come 2 facce singole con prolungamento -- TODO qui sostituire con check topologia DoubleBevel if dAngleBetweenFaces > 10 * GEO.EPS_SMALL then -- si creano superfici singole per le facce, estese fino al box della parte local nAddGrpId = BeamLib.GetAddGroup( Part.id) local idFace1 = EgtSurfTmPlaneInBBox( nAddGrpId, Proc.Faces[1].ptCenter, Proc.Faces[1].vtN, Part.b3Part, GDB_ID.ROOT) local idFace2 = EgtSurfTmPlaneInBBox( nAddGrpId, Proc.Faces[2].ptCenter, Proc.Faces[2].vtN, Part.b3Part, GDB_ID.ROOT) if not bSaveAddedGeometries then EgtSetLevel( idFace1, GDB_LV.TEMP) EgtSetLevel( idFace2, GDB_LV.TEMP) end -- lavorazione facce local Machinings1, Result1 = MakeOneFace( idFace1, Part, OptionalParameters) local Machinings2, Result2 = MakeOneFace( idFace2, Part, OptionalParameters) -- tutte le lavorazioni raggruppatee e calcolo area lavorata local dAreaToMachineTotal = 0 for i = 1, #Machinings1 do if Machinings1[i].bIsApplicable then table.insert( Machinings, Machinings1[i]) dAreaToMachineTotal = dAreaToMachineTotal + Machinings1[i].dAreaToMachine end end for i = 1, #Machinings2 do if Machinings2[i].bIsApplicable then table.insert( Machinings, Machinings2[i]) dAreaToMachineTotal = dAreaToMachineTotal + Machinings2[i].dAreaToMachine end end -- calcolo risultati Result.nQuality = FeatureLib.GetStrategyQuality( Machinings) Result.dCompletionPercentage = dAreaToMachineTotal / ( EgtSurfArea( idFace1) + EgtSurfArea( idFace2)) * 100 Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Result.dCompletionPercentage) Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Machinings) Result.dMRR = ( FeatureInfo.dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6) if Result1.sStatus == 'Completed' and Result2.sStatus == 'Completed' then Result.sStatus = 'Completed' elseif Result1.sStatus == 'Completed' or Result2.sStatus == 'Completed' then Result.sStatus = 'Not-Completed' else Result.sStatus = 'Not-Applicable' Result = FeatureLib.GetStrategyResultNotApplicable() end -- feature concava >= 90deg: lavorata con cubetti elseif dAngleBetweenFaces >= -91 then Machinings, Result = CutWithDicing( Proc, Part, OptionalParameters) -- feature concava < 90deg: lavorata come 2 facce singole con accorciamento else -- TODO da fare end end return Machinings, Result end ------------------------------------------------------------------------------------------------------------- return BLADETOWASTE