diff --git a/LuaLibs/BeamLib.lua b/LuaLibs/BeamLib.lua index 7b48888..a37449b 100644 --- a/LuaLibs/BeamLib.lua +++ b/LuaLibs/BeamLib.lua @@ -526,6 +526,22 @@ function BeamLib.TableCopyDeep( OriginalTable) return CopiedTable end +--------------------------------------------------------------------- +function BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtDirection) + local BestEdge = {} + + local dMaxDotProduct = GEO.INFINITO + for i = 1, #Edges do + local dCurrentDotProduct = ( Edges[i].vtN * vtDirection) + if ( i == 1) or ( dCurrentDotProduct > dMaxDotProduct + 10 * GEO.EPS_SMALL) then + dMaxDotProduct = dCurrentDotProduct + BestEdge = Edges[i] + end + end + + return BestEdge +end + --------------------------------------------------------------------- -- Merge sorting - algoritmo di sorting stabile, ossia che mantiene l'ordine relativo se gli elementi sono equivalenti -- TODO vedere come riordinare (tutto in tabella MergeSort??) diff --git a/LuaLibs/FeatureLib.lua b/LuaLibs/FeatureLib.lua index c58b7c2..5123b25 100644 --- a/LuaLibs/FeatureLib.lua +++ b/LuaLibs/FeatureLib.lua @@ -15,6 +15,21 @@ local ID = require( 'Identity') ------------------------------------------------------------------------------------------------------------- + +function FeatureLib.GetProcFromTrimesh( idTrimesh, Part) + local Proc = {} + + Proc.id = idTrimesh + Proc.nFct = EgtSurfTmFacetCount( Proc.id) or 0 + Proc.b3Box = EgtGetBBoxGlob( idTrimesh or GDB_ID.NULL, GDB_BB.STANDARD) + Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) + Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc) + Proc.Faces = FaceData.GetFacesInfo( Proc, Part) + + return Proc + end + +--------------------------------------------------------------------- -- recupero topologia della feature function FeatureLib.NeedTopologyFeature( Proc) -- features tipo taglio diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index 52cde7a..1dc08e9 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -445,7 +445,7 @@ function MachiningLib.FindChainSaw( Proc, ToolSearchParameters) dBestToolResidualDepth = dCurrentResidualDepth end -- se entrambi incompleti - elseif dBestToolResidualDepth > 0 and dCurrentResidualDepth > 0 then + elseif dBestToolResidualDepth > 10 * GEO.EPS_SMALL and dCurrentResidualDepth > 10 * GEO.EPS_SMALL then --scelgo quello che lavora di più if dCurrentResidualDepth > dBestToolResidualDepth then nBestToolIndex = i diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 882c0e6..eaac170 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -72,13 +72,74 @@ local function CompareEdgesBottomHead( EdgeA, EdgeB) 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, CompareEdgesBottomHead) + EdgeToMachine = EdgesSorted[1] + elseif sBladeType == 'Bottom' then + table.sort( EdgesSorted, CompareEdgesTopHead) + 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 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 = {} @@ -86,8 +147,12 @@ local function GetBestBlade( Proc, Part, Face, OptionalParameters) ToolSearchParameters.bAllowTopHead = true ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = false + ToolSearchParameters.dElevation = dElevationTop ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) - local nToolIndexTop = ToolInfo.nToolIndex + local nToolIndexTop + if ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then + nToolIndexTop = ToolInfo.nToolIndex + end -- ricerca lama testa sotto ToolSearchParameters = {} @@ -95,8 +160,12 @@ local function GetBestBlade( Proc, Part, Face, OptionalParameters) ToolSearchParameters.bAllowTopHead = false ToolSearchParameters.bAllowBottomHead = true ToolSearchParameters.bForceLongcutBlade = false + ToolSearchParameters.dElevation = dElevationBottom ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) - local nToolIndexBottom = ToolInfo.nToolIndex + local nToolIndexBottom + if ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then + nToolIndexBottom = ToolInfo.nToolIndex + end -- lama sopra e sotto if nToolIndexTop and nToolIndexBottom then @@ -122,7 +191,6 @@ local function GetBestBlade( Proc, Part, Face, OptionalParameters) else nChosenToolIndex = nToolIndexTop end - -- solo lama sopra elseif nToolIndexTop then nChosenToolIndex = nToolIndexTop @@ -131,26 +199,26 @@ local function GetBestBlade( Proc, Part, Face, OptionalParameters) 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 -end - - -local function GetEdgeToMachine( Edges, bIsBottomBlade) - local EdgeToMachine = {} - local EdgesSorted = {} - - for i = 1, #Edges do - table.insert( EdgesSorted, Edges[i]) - end - if bIsBottomBlade then - table.sort( EdgesSorted, CompareEdgesBottomHead) - else - table.sort( EdgesSorted, CompareEdgesTopHead) - end - EdgeToMachine = EdgesSorted[1] - - return EdgeToMachine + return nChosenToolIndex, sChosenBladeType end @@ -174,12 +242,7 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) 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) + Proc = FeatureLib.GetProcFromTrimesh( ProcOrId, Part) else error( 'BLADETOWASTE : Only feature or trimesh supported') end @@ -217,22 +280,36 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) if Proc.nFct == 1 and ( bIsFeatureSmall or bDropWholeWaste) then local Cutting = {} local EdgeToMachine = {} + local sChosenBladeType = '' local dDepthToMachine = 0 - -- scelta lato da lavorare per testa sopra e sotto - si prevede perchè l'utensile non è ancora stato scelto - local EdgeToMachineBottomBlade = GetEdgeToMachine( Proc.Faces[1].Edges, true) - local EdgeToMachineTopBlade = GetEdgeToMachine( Proc.Faces[1].Edges, false) - dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA - -- ricerca utensile + + -- 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 not nToolIndex then - -- scelta lama da sopra o da sotto - if not nToolIndex then - -- quetsa deve anche verificare il lato migliore per lama sopra sotto e usare la sua elevazione per la ricerca (opzionalmente) - nToolIndex = GetBestBlade( Proc, Part, Proc.Faces[1], OptionalParameters) - end + 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 + + -- 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?) + -- 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} Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) @@ -276,8 +353,9 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) end -- scelta lama da sopra o da sotto + local sChosenBladeType = '' if not nToolIndex then - nToolIndex = GetBestBlade( Proc, Part, Face1, OptionalParameters) + nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Face1, OptionalParameters) end -- se non trovata lama la lavorazione non è fattibile @@ -285,7 +363,7 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) return Machinings, Result end - -- limite per taglio downUp + -- 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) @@ -306,12 +384,8 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) local vCuts = DiceCut.GetDice( Part, Face1, Face2, OptionalParametersDiceCut) -- lavorazione cubetti - -- calcolo vtToolDirection - - - - - -- sistemo posizione nel DB e nome + local bIsDicingOk = true + -- eventuale inversione tagli ortogonali e aggiunta informazioni alla geometria local bAreOrthogonalCutsInverted = false for i = 1, #vCuts do for j = 1, #vCuts[i] do @@ -326,9 +400,9 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) end end end - -- eseguo + -- calcolo lavorazioni for i = 1, #vCuts do - -- determino il modo di tagliare + -- determinazione direzione di taglio local vtToolDirection local bNoPerpCuts = false if i % 2 == 1 then @@ -357,42 +431,36 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) else -- scelta lato da lavorare per stabilire la vtToolDirection local EdgeToMachine = {} - EdgeToMachine = GetEdgeToMachine( vCuts[i][1], nToolIndex) - - if bCutDirection then - vtToolDirection = Z_AX() - else - if Face1.vtN:getZ() < dMinNzDownUp then - vtToolDirection = EgtIf( Face1.vtN:getY() > -0.02, -Y_AX(), Y_AX()) - else - vtToolDirection = EgtIf( Face1.vtN:getY() > 0.02, Y_AX(), -Y_AX()) - end - end + 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 - -- caso standard - -- lavoro la faccia + -- calcolo lavorazione della singola faccia for j = 1, #vCuts[i] do - -- se taglio dal basso - if bDownCut then - -- se strato pari composto da 1 o 2 elementi - if ( i % 2) == 0 and #vCuts[i] <= 2 then - -- il primo elemento prende la direzione prevista, il secondo quella opposta - local vtToolDirectionNew = Vector3d( vtToolDirection) - local dVzLimDwnUp = dMinNzDownUp - if j ~= 1 then - vtToolDirectionNew = -vtToolDirection - if BeamData.GetNzLimDownUp then - dVzLimDwnUp = BeamData.GetNzLimDownUp( Part.b3Raw, Face1.vtN, V_NULL(), true) - elseif not BeamData.C_SIMM and not BeamData.TURN and abs( Face1.vtN:getY()) > 0.05 then - dVzLimDwnUp = -0.708 - end - end - local bSpecialTangentLeadInOut = ( i % 2 == 0) and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) - local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtToolDirectionNew, dVzLimDwnUp, BD.CUT_EXTRA, BD.CUT_SIC, 0, 0, 0, nil, b3Raw, nil, nil, bSpecialTangentLeadInOut) - if not bOk then return bOk, sErr end + 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} + Cutting = FaceByBlade.Make( ProcTrimesh, Part, FaceToMachine, EdgeToMachine, OptionalParametersFaceByBlade) + if Cutting.bIsApplicable then + table.insert( Machinings, Cutting) + else + bIsDicingOk = false end - -- tutti gli altri casi vengono saltati -- caso generale else -- in generale sta sollevato di pochissimo @@ -404,33 +472,45 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) dExtraCut = BeamData.CUT_EXTRA -- se altrimenti tagli ortogonali invertiti, devo approfondire dello spessore lama elseif bAreOrthogonalCutsInverted then - dExtraCut = dSawThick + dExtraCut = TOOLS[nToolIndex].dThickness -- se ultimo taglio, devo affondare elseif j == #vCuts[i] then - dExtraCut = BD.CUT_EXTRA + dExtraCut = BeamData.CUT_EXTRA end end - local dVzLimDwnUp = dMinNzDownUp - if BeamData.GetNzLimDownUp then - dVzLimDwnUp = BeamData.GetNzLimDownUp( b3Raw, Face1.vtN, V_NULL(), true) - elseif not BeamData.C_SIMM and not BeamData.TURN and Face1.vtN:getZ() > 0.707 then - dVzLimDwnUp = -0.708 - end - local bSpecialTangentLeadInOut = ( i % 2 == 0) and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) - local vtToolDirectionAlternative + 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 - vtToolDirectionAlternative = - vtToolDirection + EdgeToMachineAlternative = BeamLib.FindEdgeBestOrientedAsDirection( Edges, -EdgeToMachine.vtN) + end + local dDepthToMachine = EdgeToMachine.dElevation + dExtraCut + local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, + nToolIndex = nToolIndex, + EdgeToMachineAlternative = EdgeToMachineAlternative + } + Cutting = FaceByBlade.Make( ProcTrimesh, Part, FaceToMachine, EdgeToMachine, OptionalParametersFaceByBlade) + if Cutting.bIsApplicable then + table.insert( Machinings, Cutting) + else + bIsDicingOk = false end - bForceTangentLeadInOut = bForceTangentLeadInOut and ( ( i % 2) ~= 0) - local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtToolDirection, dVzLimDwnUp, dExtraCut, BD.CUT_SIC, 0, 0, 0, sNotes, b3Raw, nil, nil, bSpecialTangentLeadInOut, bForceTangentLeadInOut, vtToolDirectionAlternative) - if not bOk then return bOk, sErr end end end end - - -- risultati del calcolo + -- TODO contemplare il caso di lavorazione incompleta per i cubetti????? + if bIsDicingOk then + Result.sStatus = 'Completed' + Result.dCompletionPercentage = 100 + else + Result.sStatus = 'Not-Applicable' + Result.dCompletionPercentage = 0 + end + Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade') + local dMRR = dFeatureVolume / ( dDiceDimension / TOOLS[nToolIndex].Feeds.dFeed) + Result.dMRR = dMRR / pow( 10, 6) -- restituire tabella contenente lavorazioni, già con cloni se necessari return Machinings, Result diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index 1754f7f..d06508a 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -84,6 +84,9 @@ end -- TODO calcolo area lavorata per completamento +-- TODO EdgeToMachineAlternative da gestire +-- TODO invert avanzato (direzione, Z, alternativa, ...) da gestire +-- TODO bilinea da gestire function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters) local Cutting = {} Cutting.bIsApplicable = true @@ -157,7 +160,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) - -- ora che l'utensile è scelto, se non era definito l'angolo di downUp lo verifico per decidere se invertire + -- ora che l'utensile è scelto, se non era definito l'angolo di DownUp lo verifico per decidere se invertire if ToolInfo.nToolIndex and not dMinNzDownUp then dMinNzDownUp = TOOLS[ToolInfo.nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Cutting.vtToolDirection) if FaceToMachine.vtN:getZ() < dMinNzDownUp then