diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index 514b9dc..01ff1a1 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -267,6 +267,141 @@ local function IsToolInAvailableToolList( AvailableToolList, sTool) return bToolFound end +------------------------------------------------------------------------------------------------------------- +-- in base a tipo testa e angolo soglia, verifica se la faccia è troppo inclinata per la lavorazione scelta (per DownUp passare vtNFace opposta) +local function IsFaceZOutOfRange ( vtNFace, Tool) + + -- lama sotto: angolo negativo troppo basso + if Tool.SetupInfo.HeadType.Top and vtNFace:getZ() < Tool.SetupInfo.GetMinNz( vtNFace, Tool) - GEO.EPS_ZERO then + return true + end + -- lama sopra: angolo positivo troppo elevato + if Tool.SetupInfo.HeadType.Bottom and vtNFace:getZ() > Tool.SetupInfo.GetMaxNz( vtNFace, Tool) + GEO.EPS_ZERO then + return true + end + + return false +end + +------------------------------------------------------------------------------------------------------------- +local function IsBladeOrientationOkForDownUp( Face, Edge, b3Raw) + + -- se l'utensile lavora perpendicolarmente, l'orientamento è sempre valido per DownUp + if AreSameVectorApprox( Face.vtN, Edge) then + + return true + end + + -- orientamento 3d della faccia: non lavorabile in DownUp + -- TODO implementare gestione DownUp in 3d + local FaceOrientation = BeamLib.GetPlaneOrientation( Face.vtN) + if FaceOrientation[1].dRelativeMagnitude < 1 - 10 * GEO.EPS_SMALL then + + return false + end + + -- orientamento 2d: si determinano il piano della faccia e la direzione perpendicolare + local sPlane = FaceOrientation[1].sPlane + local vtPerpendicularToPlane + if sPlane == 'XY' then + vtPerpendicularToPlane = Z_AX() + elseif sPlane == 'XZ' then + vtPerpendicularToPlane = Y_AX() + elseif sPlane == 'YZ' then + vtPerpendicularToPlane = X_AX() + end + + -- se l'utensile è in direzione perpendicolare al piano, l'orientamento è sempre valido per DownUp + if AreSameOrOppositeVectorApprox( Edge.vtN, vtPerpendicularToPlane) then + + return true + end + + -- se tutte le condizioni precedenti sono soddisfatte, il DownUp si può fare se lungo l'asse in cui Face.vtN e Edge.vtN sono discordi il punto iniziale del lato è sul box + -- in pratica, ciò significa che il braccio non entrerà in collisione con la trave + -- TODO in realtà così si escludono dei casi di faccia non troncante in cui aumenterebbe l'elevation ma si potrebbe comunque lavorare + local _, ptOnBox = EgtSurfTmFacetOppositeSide( Face.idTrimesh, Face.id, -Edge.vtN, GDB_ID.ROOT) + -- Helper function: verifica se i vettori sono discordi lungo l'asse indicato e, se sì, se il punto iniziale della lavorazione è sul box oppure no, nella direzione dell'utensile + local function IsDiscordantAndOnBox( sAxis) + -- si compongono i metodi getX, getY, getZ in base all'asse in arrivo (Face.vtN[getX] equivale a Face.vtN:getX()) + local dFaceComponent = Face.vtN["get" .. sAxis](Face.vtN) + local dEdgeComponent = Edge.vtN["get" .. sAxis](Edge.vtN) + local dPtonboxComponent = ptOnBox["get" .. sAxis](ptOnBox) + local dMaxb3rawComponent = b3Raw:getMax()["get" .. sAxis](b3Raw:getMax()) + local dMinb3rawComponent = b3Raw:getMin()["get" .. sAxis](b3Raw:getMin()) + + if dFaceComponent * dEdgeComponent < 10 * GEO.EPS_SMALL then + if dEdgeComponent > GEO.EPS_SMALL then + return dPtonboxComponent > dMaxb3rawComponent - 500 * GEO.EPS_SMALL + else + return dPtonboxComponent < dMinb3rawComponent + 500 * GEO.EPS_SMALL + end + end + return false + end + -- in base all'orientamento, si verifica se il DownUp è fattibile + if sPlane == 'XY' then + if IsDiscordantAndOnBox( "X") then + return true + elseif IsDiscordantAndOnBox( "Y") then + return true + end + elseif sPlane == 'XZ' then + if IsDiscordantAndOnBox( "X") then + return true + elseif IsDiscordantAndOnBox( "Z") then + return true + end + elseif sPlane == 'YZ' then + if IsDiscordantAndOnBox( "Y") then + return true + elseif IsDiscordantAndOnBox( "Z") then + return true + end + end + + return false +end + +------------------------------------------------------------------------------------------------------------- +-- ritorna se la faccia e il lato sono lavorabili e, se sì, il modo di lavorare (standard/DownUp) e l'elevazione corretta (in DownUp può cambiare) +function MachiningLib.GetBladeEngagement( Face, Edge, b3Raw, Tool) + local sBladeEngagement = 'Standard' + local dDownUpElevation = Edge.dElevation + + -- la normale della faccia permette di lavorare in modo standard, ma potrebbero esserci altre condizioni che fanno fallire il taglio + if not IsFaceZOutOfRange( Face.vtN, Tool) then + + -- TODO verifica collisione carro Z, collisione traversa PF, collisione 'C' Fast... La riduzione percorso cambia questo test? + + return true, sBladeEngagement + end + + -- faccia non lavorabile in modo standard: si verifica se il DownUp è fattibile + -- la normale della faccia non permette il DownUp: non lavorabile in DownUp (se taglio DownUp la faccia è lavorata al contrario, vtN opposta) + if IsFaceZOutOfRange( -Face.vtN, Tool) then + + return false + end + + -- faccia non rettangolare: non lavorabile in DownUp + if not FaceData.IsFaceRectangular( Face) then + + return false + end + + -- orientamento faccia / utensile compatibili con DownUp: lavorabile, si calcola l'elevazione reale per DownUp e si ritorna + if IsBladeOrientationOkForDownUp( Face, Edge, b3Raw) then + + sBladeEngagement = 'DownUp' + dDownUpElevation = FaceData.GetEdgeElevationInBBox( Face, Edge, b3Raw ) + + return true, sBladeEngagement, dDownUpElevation + end + + return false +end + ------------------------------------------------------------------------------------------------------------- -- funzione per cercare utensile tipo FRESA con certe caratteristiche -- TODO qui vtToolDirection è in realtà vtN @@ -389,8 +524,8 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) local ToolInfo = {} -- parametri obbligatori - if type( ToolSearchParameters.vtN) ~= 'table' then - error( 'FindBlade : missing tool direction') + if type( ToolSearchParameters.FaceToMachine) ~= 'table' then + error( 'FindBlade : missing face info') end if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then error( 'FindBlade : missing top head info') @@ -401,10 +536,15 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) if not ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then error( 'FindBlade : wrong head info') end + local FaceToMachine = ToolSearchParameters.FaceToMachine + local bAllowTopHead = ToolSearchParameters.bAllowTopHead + local bAllowBottomHead = ToolSearchParameters.bAllowBottomHead -- parametri opzionali - ToolSearchParameters.dElevation = ToolSearchParameters.dElevation or 0 - ToolSearchParameters.bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false + local dElevation = ToolSearchParameters.dElevation or 0 + local bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false + local EdgeToMachine = ToolSearchParameters.EdgeToMachine + local b3Raw = ToolSearchParameters.b3Raw local nBestToolIndex local dBestToolResidualDepth = 0 @@ -412,21 +552,33 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) local bIsToolCompatible = false if TOOLS[i].sFamily == 'SAWBLADE' then - if ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then + if bAllowTopHead and not bAllowBottomHead then bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bTop - elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then + elseif bAllowBottomHead and not bAllowTopHead then bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bBottom else bIsToolCompatible = true end end - -- check angolo limite lama - if TOOLS[i].SetupInfo.HeadType.bTop and ToolSearchParameters.vtN:getZ() < TOOLS[i].SetupInfo.GetMinNz( ToolSearchParameters.vtN, TOOLS[i]) - GEO.EPS_ZERO then - bIsToolCompatible = false - end - if TOOLS[i].SetupInfo.HeadType.bBottom and ToolSearchParameters.vtN:getZ() > TOOLS[i].SetupInfo.GetMaxNz( ToolSearchParameters.vtN, TOOLS[i]) + GEO.EPS_ZERO then - bIsToolCompatible = false + -- se dati sufficienti, si determina se con questo utensile il taglio è fattibile e il modo di lavorare della lama + if FaceToMachine and EdgeToMachine and dElevation then + local sBladeEngagement + local dDownUpElevation + bIsToolCompatible, sBladeEngagement, dDownUpElevation = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachine, b3Raw, TOOLS[i]) + -- orientamento non raggiungibile o elevazione eccessiva per DownUp: non compatibile + if not bIsToolCompatible + or ( sBladeEngagement == 'DownUp' + and ( dDownUpElevation - ( EdgeToMachine.dElevation - dElevation)) > TOOLS[i].dMaxMaterial - 10 * GEO.EPS_SMALL) then + + bIsToolCompatible = false + end + + -- se si ha solo la faccia si può verificare se questa è orientata correttamente + elseif FaceToMachine then + if IsFaceZOutOfRange( FaceToMachine.vtN, TOOLS[i]) then + bIsToolCompatible = false + end end -- se c'è una lista di utensili disponibili, si verifica che l'utensile attuale sia tra quelli @@ -436,13 +588,13 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) if bIsToolCompatible then -- TODO gestire accorciamento massimo materiale per inclinazione - local dCurrentResidualDepth = ToolSearchParameters.dElevation - TOOLS[i].dMaxDepth + local dCurrentResidualDepth = dElevation - TOOLS[i].dMaxDepth if not nBestToolIndex or ( dBestToolResidualDepth > 0 and dCurrentResidualDepth <= 10 * GEO.EPS_SMALL) then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth else - -- prediligo utensile per tagli lunghi, se richiesto - if ToolSearchParameters.bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then + -- prediligo utensile per tagli lungo vena, se richiesto + if bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth else diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index 1fefe73..837d95e 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -187,141 +187,6 @@ local function GetSCC( vtMachiningDirection, vtEdgeDirection, vtNFace) end --- in base a tipo testa e angolo soglia, verifica se la faccia è troppo inclinata per il taglio scelto (Standard o DownUp) -local function IsFaceZOutOfRange ( vtNFace, Tool) - - -- lama sotto: angolo negativo troppo basso - if Tool.SetupInfo.HeadType.Top and vtNFace:getZ() < Tool.SetupInfo.GetMinNz( vtNFace, Tool) - GEO.EPS_ZERO then - return true - end - -- lama sopra: angolo positivo troppo elevato - if Tool.SetupInfo.HeadType.Bottom and vtNFace:getZ() > Tool.SetupInfo.GetMaxNz( vtNFace, Tool) + GEO.EPS_ZERO then - return true - end - - return false -end - - -local function IsOrientationOkForDownUp( Face, Edge, b3Raw) - - -- se l'utensile lavora perpendicolarmente, l'orientamento è sempre valido per DownUp - if AreSameVectorApprox( Face.vtN, Edge) then - - return true - end - - -- orientamento 3d della faccia: non lavorabile in DownUp - -- TODO implementare gestione DownUp in 3d - local FaceOrientation = BeamLib.GetPlaneOrientation( Face.vtN) - if FaceOrientation[1].dRelativeMagnitude < 1 - 10 * GEO.EPS_SMALL then - - return false - end - - -- orientamento 2d: si determinano il piano della faccia e la direzione perpendicolare - local sPlane = FaceOrientation[1].sPlane - local vtPerpendicularToPlane - if sPlane == 'XY' then - vtPerpendicularToPlane = Z_AX() - elseif sPlane == 'XZ' then - vtPerpendicularToPlane = Y_AX() - elseif sPlane == 'YZ' then - vtPerpendicularToPlane = X_AX() - end - - -- se l'utensile è in direzione perpendicolare al piano, l'orientamento è sempre valido per DownUp - if AreSameOrOppositeVectorApprox( Edge.vtN, vtPerpendicularToPlane) then - - return true - end - - -- se tutte le condizioni precedenti sono soddisfatte, il DownUp si può fare se lungo l'asse in cui Face.vtN e Edge.vtN sono discordi il punto iniziale del lato è sul box - -- in pratica, ciò significa che il braccio non entrerà in collisione con la trave - -- TODO in realtà così si escludono dei casi di faccia non troncante in cui aumenterebbe l'elevation ma si potrebbe comunque lavorare - local _, ptOnBox = EgtSurfTmFacetOppositeSide( Face.idTrimesh, Face.id, -Edge.vtN, GDB_ID.ROOT) - -- Helper function: verifica se i vettori sono discordi lungo l'asse indicato e, se sì, se il punto iniziale della lavorazione è sul box oppure no, nella direzione dell'utensile - local function IsDiscordantAndOnBox( sAxis) - -- si compongono i metodi getX, getY, getZ in base all'asse in arrivo (Face.vtN[getX] equivale a Face.vtN:getX()) - local dFaceComponent = Face.vtN["get" .. sAxis](Face.vtN) - local dEdgeComponent = Edge.vtN["get" .. sAxis](Edge.vtN) - local dPtonboxComponent = ptOnBox["get" .. sAxis](ptOnBox) - local dMaxb3rawComponent = b3Raw:getMax()["get" .. sAxis](b3Raw:getMax()) - local dMinb3rawComponent = b3Raw:getMin()["get" .. sAxis](b3Raw:getMin()) - - if dFaceComponent * dEdgeComponent < 10 * GEO.EPS_SMALL then - if dEdgeComponent > GEO.EPS_SMALL then - return dPtonboxComponent > dMaxb3rawComponent - 500 * GEO.EPS_SMALL - else - return dPtonboxComponent < dMinb3rawComponent + 500 * GEO.EPS_SMALL - end - end - return false - end - -- in base all'orientamento, si verifica se il DownUp è fattibile - if sPlane == 'XY' then - if IsDiscordantAndOnBox( "X") then - return true - elseif IsDiscordantAndOnBox( "Y") then - return true - end - elseif sPlane == 'XZ' then - if IsDiscordantAndOnBox( "X") then - return true - elseif IsDiscordantAndOnBox( "Z") then - return true - end - elseif sPlane == 'YZ' then - if IsDiscordantAndOnBox( "Y") then - return true - elseif IsDiscordantAndOnBox( "Z") then - return true - end - end - - return false -end - - --- ritorna se la faccia e il lato sono lavorabili e, se sì, il modo di lavorare (standard/DownUp) e l'elevazione corretta (in DownUp può cambiare) -function FACEBYBLADE.GetBladeEngagement( Face, Edge, b3Raw, Tool) - local sBladeEngagement = 'Standard' - local dDownUpElevation = Edge.dElevation - - -- la normale della faccia permette di lavorare in modo standard, ma potrebbero esserci altre condizioni che fanno fallire il taglio - if not IsFaceZOutOfRange( Face.vtN, Tool) then - - -- TODO verifica collisione carro Z, collisione traversa PF, collisione 'C' Fast... La riduzione percorso cambia questo test? - - return true, sBladeEngagement - end - - -- faccia non lavorabile in modo standard: si verifica se il DownUp è fattibile - -- la normale della faccia non permette il DownUp: non lavorabile in DownUp (se taglio DownUp la faccia è lavorata al contrario, vtN opposta) - if IsFaceZOutOfRange( -Face.vtN, Tool) then - - return false - end - - -- faccia non rettangolare: non lavorabile in DownUp - if not FaceData.IsFaceRectangular( Face) then - - return false - end - - -- orientamento faccia / utensile compatibili con DownUp: lavorabile, si calcola l'elevazione reale per DownUp e si ritorna - if IsOrientationOkForDownUp( Face, Edge, b3Raw) then - - sBladeEngagement = 'DownUp' - dDownUpElevation = FaceData.GetEdgeElevationInBBox( Face, Edge, b3Raw ) - - return true, sBladeEngagement, dDownUpElevation - end - - return false -end - - -- dato un certo offset radiale (uscente) e la distanza da mantenere dallo spigolo, calcola di quanto la lama deve arretrare lateralmente rispetto al centro per lavorare il lato function FACEBYBLADE.GetPathReductionLength( nToolIndex, dRadialOffset, OptionalParameters) local Tool = TOOLS[nToolIndex] @@ -413,7 +278,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar local dDownUpElevation = dDepthToMachine -- si determina se il taglio è fattibile e il modo di lavorare della lama - Cutting.bIsApplicable, Cutting.sBladeEngagement, dDownUpElevation = FACEBYBLADE.GetBladeEngagement( FaceToMachine, EdgeToMachine, Part.b3Raw, TOOLS[nToolIndex]) + Cutting.bIsApplicable, Cutting.sBladeEngagement, dDownUpElevation = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachine, Part.b3Raw, TOOLS[nToolIndex]) -- orientamento non raggiungibile o elevazione eccessiva per DownUp: non applicabile if not Cutting.bIsApplicable @@ -434,6 +299,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade ToolSearchParameters.FaceToMachine = FaceToMachine ToolSearchParameters.EdgeToMachine = EdgeToMachine + ToolSearchParameters.b3Raw = Part.b3Raw local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) Cutting.nToolIndex = ToolInfo.nToolIndex @@ -493,7 +359,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar -- si attiva OppositeToolDirection solo se il taglio è fattibile anche in direzione opposta local EdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( FaceToMachine.Edges, -Cutting.vtToolDirection) - local bIsApplicableOpposite, sBladeEngagementOpposite, dDownUpElevationOpposite = FACEBYBLADE.GetBladeEngagement( FaceToMachine, EdgeToMachineOpposite, Part.b3Raw, TOOLS[nToolIndex]) + local bIsApplicableOpposite, sBladeEngagementOpposite, dDownUpElevationOpposite = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachineOpposite, Part.b3Raw, TOOLS[nToolIndex]) if bIsApplicableOpposite and ( sBladeEngagementOpposite == Cutting.sBladeEngagement) then