diff --git a/.gitignore b/.gitignore index 4789404..362a109 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ /bin/LuaLibs/*.lua /bin/Images/*.png .vscode/settings.json +bin/LuaLibs/.placeholder +bin/Images/.placeholder diff --git a/Compile.bat b/Compile.bat index 504701d..10126dc 100644 --- a/Compile.bat +++ b/Compile.bat @@ -11,7 +11,7 @@ REM Compilazione 32 e 64 bit \EgtProg\Dll32\luac54 -o bin\LuaLibs\WProcessDoubleCut.lua LuaLibs\WProcessDoubleCut.lua \EgtProg\Dll32\luac54 -o bin\LuaLibs\WProcessDrill.lua LuaLibs\WProcessDrill.lua \EgtProg\Dll32\luac54 -o bin\LuaLibs\WProcessDtMortise.lua LuaLibs\WProcessDtMortise.lua -REM \EgtProg\Dll32\luac54 -o bin\LuaLibs\WFeatureTopology.lua LuaLibs\WFeatureTopology.lua +\EgtProg\Dll32\luac54 -o bin\LuaLibs\WFeatureTopology.lua LuaLibs\WFeatureTopology.lua \EgtProg\Dll32\luac54 -o bin\LuaLibs\WProcessFreeContour.lua LuaLibs\WProcessFreeContour.lua \EgtProg\Dll32\luac54 -o bin\LuaLibs\WProcessLapJoint.lua LuaLibs\WProcessLapJoint.lua \EgtProg\Dll32\luac54 -o bin\LuaLibs\WProcessMark.lua LuaLibs\WProcessMark.lua diff --git a/LuaLibs/WFeatureTopology.lua b/LuaLibs/WFeatureTopology.lua new file mode 100644 index 0000000..191c868 --- /dev/null +++ b/LuaLibs/WFeatureTopology.lua @@ -0,0 +1,234 @@ +-- WFeatureTopology.lua by Egaltech s.r.l. 2023/06/23 +-- Libreria per classificazione topologica feature pareti + +-- Tabella per definizione modulo +local WFeatureTopology = {} + +-- Include +require( 'EgtBase') + +-- Carico le librerie +local WL = require( 'WallLib') + +EgtOutLog( ' WFeatureTopology started', 1) + +--------------------------------------------------------------------- +-- restituisce la matrice delle adiacenze di Proc dove i e j sono le facce e a(ij) è l'angolo tra di esse; 0 se nessuna adiacenza +local function GetAdjacencyMatrix( Proc) + local vAdj = {} + for i = 1, Proc.Fct do + vAdj[i] = {} + for j = 1, Proc.Fct do + if i == j then + vAdj[i][j] = 0 + else + _, _, _, vAdj[i][j] = EgtSurfTmFacetsContact( Proc.Id, i - 1, j - 1, GDB_ID.ROOT) + if not vAdj[i][j] then vAdj[i][j] = 0 end + end + j = j + 1 + end + i = i + 1 + end + return vAdj +end + +--------------------------------------------------------------------- +-- restituisce gli id delle facce di Proc che hanno il numero di adiacenze nAdj +function WFeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, nAdj) + local vAdj = GetAdjacencyMatrix( Proc) + local vFacesWithGivenAdj = {} + for i = 1, Proc.Fct do + local nAdjCount = 0 + for j = 1, Proc.Fct do + if vAdj[i][j] and vAdj[i][j] ~= 0 then + nAdjCount = nAdjCount + 1 + end + end + if nAdjCount == nAdj then + table.insert( vFacesWithGivenAdj, i - 1) + end + end + return vFacesWithGivenAdj +end + +--------------------------------------------------------------------- +-- restituisce true se Proc ha tutti gli angoli concavi (bAllConcave) e, nei casi in cui ha senso, se questi sono esattamente 90 deg (bAllRight) +local function AreAllAnglesConcaveOrRight( Proc) + local vAdj = GetAdjacencyMatrix( Proc) + local bAllConcave, bAllRight = true, true + for i = 1, Proc.Fct do + for j = 1, Proc.Fct do + -- se trovo un angolo convesso restituisco falso e esco subito + if vAdj[i][j] and vAdj[i][j] > 0 then + bAllConcave = false + bAllRight = false + break + elseif vAdj[i][j] and vAdj[i][j] ~= 0 and vAdj[i][j] + 90 > 500 * GEO.EPS_ANG_SMALL then + bAllRight = false + end + end + end + -- se 1 faccia oppure 2 facce con angolo convesso non ha senso ritornare valori per bAllRight + if Proc.Fct < 2 or ( Proc.Fct == 2 and vAdj[1][2] > 0) then + return bAllConcave + else + return bAllConcave, bAllRight + end +end + +--------------------------------------------------------------------- +-- restituisce true se almeno una delle dimensioni della feature è maggiore o uguale ad una delle dimensioni principali del pezzo (tolleranza 1 mm) +local function IsAnyDimensionLongAsPart( Proc) + local bResult = false + local nBoxSolidId = EgtGetFirstNameInGroup( Proc.PartId or GDB_ID.NULL, 'Box') + local b3Solid = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD) + if Proc.Box:getDimX() > b3Solid:getDimX() - 1000 * GEO.EPS_SMALL or + Proc.Box:getDimY() > b3Solid:getDimY() - 1000 * GEO.EPS_SMALL or + Proc.Box:getDimZ() > b3Solid:getDimZ() - 1000 * GEO.EPS_SMALL then + bResult = true + end + return bResult +end + +--------------------------------------------------------------------- +-- retituisce un vettore con gli indici (0 based) delle facce triangolari (o quasi) di Proc +local function GetTriangularFaces( Proc) + local vTriangularFaces = {} + for i = 1, Proc.Fct do + if WL.Is3EdgesApprox( Proc, i - 1) then + table.insert( vTriangularFaces, i - 1) + end + end + return vTriangularFaces +end + +--------------------------------------------------------------------- +-- restituisce un vettore contenente gli indici delle facce di Proc parallele ad una delle direzioni principali; il check varia in base alla famiglia topologica +local function GetFacesParallelToPart( Proc, sFamily) + local vFacesParallelToPart = {} + for i = 0, Proc.Fct - 1 do + local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i, GDB_ID.ROOT) + if sFamily == 'Bevel' or sFamily == 'DoubleBevel' then + local vTriangularFaces = GetTriangularFaces( Proc) + local bIsTriangularFace = false + -- verifico se la faccia è triangolare + for j = 1, #vTriangularFaces do + if i == vTriangularFaces[j] then + bIsTriangularFace = true + end + end + -- se faccia triangolare deve avere la normale parallela ad una direzione principale + if bIsTriangularFace then + if AreSameOrOppositeVectorApprox( vtN, X_AX()) or AreSameOrOppositeVectorApprox( vtN, Y_AX()) or AreSameOrOppositeVectorApprox( vtN, Z_AX()) then + table.insert( vFacesParallelToPart, i) + end + -- altrimenti deve avere una componente della normale nulla + else + if abs( vtN:getX()) < 10 * GEO.EPS_SMALL or abs( vtN:getY()) < 10 * GEO.EPS_SMALL or abs( vtN:getZ()) < 10 * GEO.EPS_SMALL then + table.insert( vFacesParallelToPart, i) + end + end + else + -- la normale deve essere parallela ad una direzione principale + if AreSameOrOppositeVectorApprox( vtN, X_AX()) or AreSameOrOppositeVectorApprox( vtN, Y_AX()) or AreSameOrOppositeVectorApprox( vtN, Z_AX()) then + table.insert( vFacesParallelToPart, i) + end + end + end + return vFacesParallelToPart +end + +--------------------------------------------------------------------- +-- restituisce una stringa con il nome esteso della topologia della feature +-- *famiglia-passante-angoli tutti concavi a 90deg-facce tutte parallele alle dimensioni principali-numero di facce* +local function GetTopologyLongName( sFamily, bIsThrough, bAllRightAngles, bIsParallel, nNumberOfFaces) + -- feature passante o cieca + local sThrough = '_' + if bIsThrough ~= nil then sThrough = EgtIf( bIsThrough, 'Through', 'Blind') end + -- tutti gli angoli della feature sono retti oppure no + local sAllRightAngles = '_' + if bAllRightAngles ~= nil then sAllRightAngles = EgtIf( bAllRightAngles, 'RightAngles', 'NotRightAngles') end + -- tutte le dimensioni della feature sono parallele agli assi principali del pezzo oppure no + local sParallel = '_' + if bIsParallel ~= nil then sParallel = EgtIf( bIsParallel, 'Parallel', 'NotParallel') end + + local sLongName = sFamily .. '-' .. sThrough .. '-' .. sAllRightAngles .. '-' .. sParallel .. '-' .. nNumberOfFaces + return sLongName +end + +--------------------------------------------------------------------- +-- riconosce se Proc è una delle topologie standard e, in caso positivo, ne scrive le caratteristiche in campi specifici della Proc stessa restituendo true +function WFeatureTopology.Classify( Proc) + local bRecognized = false + local sFamily + local bIsThrough + local bAllRightAngles + local bIsParallel + local sLongName = '' + + -- SE NON HA TUTTE LE FACCE PIANE RITORNARE NIL!! + + local bAllAnglesConcave + bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( Proc) + local vTriangularFaces = GetTriangularFaces( Proc) + local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc) + local vFacesWithTwoAdj = WFeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, 2) + local vFacesWithThreeAdj = WFeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, 3) + local vFacesWithFourAdj = WFeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, 4) + + if Proc.IsOutline then + sFamily = 'OUTLINE' + elseif Proc.Prc == 40 then + sFamily = 'DRILLING' + elseif Proc.Fct == 1 and bIsAnyDimensionLongAsPart then + sFamily = 'Bevel' + bIsThrough = true + elseif Proc.Fct == 2 and bAllAnglesConcave and #vTriangularFaces == 1 then + sFamily = 'Bevel' + bIsThrough = false + elseif Proc.Fct == 2 and bAllAnglesConcave then + sFamily = 'Rabbet' + bIsThrough = true + elseif Proc.Fct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then + sFamily = 'DoubleBevel' + bIsThrough = true + elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithTwoAdj == 1 and #vTriangularFaces == 2 then + sFamily = 'Bevel' + bIsThrough = false + elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithTwoAdj == 1 and bIsAnyDimensionLongAsPart then + sFamily = 'Groove' + bIsThrough = true + elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithTwoAdj == 3 then + sFamily = 'Groove' + bIsThrough = false + elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithThreeAdj == 2 then + sFamily = 'Groove' + bIsThrough = false + elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithTwoAdj == 4 and bIsAnyDimensionLongAsPart then + sFamily = 'Tunnel' + bIsThrough = true + elseif Proc.Fct == 5 and bAllAnglesConcave and #vFacesWithFourAdj == 1 then + sFamily = 'Pocket' + bIsThrough = false + end + local vFacesParallelToPart = GetFacesParallelToPart( Proc, sFamily) + bIsParallel = ( #vFacesParallelToPart == Proc.Fct) + + if sFamily == 'OUTLINE' or sFamily == 'DRILLING' then + Proc.Topology = sFamily + Proc.TopologyLongName = sFamily + bRecognized = true + elseif sFamily then + sLongName = GetTopologyLongName( sFamily, bIsThrough, bAllRightAngles, bIsParallel, Proc.Fct) + Proc.Topology, Proc.IsThrough, Proc.AllRightAngles, Proc.IsParallel, Proc.TopologyLongName = sFamily, bIsThrough, bAllRightAngles, bIsParallel, sLongName + bRecognized = true + else + Proc.Topology = 'OTHER' + Proc.TopologyLongName = 'OTHER' + end + + return bRecognized +end + +------------------------------------------------------------------------------------------------------------- +return WFeatureTopology \ No newline at end of file diff --git a/LuaLibs/WMachiningLib.lua b/LuaLibs/WMachiningLib.lua index 9ffd7f6..d4cbf8d 100644 --- a/LuaLibs/WMachiningLib.lua +++ b/LuaLibs/WMachiningLib.lua @@ -3,8 +3,8 @@ -- 2023/03/09 Piccola correzione alla SideDepth in FindMilling -- In FindMilling aggiunta gestione spessore e massimo materiale nel caso di lam -- 2023/05/25 Aggiunta funzione AddMachining che incapsula EgtAddMachining trascrivendo le priorità btl dalle feature alle lavorazioni. --- 2023/06/07 Alla funzione AddMachining aggiunta la scrittura dell'info ISOUTLINE alle lavorazioni. -- 2023/10/18 In SetCurrMachiningAndTool sostituito controllo di utensile attivo con controllo utensile nel setup corrente. +-- 2023/11/14 Modifiche sostanziali per l'aggiunta delle lavorazioni in doppio e per il miglioramento nella gestione delle tasche. -- Tabella per definizione modulo local WMachiningLib = {} @@ -56,7 +56,7 @@ function WMachiningLib.FindCutting( sType, dDepth, nTool_ID) end --------------------------------------------------------------------- -function WMachiningLib.FindMilling( sType, dDepth, sTuuid, nTool_ID, dMaxDiam, dMaxMat, bTipFeed, dMinSideElev) +function WMachiningLib.FindMilling( sType, dDepth, sTuuid, nTool_ID, dMaxDiam, dMaxMat, bTipFeed, dMinSideElev, sHead) for i = 1, #Millings do local Milling = Millings[i] if Milling.On and Milling.Type == sType and SetCurrMachiningAndTool( Milling.Name) then @@ -70,6 +70,7 @@ function WMachiningLib.FindMilling( sType, dDepth, sTuuid, nTool_ID, dMaxDiam, d local dTTipFeed = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) local dTMaxDepthOnSide = EgtIf( bIsBlade, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), min( EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or 999, 0.5 * ( dTDiam - dTDiamTh))) local nMyTool_ID = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'Tool_ID', 'i') + local sMyHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) if nMchType == MCH_MY.MILLING and ( not sTuuid or sTuuid == sMyTuuid) and ( not dDepth or dTMaxDepth > dDepth - GEO.EPS_SMALL) and @@ -77,7 +78,8 @@ function WMachiningLib.FindMilling( sType, dDepth, sTuuid, nTool_ID, dMaxDiam, d ( not dMaxMat or dTMaxMat < dMaxMat + GEO.EPS_SMALL) and ( not bTipFeed or dTTipFeed > 1) and ( not dMinSideElev or dTMaxDepthOnSide > dMinSideElev - GEO.EPS_SMALL) and - ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) then + ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) and + ( not sHead or sHead == sMyHead) then return Milling.Name, dTMaxDepth, dTMaxMat, dTDiam end end @@ -100,18 +102,32 @@ function WMachiningLib.FindNailing( nType) end --------------------------------------------------------------------- -function WMachiningLib.FindPocketing( sType, dMaxDiam, dDepth, nTool_ID) +function WMachiningLib.FindPocketing( sType, dMaxDiam, dDepth, nTool_ID, sHead, bExcludeNoTipFeed, dDistanceToNearestPart) + if not dMaxDiam then dMaxDiam = 999 end for i = 1, #Pocketings do local Pocketing = Pocketings[i] if Pocketing.On and Pocketing.Type == sType and SetCurrMachiningAndTool( Pocketing.Name) then local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE) local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) local dTMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) - local nMyTool_ID = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'Tool_ID', 'i') + local nMyTool_ID = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'Tool_ID', 'i') + local sMyHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) + local bHasTipFeed = ( EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) ~= 0) + -- attacco con rampa molto lunga e step basso, utilizzabile anche con frese che non lavorano di testa + local bIsSpecialLeadIn = ( EgtMdbGetCurrMachiningParam( MCH_MP.LEADINTYPE) == MCH_POCK_LI.ZIGZAG or MCH_POCK_LI.HELIX) and + ( ( EgtMdbGetCurrMachiningParam( MCH_MP.LITANG) or 0) > dTDiam - 1 - 10 * GEO.EPS_SMALL) and + ( ( EgtMdbGetCurrMachiningParam( MCH_MP.LIELEV) or 999) <= 2) + local bIsSpiralOut = EgtMdbGetCurrMachiningParam( MCH_MP.SUBTYPE) == MCH_POCK_SUB.SPIRALOUT + -- se ho un altro pezzo troppo vicino riduco il diametro massimo utensile + if dDistanceToNearestPart then + dMaxDiam = min( dMaxDiam, EgtIf( bIsSpiralOut, dDistanceToNearestPart * 2 + 5, dDistanceToNearestPart + 5)) + end if nMchType == MCH_MY.POCKETING and ( not dMaxDiam or dTDiam < dMaxDiam + GEO.EPS_SMALL) and ( not dDepth or dTMaxDepth > dDepth - GEO.EPS_SMALL) and - ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) then + ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) and + ( not sHead or sHead == sMyHead) and + ( not bExcludeNoTipFeed or bHasTipFeed or bIsSpecialLeadIn) then return Pocketing.Name, dTDiam, dTMaxDepth end end @@ -183,8 +199,8 @@ function WMachiningLib.FindSurfacing( sType) end end --- incapsulo EgtAddMachining e trascrivo alcune informazioni utili nelle note dell'operazione --------------------------------------------------------------------- +-- incapsulo EgtAddMachining e trascrivo alcune informazioni utili nelle note dell'operazione function WMachiningLib.AddMachining( Proc, sName, sMachining) local nMchId, sFinalName = EgtAddMachining( sName, sMachining) if type( Proc) == 'table' then @@ -195,5 +211,60 @@ function WMachiningLib.AddMachining( Proc, sName, sMachining) return nMchId, sFinalName end +--------------------------------------------------------------------- +-- verifica se utensile sToolMasterName e gemello sToolDoubleName sono compatibili con la specchiatura +function WMachiningLib.IsToolDoubleOk( sToolMasterName, sToolDoubleName) + local bIsToolDoubleOk = false + -- dimensioni utensile master + EgtTdbSetCurrTool( sToolMasterName) + local bIsBlade = ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE ~= 0) or false + local dTMaxMat = EgtIf( bIsBlade, EgtTdbGetCurrToolParam( MCH_TP.THICK), EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)) + local dTMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, dTMaxMat, EgtTdbGetCurrToolMaxDepth()) + local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) + local dTDiamTh = EgtTdbGetCurrToolThDiam() or 0 + local bHasTipFeed = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) ~= 0 + local dTMaxDepthOnSide = EgtIf( bIsBlade, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), min( EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or 999, 0.5 * ( dTDiam - dTDiamTh))) + local bIsPrimaryHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) == 'H1' + -- dimensioni utensile double + EgtTdbSetCurrTool( sToolDoubleName) + local bIsBladeDouble = ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE ~= 0) or false + local dTMaxMatDouble = EgtIf( bIsBladeDouble, EgtTdbGetCurrToolParam( MCH_TP.THICK), EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)) + local dTMaxDepthDouble = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, dTMaxMatDouble, EgtTdbGetCurrToolMaxDepth()) + local dTDiamDouble = EgtTdbGetCurrToolParam( MCH_TP.DIAM) + local dTDiamThDouble = EgtTdbGetCurrToolThDiam() or 0 + local bHasTipFeedDouble = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) ~= 0 + local dTMaxDepthOnSideDouble = EgtIf( bIsBladeDouble, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), min( EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or 999, 0.5 * ( dTDiamDouble - dTDiamThDouble))) + -- controllo che siano uguali ( permetto una leggera differenza di lunghezza) + local dMaxLengthDifference = 6.5 + bIsToolDoubleOk = bIsPrimaryHead and + ( bIsBlade == bIsBladeDouble) and + ( dTMaxMatDouble > dTMaxMat - 100 * GEO.EPS_SMALL) and + ( dTMaxDepthDouble > dTMaxDepth - dMaxLengthDifference) and + ( abs( dTDiam - dTDiamDouble) < 100 * GEO.EPS_SMALL) and + ( abs( dTDiamTh - dTDiamThDouble) < 100 * GEO.EPS_SMALL) and + ( bHasTipFeed == bHasTipFeedDouble) and + ( abs( dTMaxDepthOnSide - dTMaxDepthOnSideDouble) < GEO.EPS_SMALL) and + EgtFindToolInCurrSetup( sToolDoubleName) + return bIsToolDoubleOk +end + +--------------------------------------------------------------------- +-- verifica se la lavorazione sMachining è adatta alla specchiatura +function WMachiningLib.IsMachiningOkForDouble( sMachining) + local bDoubleOk = false + if sMachining and EgtMdbSetCurrMachining( sMachining) then + -- recupero l'utensile della lavorazione + local sToolMasterName = EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) + if EgtTdbSetCurrTool( sToolMasterName or '') then + -- cerco eventuale utensile in doppio + local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') + if sToolDoubleName and EgtTdbSetCurrTool( sToolDoubleName) then + bDoubleOk = WMachiningLib.IsToolDoubleOk( sToolMasterName, sToolDoubleName) + end + end + end + return bDoubleOk +end + ------------------------------------------------------------------------------------------------------------- return WMachiningLib diff --git a/LuaLibs/WProcessDoubleCut.lua b/LuaLibs/WProcessDoubleCut.lua index 92e2ac9..a4ee365 100644 --- a/LuaLibs/WProcessDoubleCut.lua +++ b/LuaLibs/WProcessDoubleCut.lua @@ -1,6 +1,7 @@ -- WProcessDoubleCut.lua by Egaltech s.r.l. 2023/04/17 -- Gestione calcolo doppi tagli di lama per Pareti -- 2023/04/17 Quando si chiama LapJoint si trasforma il Gruppo da 1 a 3 e da 2 a 4. +-- 2023/11/14 Aggiunta funzione IdentifyStrict per il riconoscimento della sola feature L011. -- Tabella per definizione modulo local WPDC = {} @@ -24,6 +25,12 @@ function WPDC.Identify( Proc) ( Proc.Grp == 0 and Proc.Prc == 12)) end +--------------------------------------------------------------------- +-- Riconoscimento della sola feature L011 +function WPDC.IdentifyStrict( Proc) + return ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 11 +end + --------------------------------------------------------------------- -- Classificazione della feature function WPDC.Classify( Proc, b3Raw) diff --git a/LuaLibs/WProcessDrill.lua b/LuaLibs/WProcessDrill.lua index 6865dc9..b2e01aa 100644 --- a/LuaLibs/WProcessDrill.lua +++ b/LuaLibs/WProcessDrill.lua @@ -9,6 +9,7 @@ -- 2022/02/22 ES Aggiunta gestione prefori. -- 2022/03/08 DS Vanno accettati fori orizzontali sul bordo anche senza foratori orizzontali speciali. -- 2023/05/25 Funzioni EgtAddMachining sostituite da WM.AddMachining in modo da trascrivere le priorità da btl alle lavorazioni. +-- 2023/11/14 Aggiunta gestione forature in doppio. -- Tabella per definizione modulo local WPD = {} @@ -55,7 +56,7 @@ end --------------------------------------------------------------------- -- Classificazione della feature -function WPD.Classify( Proc, b3Raw) +function WPD.Classify( Proc, b3Raw) -- recupero e verifico l'entità foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 @@ -156,6 +157,41 @@ function WPD.RotateClassify( Proc) end end +--------------------------------------------------------------------- +local function IsToolDoubleOk( sToolMasterName, sToolDoubleName) + local bIsToolDoubleOk = false + -- dimensioni utensile master + EgtTdbSetCurrTool( sToolMasterName) + local dTMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) + local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) + -- dimensioni utensile double + EgtTdbSetCurrTool( sToolDoubleName) + local dTMaxMatDouble = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) + local dTDiamDouble = EgtTdbGetCurrToolParam( MCH_TP.DIAM) + -- controllo che siano uguali + bIsToolDoubleOk = ( dTMaxMatDouble > dTMaxMat - 100 * GEO.EPS_SMALL) and + ( abs( dTDiam - dTDiamDouble) < 100 * GEO.EPS_SMALL) and + EgtFindToolInCurrSetup( sToolDoubleName) + return bIsToolDoubleOk +end + +--------------------------------------------------------------------- +local function IsMachiningOkForDouble( sMachining) + local bDoubleOk = false + if sMachining and EgtMdbSetCurrMachining( sMachining) then + -- recupero l'utensile della lavorazione + local sToolMasterName = EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) + if EgtTdbSetCurrTool( sToolMasterName or '') then + -- cerco eventuale utensile in doppio + local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') + if sToolDoubleName and EgtTdbSetCurrTool( sToolDoubleName) then + bDoubleOk = IsToolDoubleOk( sToolMasterName, sToolDoubleName) + end + end + end + return bDoubleOk +end + --------------------------------------------------------------------- local function IsHorizLongDrill( Proc) -- recupero e verifico l'entità foro @@ -263,10 +299,21 @@ function WPD.Make( Proc, nRawId, b3Raw) end end end + local bUseDLenToFindDrilling = true local sDrilling, nType = WM.FindDrilling( dDiam, dLen, sHead) if not sDrilling then + bUseDLenToFindDrilling = false sDrilling, nType = WM.FindDrilling( dDiam, nil, sHead) end + -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata + if Proc.Double and Proc.Double == 2 then + local sDrillingBackup = sDrilling + sDrilling = WM.FindDrilling( dDiam, EgtIf( bUseDLenToFindDrilling, dLen, nil), 'H1') + if not IsMachiningOkForDouble( sDrilling) then + Proc.Double = 0 + sDrilling = sDrillingBackup + end + end if sHead and not sDrilling then sDrilling, nType = WM.FindDrilling( dDiam, dLen) if not sDrilling then @@ -447,21 +494,26 @@ function WPD.Make( Proc, nRawId, b3Raw) end end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) - -- Note utente - local sUserNotes = '' + -- leggo eventuali note esistenti della lavorazione + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- se foratura o svuotatura, dichiarazione nessuna generazione sfridi per Vmill if nType == 'Drill' or nType == 'Pocket' then - sUserNotes = 'VMRS=0;' + sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0) end -- se foratura if nType == 'Drill' then -- aggiungo alle note massima elevazione (coincide con affondamento) - sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dDepth, 1) .. ';' + sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dDepth, 1)) -- se foro passante, aggiungo questa qualifica alle note if bOpen then - sUserNotes = sUserNotes .. 'Open=1;' + sUserNotes = EgtSetValInNotes( sUserNotes, 'Open', 1) end end + -- se lavorazione in doppio aggiungo le rispettive note + if Proc.Double and Proc.Double == 2 then + sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) + sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) + end EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then diff --git a/LuaLibs/WProcessFreeContour.lua b/LuaLibs/WProcessFreeContour.lua index e1c4d15..9a0ebbb 100644 --- a/LuaLibs/WProcessFreeContour.lua +++ b/LuaLibs/WProcessFreeContour.lua @@ -25,6 +25,8 @@ -- 2023/09/21 In MakeByMill modificato SCC per correggere caso con lama su testa fresa. -- 2023/09/26 In Is3EdgesApprox aggiunta cancellazione dei loop temporanei. -- 2023/10/02 Correzione a MakeCustomPath per calcolare correttamente puliture spigoli di tipo 2 (Clean 30) e 3 (Gola di Scarico). +-- 2023/11/14 Spostamento di alcune funzioni in WallLib. +-- Aggiunta dei FreeContour in doppio. -- Tabella per definizione modulo local WPF = {} @@ -155,64 +157,6 @@ function WPF.FlipClassify( Proc, b3Raw) return nFlip0, nFlip1 end ---------------------------------------------------------------------- -local function TestElleShape3( nIdGeom, nNumFacet) - -- valida solo nel caso di tre facce - if nNumFacet ~= 3 then return false end - -- determino se L con una faccia terminale o U con tre facce - local bIsL = true - for i = 1, 3 do - local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1] - -- le conto - local nCount = 0 - for j = 1, #vFacAdj do - if vFacAdj[j] >= 0 then - nCount = nCount + 1 - end - end - if nCount == 1 then - bIsL = false - break - end - end - return bIsL -end - ---------------------------------------------------------------------- -local function TestElleShape4( nIdGeom, nNumFacet) - -- valida solo nel caso di quattro facce - if nNumFacet ~= 4 then return false end - -- determino se L con due facce terminali o O - local nFac3Adj = 0 - local dMinArea3 = GEO.INFINITO * GEO.INFINITO - local dMaxArea2 = 0 - for i = 1, 4 do - local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1] - -- le conto - local nCount = 0 - for j = 1, #vFacAdj do - if vFacAdj[j] >= 0 then - nCount = nCount + 1 - end - end - local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nIdGeom, i - 1, GDB_ID.ROOT) - local dArea = dH * dV - if nCount == 2 then - dMaxArea2 = max( dMaxArea2, dArea) - elseif nCount == 3 then - dMinArea3 = min( dMinArea3, dArea) - nFac3Adj = nFac3Adj + 1 - end - end - if nFac3Adj ~= 2 then return false end - -- verifico se L profonda oppure lunga - if dMinArea3 < dMaxArea2 then - return 1 - else - return 2 - end -end - --------------------------------------------------------------------- local function VerifyCornerType( Proc) -- Verifico il tipo di lavorazione su angolo : @@ -1212,35 +1156,6 @@ local function GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen) end end ---------------------------------------------------------------------- --- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce -local function Is3EdgesApprox( Proc, nFacet, nAddGrpId) - nAddGrpId = nAddGrpId or WL.GetAddGroup( Proc.PartId) - -- recupero il contorno della faccia - local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.Id, nFacet, nAddGrpId) - if not nContourId then return false end - EgtMergeCurvesInCurveCompo( nContourId) - -- recupero il numero di lati del contorno - local _, nEntityCount = EgtCurveDomain( nContourId) - if not nEntityCount then return false end - -- se sono già tre, ho finito - if nEntityCount == 3 then return true end - -- rimuovo i lati molto corti dal conteggio totale - local nEdges = nEntityCount - for i = 1, nEntityCount do - local dLength = EgtCurveCompoLength( nContourId, i - 1) - if dLength < 15 then nEdges = nEdges - 1 end - end - -- verifico il numero significativo di lati - local bResult = ( nEdges == 3) - -- cancello tutti i contorni appena creati - EgtErase( EgtTableFill( nContourId, nContourCnt)) - if bResult then - EgtOutLog( 'FreeContour : Face with ' .. tostring( nEntityCount) .. ' edges skipped (approx 3 edges)') - end - return bResult -end - --------------------------------------------------------------------- local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId) -- flag per fresature non passanti @@ -1263,7 +1178,7 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAdd end -- verifico se le facce hanno alcuni lati molto corti e possono quindi essere approssimate a 3 lati for currentFace = 1, #vFace do - if Is3EdgesApprox( Proc, vFace[currentFace].Fac, nAddGrpId) then + if WL.Is3EdgesApprox( Proc, vFace[currentFace].Fac, nAddGrpId) then vFace[currentFace].Is3EdgesApprox = true end end @@ -1369,6 +1284,8 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAdd nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) + -- scrivo nell'operazione il vettore normale alla superfice che servirà per il doppio + EgtSetInfo( nMchId or GDB_ID.NULL, 'NORM_SUM', vFace[i].Norm) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() @@ -1566,6 +1483,13 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAdd -- posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP) end + --scrivo nell'operazione il vettore somma delle normali alle superfici che servirà per il doppio + local vtNSum = Vector3d( 0, 0, 0) + for iGeom = 1, #vGeom do + local nFace = vGeom[iGeom][2] + vtNSum = vtNSum + Proc.Face[ nFace + 1].VtN + end + EgtSetInfo( nMchId or GDB_ID.NULL, 'NORM_SUM', vtNSum) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() @@ -1628,6 +1552,8 @@ local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAdd nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) + -- scrivo nell'operazione il vettore normale alla superfice che servirà per il doppio + EgtSetInfo( nMchId or GDB_ID.NULL, 'NORM_SUM', vFace[i].Norm) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() @@ -2478,9 +2404,9 @@ local function MakeByPocket( Proc, nRawId, b3Raw) local nAddGrpId = WL.GetAddGroup( Proc.PartId) local nNewProc, nNumFacet = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet) -- se ho forma a L - local bIsL = ( nNumFacet == 2 or TestElleShape3( nNewProc, nNumFacet) or TestElleShape4( nNewProc, nNumFacet) == 2) + local bIsL = ( nNumFacet == 2 or WL.TestElleShape3( nNewProc, nNumFacet) or WL.TestElleShape4( nNewProc, nNumFacet) == 2) -- verifico se U - local bIsU = ( nNumFacet == 3 and not TestElleShape3( nNewProc, nNumFacet)) + local bIsU = ( nNumFacet == 3 and not WL.TestElleShape3( nNewProc, nNumFacet)) local dMiddleFacetLength = 0 if bIsU then local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( nNewProc, 1, GDB_ID.ROOT) diff --git a/LuaLibs/WProcessLapJoint.lua b/LuaLibs/WProcessLapJoint.lua index 1c13bc7..6a43f81 100644 --- a/LuaLibs/WProcessLapJoint.lua +++ b/LuaLibs/WProcessLapJoint.lua @@ -30,6 +30,8 @@ -- 2023/09/21 Modifica controllo lavorabilità con tre facce tipo tunnel ma non ortogonali tra loro. -- 2023/09/21 In MakeByMill modificato SCC per correggere caso con lama su testa fresa. -- 2023/10/02 Aggiunta segnalazione lavorazione tipo Side non trovata. +-- 2023/11/14 Aggiunta tasche in doppio. +-- Miglioramenti sostanziali nella gestione delle tasche. -- Tabella per definizione modulo local WPL = {} @@ -358,64 +360,6 @@ function WPL.FlipClassify( Proc) return nFlip0, nFlip1 end ---------------------------------------------------------------------- -local function TestElleShape3( nIdGeom, nNumFacet) - -- valida solo nel caso di tre facce - if nNumFacet ~= 3 then return false end - -- determino se L con una faccia terminale o U con tre facce - local bIsL = true - for i = 1, 3 do - local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1] - -- le conto - local nCount = 0 - for j = 1, #vFacAdj do - if vFacAdj[j] >= 0 then - nCount = nCount + 1 - end - end - if nCount == 1 then - bIsL = false - break - end - end - return bIsL -end - ---------------------------------------------------------------------- -local function TestElleShape4( nIdGeom, nNumFacet) - -- valida solo nel caso di quattro facce - if nNumFacet ~= 4 then return false end - -- determino se L con due facce terminali o O - local nFac3Adj = 0 - local dMinArea3 = GEO.INFINITO * GEO.INFINITO - local dMaxArea2 = 0 - for i = 1, 4 do - local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1] - -- le conto - local nCount = 0 - for j = 1, #vFacAdj do - if vFacAdj[j] >= 0 then - nCount = nCount + 1 - end - end - local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nIdGeom, i - 1, GDB_ID.ROOT) - local dArea = dH * dV - if nCount == 2 then - dMaxArea2 = max( dMaxArea2, dArea) - elseif nCount == 3 then - dMinArea3 = min( dMinArea3, dArea) - nFac3Adj = nFac3Adj + 1 - end - end - if nFac3Adj ~= 2 then return false end - -- verifico se L profonda oppure lunga - if dMinArea3 < dMaxArea2 then - return 1 - else - return 2 - end -end - --------------------------------------------------------------------- local function GetOtherRegions( nPartId) local vOthers = {} @@ -1336,6 +1280,54 @@ local function MakeByChainSaw( Proc, nFacet, nRawId, b3Raw, dElev, dH, dV) return true end +--------------------------------------------------------------------- +-- restituisce true se la lavorazione potrebbe danneggiare le parti limitrofe +local function IsMachiningDamagingOtherParts( Proc, dMillDiameter, nRawId) + local bIsMachiningDamagingOtherParts = false + -- box da estendere in tutte le direzioni, compreso angolo cieco + local b3ProcExtended = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) + -- punto minimo e massimo assoluti del box + local ptMin = b3ProcExtended:getMin() + local ptMax = b3ProcExtended:getMax() + -- estensione aggiunta ai box + local dBoxExtensionLength = dMillDiameter / 2 + 5 + -- check box verso X- + if Proc.AffectedFaces.Left then + local vtMove = Vector3d( -dBoxExtensionLength, 0, 0) + ptMin:move( vtMove) + end + -- check box verso X+ + if Proc.AffectedFaces.Right then + local vtMove = Vector3d( dBoxExtensionLength, 0, 0) + ptMax:move( vtMove) + end + -- check box verso Y- + if Proc.AffectedFaces.Front then + local vtMove = Vector3d( 0, -dBoxExtensionLength, 0) + ptMin:move( vtMove) + end + -- check box verso Y+ + if Proc.AffectedFaces.Back then + local vtMove = Vector3d( 0, dBoxExtensionLength, 0) + ptMax:move( vtMove) + end + -- estendo il box in direzione X e Y e verifico se interseca altre parti + b3ProcExtended:Add( ptMin) + b3ProcExtended:Add( ptMax) + local nPartId = EgtGetFirstPartInRawPart( nRawId) + while nPartId do + local nBoxSolidId = EgtGetFirstNameInGroup( nPartId, 'Box') + local b3Solid = EgtGetBBoxGlob( nBoxSolidId or GDB_ID.NULL, GDB_BB.STANDARD) + b3Solid:expand( - 10 * GEO.EPS_SMALL) + if ( nPartId ~= Proc.PartId) and OverlapsXY( b3ProcExtended, b3Solid) then + bIsMachiningDamagingOtherParts = true + end + nPartId = EgtGetNextPartInRawPart( nPartId) + end + + return bIsMachiningDamagingOtherParts +end + --------------------------------------------------------------------- local function MakeByMill( Proc, nFacet, nOthFac, nRawId, b3Raw, dSideDist) -- dati della faccia e dell'altra @@ -1346,6 +1338,14 @@ local function MakeByMill( Proc, nFacet, nOthFac, nRawId, b3Raw, dSideDist) local _, vtRef = EgtSurfTmFacetCenter( Proc.Id, nOthFac, GDB_ID.ROOT) -- recupero la lavorazione local sMilling = WM.FindMilling( 'Side') + if Proc.Double and Proc.Double == 2 then + local sMillingBackup = sMilling + sMilling = WM.FindMilling( 'Side', nil, nil, nil, nil, nil, nil, nil, 'H1') + if not WM.IsMachiningOkForDouble( sMilling) then + Proc.Double = 0 + sMilling = sMillingBackup + end + end if not sMilling then local sErr = 'Error : Side not found in library' EgtOutLog( sErr) @@ -1413,6 +1413,16 @@ local function MakeByMill( Proc, nFacet, nOthFac, nRawId, b3Raw, dSideDist) -- imposto modo di lavorare la faccia local nFaceUse = WL.GetNearestOrthoOpposite( vtRef, vtN) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) + -- leggo eventuali note esistenti della lavorazione + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) + -- se lavorazione in doppio aggiungo le rispettive note + if Proc.Double and Proc.Double == 2 then + sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) + sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) + sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ) + end + -- scrivo le note della lavorazione + EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() @@ -1423,7 +1433,7 @@ local function MakeByMill( Proc, nFacet, nOthFac, nRawId, b3Raw, dSideDist) end --------------------------------------------------------------------- -local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, dMaxDepthOnSide, bEnablePreMill, bMachFromDn, dAng, bAsEnablePreMill, nSinglePass, bExcludeFinishing) +local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, dMaxDepthOnSide, bEnablePreMill, bMachFromDn, dAng, bAsEnablePreMill, nSinglePass, bExcludeFinishing, bDoubleCustomMach) local sWarn -- dati della faccia principale (la più verticale) local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) @@ -1444,9 +1454,20 @@ local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, d -- se ho lavorazione custom if sCustomMach then sMilling = sCustomMach + -- se avevo stabilito che la customMach non era adatta al double, setto per non specchiare + if not bDoubleCustomMach then Proc.Double = 0 end -- altrimenti la cerco else sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV)) + -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata + if Proc.Double and Proc.Double == 2 then + local sMillOnSideBackup = sMilling + sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, nil, 'H1') + if not WM.IsMachiningOkForDouble( sMilling) then + Proc.Double = 0 + sMilling = sMillOnSideBackup + end + end end if not sMilling then local sErr = 'Error : SideGroove not found in library' @@ -1497,10 +1518,14 @@ local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, d end end -- se profondità ribasso è maggiore della capacità di sottosquadro dell'utensile - if ( not bEnablePreMill and bMachFromDn) and ( dElev > 0.5 * ( dMillDiam - dMillDiamTh) - 10 * GEO.EPS_SMALL) then - local sErr = 'Error : Side Elevation (' .. dElev .. ') bigger than max tool side depth (' .. ( 0.5 * ( dMillDiam - dMillDiamTh)) ..')' - EgtOutLog( sErr) - return false, sErr + if ( dElev > 0.5 * ( dMillDiam - dMillDiamTh) - 10 * GEO.EPS_SMALL) then + if ( not bEnablePreMill and ( bMachFromDn or Proc.Fct > 2)) then + local sErr = 'Error : Side Elevation (' .. dElev .. ') bigger than max tool side depth (' .. ( 0.5 * ( dMillDiam - dMillDiamTh)) ..')' + EgtOutLog( sErr) + return false, sErr + elseif Proc.Double then + Proc.Double = 0 + end end local dMillExtra = dMillTotLen - dMillLen if Proc.Box:getMin():getZ() - dMillExtra < b3Raw:getMin():getZ() - 10 * GEO.EPS_SMALL then @@ -1871,6 +1896,78 @@ local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, d bUpwardMilling = true end + -- step extra in caso di doppio con mix rabbet dal basso e dall'alto, per eliminare la lamina che potrebbe rimanere + if Proc.Double and Proc.Double == 2 and Proc.Topology == 'Rabbet' and + not ( Proc.AffectedFaces.Bottom and Proc.Mirror.AffectedFaces.Bottom) and not ( Proc.AffectedFaces.Top and Proc.AffectedFaces.Bottom) then + -- determino a quale delle due feature applicare la lavorazione + local bProcVsMirrorToCopy = true + local nFacetToMachine = nFacet + if Proc.AffectedFaces.Bottom then + bProcVsMirrorToCopy = false + for i = 1, Proc.Mirror.Fct do + local vtNMirror = Proc.Mirror.Face[i].VtN + if AreOppositeVectorApprox( vtN, vtNMirror) then + nFacetToMachine = Proc.Mirror.Face[i].Id + break + end + end + end + local nAddGrpId = WL.GetAddGroup( EgtIf( bProcVsMirrorToCopy, Proc.PartId, Proc.Mirror.PartId)) + local nNewProc = EgtCopyGlob( EgtIf( bProcVsMirrorToCopy, Proc.Id, Proc.Mirror.Id), nAddGrpId) or GDB_ID.NULL + local NewProc = { Id = nNewProc, PartId = EgtIf( bProcVsMirrorToCopy, Proc.PartId, Proc.Mirror.PartId)} + -- lavorazione + local sName = 'PreSideMill_' .. EgtGetName( NewProc.Id) or tostring( NewProc.Id) + local nMchFId = WM.AddMachining( NewProc, sName, sMilling) + if not nMchFId then + local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling + EgtOutLog( sErr) + return false, sErr + end + EgtSetInfo( nMchFId, 'Part', NewProc.PartId) + -- aggiungo geometria + EgtSetMachiningGeometry( {{ NewProc.Id, nFacetToMachine}}) + -- imposto posizione braccio porta testa + local nSCC = MCH_SCC.ADIR_NEAR + EgtSetMachiningParam( MCH_MP.SCC, nSCC) + -- imposto modo di lavorare la faccia + local nFaceUse = WL.GetNearestParalOpposite( Z_AX()) + EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) + -- imposto elevazione e step + local dDepth = 5 + EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) + EgtSetMachiningParam( MCH_MP.STEP, dElev) + -- setto il lato di lavoro standard + EgtSetMachiningParam( MCH_MP.INVERT, true) + EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) + -- setto allungamenti iniziali e finali + EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) + EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) + -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita + if dElev > ( 0.5 * dMillDiam) then + -- setto allungamenti perpendicolari + EgtSetMachiningParam( MCH_MP.LIPERP, 0) + EgtSetMachiningParam( MCH_MP.LOPERP, 0) + end + -- se richiesto, setto la nota per spostare la lavorazione alla fine + if not WD.SIDEMILL_BEFORE then + EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) + end + -- eseguo + if not EgtApplyMachining( true, false) then + -- provo a invertire posizione braccio porta testa + nSCC = MCH_SCC.ADIR_FAR + EgtSetMachiningParam( MCH_MP.SCC, nSCC) + if not EgtApplyMachining( true, false) then + local _, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nMchFId, false) + return false, sErr + end + end + -- se faccio lo step extra e ho rimosso la lamina, in doppio lavorerò dal basso verso l'alto + bUpwardMilling = true + end + + -- lavorazione local dStepOri if not bExcludeSideMill then local nSideStep = 1 @@ -1921,6 +2018,12 @@ local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, d local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- aggiungo alle note massima elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev, 3)) + -- se lavorazione in doppio aggiungo le rispettive note + if Proc.Double and Proc.Double == 2 then + sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) + sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) + sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ) + end -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- setto il lato di lavoro standard @@ -2154,61 +2257,140 @@ local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, d end --------------------------------------------------------------------- -local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) - -- dati della faccia - local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) - local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) +-- trova la migliore lavorazione tasca in base a diametro utensile, elevazione, doppio e eventuale interferenza di parti vicine +-- se necessario forza la tasca a chiusa +local function VerifyPocket( Proc, nFacet, dElev, nRawId) + + local bForceClosedPocket = false + local b3Raw = EgtGetRawPartBBox( nRawId) + -- verifico se la feature è sul bordo (non ci sono altri pezzi davanti alla tasca). Se è sul bordo, l'utensile potrà attaccare da fuori. + local bIsFeatureOnEdge = ( Proc.Topology == 'Groove' and Proc.Fct == 4 and Proc.DistanceToNearestParts.Front > b3Raw:getDimY()) + + -- trovo il massimo diametro utensile ammissibile per la tasca local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) - local dDiam = min( dH, dV) - -- gruppo ausiliario - local nAddGrpId = WL.GetAddGroup( Proc.PartId) - local nNewProc, nNumFacet = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet) - -- se una sola faccia + local dStartDiameter = min( dH, dV) + local dMaxDiameter = dStartDiameter + -- se una sola faccia posso usare un utensile più grande della faccia if Proc.Fct == 1 then - dDiam = 2 * dDiam + dMaxDiameter = 2 * dMaxDiameter end - -- se forma ad L - local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc.Id, Proc.Fct) or TestElleShape4( Proc.Id, Proc.Fct) == 2) + -- se forma ad L posso usare un utensile più grande della faccia + local bIsL = ( Proc.Fct == 2 or WL.TestElleShape3( Proc.Id, Proc.Fct) or WL.TestElleShape4( Proc.Id, Proc.Fct) == 2) if bIsL then - dDiam = 2 * dDiam + dMaxDiameter = 2 * dMaxDiameter end - -- se forma ad U - local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc.Id, Proc.Fct)) + -- se forma ad U riduco il diametro se necessario + local bIsU = ( Proc.Fct == 3 and not WL.TestElleShape3( Proc.Id, Proc.Fct)) if bIsU then - local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) -- prendo la linea di base local dMiddleFacetLength = 0 - if abs( dElev - dH2) < 1 and abs( dElev - dV2) > 1 then - dMiddleFacetLength = dV2 - elseif abs( dElev - dV2) < 1 and abs( dElev - dH2) > 1 then - dMiddleFacetLength = dH2 + if abs( dElev - dH) < 1 and abs( dElev - dV) > 1 then + dMiddleFacetLength = dV + elseif abs( dElev - dV) < 1 and abs( dElev - dH) > 1 then + dMiddleFacetLength = dH end - if dMiddleFacetLength > dDiam then - dDiam = min( 2 * dDiam, dMiddleFacetLength) + if dMiddleFacetLength > dMaxDiameter then + dMaxDiameter = min( 2 * dMaxDiameter, dMiddleFacetLength) end end -- in presenza di angoli interni, limito secondo impostazione globale il diametro massimo utensile if Proc.Fct == 3 and bIsL then - dDiam = min( dDiam, WD.MAXDIAM_POCK_CORNER or 1000) + dMaxDiameter = min( dMaxDiameter, WD.MAXDIAM_POCK_CORNER or 1000) elseif Proc.Fct >= 4 then - dDiam = min( dDiam, WD.MAXDIAM_POCK_CORNER or 1000) + dMaxDiameter = min( dMaxDiameter, WD.MAXDIAM_POCK_CORNER or 1000) end + + -- verifico la distanza minima dalle parti vicine e nel caso il FindPocketing limiterà il diametro massimo dell'utensile + local dDistanceToNearestPart = GEO.INFINITO + if Proc.AffectedFaces.Front then + dDistanceToNearestPart = Proc.DistanceToNearestParts.Front + end + if Proc.AffectedFaces.Back then + dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Back) + end + if Proc.AffectedFaces.Left then + dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Left) + end + if Proc.AffectedFaces.Right then + dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Right) + end + -- se la distanza è inferiore ad un valore minimo forzo la tasca chiusa per evitare che la ricerca utensile fallisca + local dMinToolDiameter = 25 + if dDistanceToNearestPart < dMinToolDiameter / 2 - 10 * GEO.EPS_SMALL then + bForceClosedPocket = true + dDistanceToNearestPart = dMaxDiameter + end + + local bExcludeNoTipFeed = ( Proc.Topology == 'Pocket') -- recupero la lavorazione - local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dElev) + local bUseDElevToFindPocketing = true + local sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, dElev, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) + -- se tasca troppo profonda cerco senza elevazione e limiterò la profondità if not sPocketing then - sPocketing = WM.FindPocketing( 'Pocket', dDiam) - if not sPocketing then - local sErr = 'Error : pocketing not found in library' - EgtOutLog( sErr) - return false, sErr - end + bUseDElevToFindPocketing = false + sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, nil, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) end - -- recupero i dati dell'utensile local dMillDiam = 20 local dMaxDepth = 0 local dThDiam = 100 local sTuuid - if EgtMdbSetCurrMachining( sPocketing) then + -- se lavorazione trovata verifico eventuale doppio, raccolgo i dati utensile e verifico collisioni dell'utensile con altre parti + if sPocketing then + -- se doppio cerco una lavorazione adatta + if Proc.Double and Proc.Double == 2 then + local sPocketingBackup = sPocketing + sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, EgtIf( bUseDElevToFindPocketing, dElev, nil), nil, 'H1', true, dDistanceToNearestPart) + if not WM.IsMachiningOkForDouble( sPocketing) then + Proc.Double = 0 + sPocketing = sPocketingBackup + end + end + -- recupero diametro utensile + if EgtMdbSetCurrMachining( sPocketing) then + sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) + if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then + dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam + end + end + -- verifico se la lavorazione (o il suo eventuale mirror) potrebbe danneggiare le parti limitrofe e devo quindi forzare una tasca chiusa + local bIsMachiningDamagingOtherParts = IsMachiningDamagingOtherParts( Proc, dMillDiam, nRawId) + if bIsMachiningDamagingOtherParts then + bForceClosedPocket = true + end + -- disattivo il doppio se devo forzare una tasca chiusa ma l'altra no + if Proc.Double and Proc.Double > 0 then + local bIsMirrorMachiningDamagingOtherParts = IsMachiningDamagingOtherParts( Proc.Mirror, dMillDiam, nRawId) + if bIsMachiningDamagingOtherParts ~= bIsMirrorMachiningDamagingOtherParts then + Proc.Double = 0 + end + end + -- altrimenti diametro utensile troppo piccolo: devo forzare tasca chiusa + else + bForceClosedPocket = true + end + + -- se tasca chiusa cerco lavorazione con diametro massimo pari a dimensione tasca e riverifico per eventuale doppio + if bForceClosedPocket then + dMaxDiameter = dStartDiameter + bUseDElevToFindPocketing = true + sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, dElev, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) + if not sPocketing then + bUseDElevToFindPocketing = false + sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, nil, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) + end + -- se doppio cerco una lavorazione adatta + if Proc.Double and Proc.Double == 2 then + local sPocketingBackup = sPocketing + sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, EgtIf( bUseDElevToFindPocketing, dElev, nil), nil, 'H1', true, dDistanceToNearestPart) + if not WM.IsMachiningOkForDouble( sPocketing) then + Proc.Double = 0 + sPocketing = sPocketingBackup + end + end + end + + -- recupero dati utensile + if sPocketing and EgtMdbSetCurrMachining( sPocketing) then sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam @@ -2216,6 +2398,25 @@ local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam end end + + return sPocketing, bForceClosedPocket, bIsFeatureOnEdge, sTuuid, dMillDiam, dMaxDepth, dThDiam +end +--------------------------------------------------------------------- +local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) + -- dati della faccia + local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) + local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) + -- gruppo ausiliario + local nAddGrpId = WL.GetAddGroup( Proc.PartId) + local nNewProc = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet) + -- cerco lavorazione adatta e recupero i dati utensile + local sPocketing, bForceClosedPocket, bIsFeatureOnEdge, sTuuid, dMillDiam, dMaxDepth, dThDiam = VerifyPocket( Proc, nFacet, dElev, nRawId) + if not sPocketing then + local sErr = 'Error : pocketing not found in library' + EgtOutLog( sErr) + return false, sErr + end + -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = WM.AddMachining( Proc, sName, sPocketing) @@ -2251,6 +2452,20 @@ local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- imposto elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( min( dElev, dMaxDepth), 1)) + -- se lavorazione in doppio aggiungo le rispettive note + if Proc.Double and Proc.Double == 2 then + sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) + sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) + sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ) + -- escludo ottimizzazioni e forzo attacco interno perchè la tasca specchiata potrebbe essere nel mezzo del pannello + sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxOptSize', 0.1) + EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALOUT) + end + -- setto eventuale nota per forzare tasca chiusa + if bForceClosedPocket then sUserNotes = EgtSetValInNotes( sUserNotes, 'Open', 0) end + -- setto eventuale nota per forzare attacco esterno, fino ad un certo spessore del grezzo + local dMaxRawThicknessToStartOut = 75 + if bIsFeatureOnEdge and ( not Proc.Double or Proc.Double == 0) then sUserNotes = EgtSetValInNotes( sUserNotes, 'OpenMinSafe', dMaxRawThicknessToStartOut) end -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo @@ -2259,7 +2474,9 @@ local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) EgtSetOperationMode( nMchFId, false) return false, sErr end + -- verifica parametro Q per pulitura spigoli + local bIsU = ( Proc.Fct == 3 and not WL.TestElleShape3( Proc.Id, Proc.Fct)) if bCheckQPar and not ( bIsU and AreSameOrOppositeVectorApprox( vtN, Z_AX())) then -- lettura parametri (probabile/i parametro/i Q) local nConeCut = EvaluateQParam( Proc) @@ -2267,7 +2484,7 @@ local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) local vFace, dMaxWidth = GetFacesData( nNewProc, false, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, Proc.PartId) -- se abilitata la lavorazione corner con stop macchina if nConeCut == 1 then - local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, + local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, dMillDiam, nAddGrpId, dMaxWidth, nNewProc, dDepth) if not bMcok then return bMcok, sMcErr end elseif nConeCut == 2 then @@ -2383,7 +2600,18 @@ local function MakeTwoFaces( Proc, nRawId, b3Raw) dMinSideElev = dDimY[2] end end - local sMillOnSide, dTMaxDepth, dMaxMat, dDiam = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev) + local sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev) + -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata + local bDoubleMillOnSide = false + if Proc.Double and Proc.Double == 2 then + local sMillOnSideBackup = sMillOnSide + sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev, 'H1') + if WM.IsMachiningOkForDouble( sMillOnSide) then + bDoubleMillOnSide = true + else + sMillOnSide = sMillOnSideBackup + end + end local bEnableMillOnSide if sMillOnSide and nUseMillOnSide >= 1 then dMaxZVers = 0.866 @@ -2444,7 +2672,7 @@ local function MakeTwoFaces( Proc, nRawId, b3Raw) end -- se posso eseguire la lavorazione per distanza inferiore utensile o lavorazione preceduta da sgossatura gola if bInsertMach then - return MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng) + return MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, nil, nil, nil, bDoubleMillOnSide) else local sErr = 'Error feature not machinable (dimensions)' EgtOutLog( sErr) @@ -2512,10 +2740,10 @@ local function MakeTwoFaces( Proc, nRawId, b3Raw) local bMachFromDn = false local bInsertMach if dSideDist and dSideDist < dMaxDist then - -- se abilitata SideMill - if bEnableMillOnSide and dMaxDepthOnSide > 0 then + -- se abilitata SideMill oppure se la specchiata guarda in basso e quindi l'attacco deve essere a filo + if ( bEnableMillOnSide and dMaxDepthOnSide > 0) or ( Proc.Double == 2 and Proc.MirrorDeltaZ and abs( Proc.MirrorDeltaZ) > GEO.EPS_SMALL) then bLikeAsMakeFirstGroove = false - return MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove) + return MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove, nil, nil, bDoubleMillOnSide) else local bOk, sErr = MakeByMill( Proc, nFacet, 1 - nFacet, nRawId, b3Raw, dSideDist) -- se angolo ottuso riprendo il lato quasi verticale @@ -2526,7 +2754,7 @@ local function MakeTwoFaces( Proc, nRawId, b3Raw) end elseif bEnableMillOnSide and dMaxDepthOnSide > 0 then bLikeAsMakeFirstGroove = true - local bOk, sErr = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove) + local bOk, sErr = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove, nil, nil, bDoubleMillOnSide) if bOk then return true end end -- se non inclinate o capacità di taglio non sufficiente o non molto grandi (80mm), provo con contornatura o svuotatura @@ -2629,6 +2857,17 @@ local function MakeMoreFaces( Proc, nRawId, b3Raw) local dSideElev = WL.GetFaceElevation( Proc.Id, nFacInd) -- se abilitata lavorazione ribasso con fresa di fianco e parametro Q03 abilitato local sMillOnSide, dTMaxDepth, dMaxMat, dDiam = WM.FindMilling( 'SideMill', nil, nil, nil, nil, min( dH, dV), nil, dSideElev) + -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata + local bDoubleMillOnSide = false + if Proc.Double and Proc.Double == 2 then + local sMillOnSideBackup = sMillOnSide + sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, min( dH, dV), nil, dSideElev, 'H1') + if WM.IsMachiningOkForDouble( sMillOnSide) then + bDoubleMillOnSide = true + else + sMillOnSide = sMillOnSideBackup + end + end local _, nUseMillOnSide = EvaluateQParam( Proc) -- se ho abilitata lavorazione di fresa di fianco if Proc.Fct >= 3 and sMillOnSide and nUseMillOnSide >= 1 and not bIsSmallSlot then @@ -2669,14 +2908,27 @@ local function MakeMoreFaces( Proc, nRawId, b3Raw) nSinglePass = 2 bMakeFirstGroove = false end - return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, EgtIf( dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, nil, nil, bLikeAsMakeFirstGroove, nSinglePass) + return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, EgtIf( dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, nil, nil, bLikeAsMakeFirstGroove, nSinglePass, nil, bDoubleMillOnSide) end else -- fresatura (se definita); se disponibile, cerco di usare un utensile che non lavori al limite della capacità di sottosquadro - local sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, 1.2 * dSideElev) + local dSideElevMultiplier = 1.2 + local sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElevMultiplier * dSideElev) -- se non ho trovato un utensile un po' più grande del sottosquadro richiesto, passo alla ricerca standard if not sMilling then sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElev) + dSideElevMultiplier = 1 + end + -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata + bDoubleMillOnSide = false + if Proc.Double and Proc.Double == 2 then + local sMillOnSideBackup = sMillOnSide + sMillOnSide = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElevMultiplier * dSideElev, 'H1') + if WM.IsMachiningOkForDouble( sMillOnSide) then + bDoubleMillOnSide = true + else + sMillOnSide = sMillOnSideBackup + end end -- recupero i dati dell'utensile local dMaxMat = 1000 @@ -2701,7 +2953,7 @@ local function MakeMoreFaces( Proc, nRawId, b3Raw) end end if sMilling and dElev < dMaxDepthOnSide then - return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, sMilling) + return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, sMilling, nil, nil, nil, nil, nil, nil, nil, bDoubleMillOnSide) -- altrimenti sega a catena else return MakeByChainSaw( Proc, nFacInd, nRawId, b3Raw, dElev, dH, dV) diff --git a/LuaLibs/WallExec.lua b/LuaLibs/WallExec.lua index 2b6d933..4ffabc6 100644 --- a/LuaLibs/WallExec.lua +++ b/LuaLibs/WallExec.lua @@ -5,6 +5,8 @@ -- 2023/06/27 Aggiunte origini TN e BN. -- 2023/07/04 Se c'è funzione di macchina WD.GetOrigCorner si lascia scegliere posizione default a questa impostando 0 se non c'è 'REFPOS'. -- 2023/10/16 Aggiunta gestione Aree vietate (LockOut) per chiodature. +-- 2023/11/14 Modifiche sostanziali per l'aggiunta delle lavorazioni in doppio. +-- In Collect aggiunto il recupero preliminare di varie informazioni sulla feature. -- Tabella per definizione modulo local WallExec = {} @@ -25,6 +27,7 @@ if WALL and WALL.NESTINGCORNERBL then WD.NESTING_CORNER = 'BL' end -- Carico le librerie _G.package.loaded.WMachiningLib = nil _G.package.loaded.WallLib = nil +_G.package.loaded.WFeatureTopology = nil _G.package.loaded.WProcessCut = nil _G.package.loaded.WProcessDoubleCut = nil _G.package.loaded.WProcessSawCut = nil @@ -38,6 +41,7 @@ _G.package.loaded.WProcessFreeContour = nil _G.package.loaded.WProcessVariant = nil local WM = require( 'WMachiningLib') local WL = require( 'WallLib') +local Topology = require( 'WFeatureTopology') local Cut = require( 'WProcessCut') local DoubleCut = require( 'WProcessDoubleCut') local SawCut = require( 'WProcessSawCut') @@ -191,6 +195,19 @@ function WallExec.CollectFeatures( PartId, b3Raw) Proc.TaskId = nTaskId Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) Proc.IsOutline = ( Proc.Prc == 251 or Proc.Prc == 252) + if b3Raw then + -- recupero l'elenco delle facce della parte interessate dalla feature + Proc.AffectedFaces = WL.GetProcessAffectedFaces( Proc) + -- recupero le distanze tra la feature e le altre parti più vicine + Proc.DistanceToNearestParts = WL.GetProcessDistanceToNearestParts( Proc) + -- recupero le distanze tra la feature e il grezzo + Proc.DistanceToRawPart = WL.GetProcessDistanceToRawPart( Proc, b3Raw) + -- recupero informazioni sulle facce della feature + Proc.Face = {} + for i = 1, Proc.Fct do + Proc.Face[i] = { Id = i - 1, VtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT ), Elevation = WL.GetFaceElevation( Proc.Id, i - 1, PartId)} + end + end if Proc.Box and not Proc.Box:isEmpty() then table.insert( vProc, Proc) -- se foro @@ -291,14 +308,27 @@ local function ClassifyFeatures( vProc, b3Raw) end end +------------------------------------------------------------------------------------------------------------- +local function ClassifyTopology( vProc) + local nRecognized = 0 + for i = 1, #vProc do + local Proc = vProc[i] + if Topology.Classify( Proc) then + nRecognized = nRecognized + 1 + end + end + + return nRecognized +end + ------------------------------------------------------------------------------------------------------------- local function PrintFeatures( vProc) EgtOutLog( ' *** Feature List ***') for i = 1, #vProc do local Proc = vProc[i] - local sOut = string.format( 'Part=%3d Proc=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Lo=%d Fcse=%1d,%1d Diam=%.2f Fct=%2d Dbl=%2d Dlt=%.1f Box=%s', + local sOut = string.format( 'Part=%3d Proc=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Lo=%d Fcse=%1d,%1d Diam=%.2f Fct=%2d Dbl=%2d Dlt=%.1f Box=%s TopoName=%s', Proc.PartId, Proc.Id, Proc.Grp, Proc.Prc, Proc.TaskId, Proc.CutId, - Proc.Flg, EgtIf( Proc.LockOut, 1, 0), Proc.Fcs, Proc.Fce, Proc.Diam, Proc.Fct, Proc.Double or 0, Proc.Delta or 0, tostring( Proc.Box)) + Proc.Flg, EgtIf( Proc.LockOut, 1, 0), Proc.Fcs, Proc.Fce, Proc.Diam, Proc.Fct, Proc.Double or 0, Proc.Delta or 0, tostring( Proc.Box), Proc.TopologyLongName or '') EgtOutLog( sOut) end end @@ -579,6 +609,8 @@ local function SortMachinings( nPhase, PrevMch, nPartId, nPriority) PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFFINISHING, nil, nil, 'MOVE_AFTER', false, nil, nil, nil, nPriority) -- Fresature per gole PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Gorge_'}, true, 'MOVE_AFTER', false, nil, nil, nil, nPriority) + -- Fresature da fare prima delle SideMill + PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'PreSideMill_'}, true, 'MOVE_AFTER', false, false, true, true, nPriority) -- Fresature che sono rifiniture di spigoli PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'SideMill_'}, true, 'MOVE_AFTER', false, false, true, true, nPriority) -- Fresature che sono puliture di spigoli @@ -589,6 +621,8 @@ local function SortMachinings( nPhase, PrevMch, nPartId, nPriority) PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.SAWING, nil, nil, nil, nil, nil, nil, nil, nPriority) -- Qui rimozione sfridi (se ci sono lavorazioni successive) if not nPriority then + -- Fresature da fare prima delle SideMill + PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'PreSideMill_'}, true, 'MOVE_AFTER', true, false, true, true) -- Fresature dei lapjoint che necessitano di gorge PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'SideMill_'}, true, 'MOVE_AFTER', true, false, true, true) -- Tagli con sega a catena che vanno fatti dopo i tagli con lama @@ -626,6 +660,406 @@ function InsertScrapRemoval( nPhase) EgtSetCurrMachining( nActiveMachiningId or GDB_ID.NULL) end +------------------------------------------------------------------------------------------------------------- +-- funzione per l'ordinamento delle features in doppio da accoppiare +-- ordinate prima in base alla X e poi alla Y +local function SortFeaturesForMirror( Proc1, Proc2) + -- tolleranza di ricerca + local TOL = EgtIf( Proc1.TopologyLongName == 'DRILLING', WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1 , WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) + -- recupero i centri dei box lungo X e Y + local Proc1X = Proc1.Box:getCenter():getX() + local Proc1Y = Proc1.Box:getCenter():getY() + local Proc2X = Proc2.Box:getCenter():getX() + local Proc2Y = Proc2.Box:getCenter():getY() + -- confronto per ordinamento + if Proc1X < Proc2X - TOL then + return true + elseif abs( Proc1X - Proc2X) < TOL then + if Proc1Y < Proc2Y - TOL then + return true + end + end +end + +------------------------------------------------------------------------------------------------------------- +-- funzione per l'ordinamento delle operazioni in doppio da accoppiare +-- ordinate prima in base alla X e poi alla Y +local function SortOperationsForMirror( nOper1, nOper2) + -- tolleranza di ricerca + local TOL = 0.1 + -- recupero il box della prima operazione + local nClId1 = EgtGetFirstNameInGroup( nOper1, 'CL') + local ptMin1 = EgtGetInfo( nClId1, 'MMIN', 'p') + local ptMax1 = EgtGetInfo( nClId1, 'MMAX', 'p') + local b3Oper1 = BBox3d( ptMin1, ptMax1) + -- recupero il box delle seconda operazione + local nClId2 = EgtGetFirstNameInGroup( nOper2, 'CL') + local ptMin2 = EgtGetInfo( nClId2, 'MMIN', 'p') + local ptMax2 = EgtGetInfo( nClId2, 'MMAX', 'p') + local b3Oper2 = BBox3d( ptMin2, ptMax2) + -- recupero i centri dei box lungo X e Y + local dOper1X = b3Oper1:getCenter():getX() + local dOper1Y = b3Oper1:getCenter():getY() + local dOper2X = b3Oper2:getCenter():getX() + local dOper2Y = b3Oper2:getCenter():getY() + -- confronto per ordinamento + if dOper1X < dOper2X - TOL then + return true + elseif abs( dOper1X - dOper2X) < TOL then + if dOper1Y < dOper2Y - TOL then + return true + end + end +end + +------------------------------------------------------------------------------------------------------------- +-- Controlla in vProc la presenza di feature da lavorare in doppio e, se trovate, ne setta i parametri +local function SetMirroredFeatures( vProc, b3Raw) + -- interasse minimo + local dMinimumDistanceMirroredFeatures = 780 + -- inizializzazione array tasche e forature + local vPockets = {} + local vDrillings = {} + + -- raccolgo le feature compatibili con doppio + for i = 1, #vProc do + local Proc = vProc[i] + if Proc.Flg ~= 0 then + -- raccolgo le tasche compatibili + if WD.DOUBLE_HEAD_POCKET and + ( + ( Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2' and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right) or + ( Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' and ( not Proc.AffectedFaces.Bottom and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right)) or + ( Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-3') or + ( Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4') or + ( Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' and not Proc.AffectedFaces.Bottom) + ) then + table.insert( vPockets, Proc) + -- raccolgo i fori verticali e aperti verso Z+ + elseif WD.DOUBLE_HEAD_DRILLING and Proc.TopologyLongName == 'DRILLING' then + -- recupero e verifico la geometria del foro + local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 + if AuxId then AuxId = AuxId + Proc.Id end + if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then + return false + end + local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) + if Proc.AffectedFaces.Top and AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then + table.insert( vDrillings, Proc) + end + end + end + end + + -- ordinamento delle feature raccolte secondo X e poi Y crescente + table.sort( vPockets, SortFeaturesForMirror) + table.sort( vDrillings, SortFeaturesForMirror) + + -- accoppio le tasche + local nCurrentPocket = 1 + while nCurrentPocket <= #vPockets do + local Proc = vPockets[nCurrentPocket] + if Proc.Flg ~= 0 then + local b3Proc = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) + -- cerco evenutale specchiata + local nCurrentMirrorPocket = nCurrentPocket + 1 + while nCurrentMirrorPocket <= #vPockets do + local ProcMirror = vPockets[nCurrentMirrorPocket] + local b3ProcMirror = EgtGetBBoxGlob( ProcMirror.Id, GDB_BB.STANDARD) + -- feature non disattivata e diversa da nCurrentPocket + local bIsMirrorIdOk = ( Proc.Id ~= ProcMirror.Id and ProcMirror.Flg ~= 0) + -- feature mirror della stessa classe topologica + local bIsMirrorTopologyOk = ( Proc.TopologyLongName == ProcMirror.TopologyLongName) + -- determino se di fianco o in mezzo al singolo pannello + local bLapVsTop = Proc.AffectedFaces.Front and + ( + Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2' or + Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' or + Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-3' or + Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' or + Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' + ) + -- se di fianco, determino se è l'ultima parte prima della fine del grezzo + local bIsFeatureOnEdge, bIsMirrorFeatureOnEdge = false, false + if bLapVsTop then + bIsFeatureOnEdge = Proc.DistanceToNearestParts.Front > b3Raw:getDimY() + bIsMirrorFeatureOnEdge = ProcMirror.DistanceToNearestParts.Back > b3Raw:getDimY() + end + -- se di fianco, si sceglie se le feature sono compatibili con il doppio e nel caso che tipo di lavorazione fare + -- -1: no doppio, 0: nessuna preferenza, 1: pocket, 2: side (scambio faccia principale) + local nDoubleType = 0 + local bAllowSideOnMirror = ( ProcMirror.DistanceToRawPart.Back - Proc.DistanceToRawPart.Front < 1 + 10 * GEO.EPS_SMALL) or ( not WD.SIDEMILL_BEFORE and ( not Proc.AffectedFaces.Top or not ProcMirror.AffectedFaces.Top)) + if bLapVsTop and ( Proc.AffectedFaces.Top or Proc.AffectedFaces.Bottom) then + -- side + if bIsFeatureOnEdge and bIsMirrorFeatureOnEdge then + if not ( Proc.AffectedFaces.Top and ProcMirror.AffectedFaces.Top) then + nDoubleType = 2 + end + -- no doppio + elseif Proc.AffectedFaces.Bottom or ProcMirror.AffectedFaces.Bottom then + nDoubleType = -1 + -- tasca + else + nDoubleType = 1 + end + end + -- corrispondenza nella posizione delle feature. Se di fianco il lato master è sempre quello verso l'operatore, se sopra nessun vincolo + local bIsMirrorSideOk = ( bLapVsTop and ProcMirror.AffectedFaces.Back and bIsFeatureOnEdge and bIsMirrorFeatureOnEdge and bAllowSideOnMirror) or + Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' and Proc.AffectedFaces.Top and ProcMirror.AffectedFaces.Top or + Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' and Proc.AffectedFaces.Top and Proc.AffectedFaces.Left and ProcMirror.AffectedFaces.Top and ProcMirror.AffectedFaces.Left or + Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' and Proc.AffectedFaces.Top and Proc.AffectedFaces.Right and ProcMirror.AffectedFaces.Top and ProcMirror.AffectedFaces.Right or + Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' and Proc.AffectedFaces.Top and ProcMirror.AffectedFaces.Top + -- box delle stesse dimensioni + local bIsMirrorFeatureSameDimension = abs( b3Proc:getDimX() - b3ProcMirror:getDimX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and + abs( b3Proc:getDimY() - b3ProcMirror:getDimY()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and + abs( b3Proc:getDimZ() - b3ProcMirror:getDimZ()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) + -- box allineati in X + local bIsMirrorBoxXAligned = abs( Proc.Box:getCenter():getX() - ProcMirror.Box:getCenter():getX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) + -- box che non si intersecano + local bIsNotMirrorBoxOverlapping = not OverlapsXY( b3Proc, b3ProcMirror) + -- distanza minima tra le feature + local dYMinDistance = max( b3Proc:getMin():getY(), b3ProcMirror:getMin():getY()) - min( b3Proc:getMax():getY(), b3ProcMirror:getMax():getY()) + local bIsMirrorFeatureDistanceOk = dYMinDistance > dMinimumDistanceMirroredFeatures + 10 * GEO.EPS_SMALL + -- se tutte vere le condizioni, calcolo i parametri da passare alle lavorazioni + if nDoubleType > -1 and bIsMirrorIdOk and bIsMirrorTopologyOk and bIsMirrorSideOk and bIsMirrorFeatureSameDimension and bIsMirrorBoxXAligned and bIsNotMirrorBoxOverlapping and bIsMirrorFeatureDistanceOk then + local dYMirrorAx + local b3Tab = EgtGetTableArea() + local ptOnMirrorAx = ( Proc.Box:getCenter() + ProcMirror.Box:getCenter()) / 2 + dYMirrorAx = ptOnMirrorAx:getY() - b3Tab:getMin():getY() + local dDeltaZ = ProcMirror.Box:getMax():getZ() - Proc.Box:getMax():getZ() + -- forzo side o pocket, se necessario + if nDoubleType == 1 then + EgtSetInfo( Proc.Id, 'PCKT', 1) + EgtSetInfo( ProcMirror.Id, 'PCKT', 1) + elseif nDoubleType == 2 then + Proc.Stype = 2 + ProcMirror.Stype = 2 + end + -- scrivo i parametri nella lavorazione + -- 2: specchiatura in Y + Proc.Double = 2 + Proc.Mirror = ProcMirror + -- posizione Y dell'asse di specchiatura + Proc.MirrorAx = dYMirrorAx + -- Offset Z tra le feature + Proc.MirrorDeltaZ = dDeltaZ + + -- rimuovo dalla lista le pocket già assegnate + local ProcMirrorOldId = ProcMirror.Id + table.remove( vPockets, nCurrentPocket) + -- avendo rimosso un elemento dall'array, potrebbe essere cambiato l'elemento nCurrentMirrorPocket + if nCurrentMirrorPocket > #vPockets or ( vPockets[nCurrentMirrorPocket].Id ~= ProcMirrorOldId) then nCurrentMirrorPocket = nCurrentMirrorPocket - 1 end + table.remove( vPockets, nCurrentMirrorPocket) + nCurrentPocket = 0 + break + end + nCurrentMirrorPocket = nCurrentMirrorPocket + 1 + end + end + nCurrentPocket = nCurrentPocket + 1 + end + + -- accoppio le forature + local nCurrentDrilling = 1 + while nCurrentDrilling <= #vDrillings do + local Proc = vDrillings[nCurrentDrilling] + if Proc.Flg ~= 0 then + local b3Proc = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) + -- cerco evenutale specchiata + local nCurrentMirrorDrilling = nCurrentDrilling + 1 + while nCurrentMirrorDrilling <= #vDrillings do + local ProcMirror = vDrillings[nCurrentMirrorDrilling] + local b3ProcMirror = EgtGetBBoxGlob( ProcMirror.Id, GDB_BB.STANDARD) + -- feature non disattivata e diversa da nCurrentDrilling + local bIsMirrorIdOk = ( Proc.Id ~= ProcMirror.Id and ProcMirror.Flg ~= 0) + -- box delle stesse dimensioni + local bIsMirrorFeatureSameDimension = abs( b3Proc:getDimX() - b3ProcMirror:getDimX()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) and + abs( b3Proc:getDimY() - b3ProcMirror:getDimY()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) and + abs( b3Proc:getDimZ() - b3ProcMirror:getDimZ()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) + -- box allineati in X + local bIsMirrorBoxXAligned = abs( Proc.Box:getCenter():getX() - ProcMirror.Box:getCenter():getX()) < ( WD.DOUBLE_HEAD_DRILLING_TOLERANCE or 0.1) + -- box che non si intersecano + local bIsNotMirrorBoxOverlapping = not OverlapsXY( b3Proc, b3ProcMirror) + -- distanza minima tra le feature + local dYMinDistance = max( b3Proc:getMin():getY(), b3ProcMirror:getMin():getY()) - min( b3Proc:getMax():getY(), b3ProcMirror:getMax():getY()) + local bIsMirrorFeatureDistanceOk = dYMinDistance > dMinimumDistanceMirroredFeatures + 10 * GEO.EPS_SMALL + -- se tutte vere le condizioni, calcolo i parametri da passare alle lavorazioni + if bIsMirrorIdOk and bIsMirrorFeatureSameDimension and bIsMirrorBoxXAligned and bIsNotMirrorBoxOverlapping and bIsMirrorFeatureDistanceOk then + local dYMirrorAx + local b3Tab = EgtGetTableArea() + local ptOnMirrorAx = ( Proc.Box:getCenter() + ProcMirror.Box:getCenter()) / 2 + dYMirrorAx = ptOnMirrorAx:getY() - b3Tab:getMin():getY() + -- scrivo i parametri nella lavorazione + -- 2: specchiatura in Y + Proc.Double = 2 + Proc.Mirror = ProcMirror + -- posizione Y dell'asse di specchiatura + Proc.MirrorAx = dYMirrorAx + + -- rimuovo dalla lista le forature già assegnate + local ProcMirrorOldId = ProcMirror.Id + table.remove( vDrillings, nCurrentDrilling) + -- avendo rimosso un elemento dall'array, potrebbe essere cambiato l'elemento nCurrentMirrorDrilling + if nCurrentMirrorDrilling > #vDrillings or ( vDrillings[nCurrentMirrorDrilling].Id ~= ProcMirrorOldId) then nCurrentMirrorDrilling = nCurrentMirrorDrilling - 1 end + table.remove( vDrillings, nCurrentMirrorDrilling) + nCurrentDrilling = 0 + break + end + nCurrentMirrorDrilling = nCurrentMirrorDrilling + 1 + end + end + nCurrentDrilling = nCurrentDrilling + 1 + end +end + +------------------------------------------------------------------------------------------------------------- +-- verifico e imposto le fresature da specchiare +local function SetMirroredOperations() + -- interasse minimo + local dMinimumDistanceMirroredOperations = 780 + -- inzializzazione array + local vMillings = {} + + -- raccolgo le fresature non già fatte in doppio + if WD.DOUBLE_HEAD_MILLCORNER then + local nOperId = EgtGetNextOperation( EgtGetPhaseDisposition( 1)) + while nOperId do + EgtSetCurrMachining( nOperId) + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) + local bIsDouble = ( EgtGetValInNotes( sUserNotes, 'DOUBLE', 'i') or 0) > 0 + if EgtGetOperationMode( nOperId) and not EgtIsMachiningEmpty( nOperId) and not bIsDouble and EgtGetOperationType( nOperId) == MCH_OY.MILLING then + table.insert( vMillings, nOperId) + end + nOperId = EgtGetNextOperation( nOperId) + end + end + + -- ordinamento delle operazioni raccolte secondo X e poi Y crescente + table.sort( vMillings, SortOperationsForMirror) + + -- accoppio le fresature + local nCurrentMilling = 1 + while nCurrentMilling <= #vMillings do + local nOperIdMaster = vMillings[nCurrentMilling] + EgtSetCurrMachining( nOperIdMaster) + local sMachining = EgtGetMachiningParam( MCH_MP.NAME, 's') + local nClId = EgtGetFirstNameInGroup( nOperIdMaster, 'CL') + local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL) + -- vettore direzione utensile e somma normali facce per lavorazione master + local vtTool = EgtGetInfo( nPathId, 'EXTR', 'v') + local vtNormSum = EgtGetInfo( nOperIdMaster, 'NORM_SUM', 'v') + local ptMin = EgtGetInfo( nClId, 'MMIN', 'p') + local ptMax = EgtGetInfo( nClId, 'MMAX', 'p') + -- box percorso lavorazione master + local b3Operation = BBox3d( ptMin, ptMax) + -- lavorazione master adatta alla specchiatura + local bIsMachiningOk = WM.IsMachiningOkForDouble( sMachining) + if bIsMachiningOk then + -- recupero la distanza tra centro di rotazione e punta dell'utensile per aumentare o ridurre l'interasse minimo + local dTipToPivot, dTipToPivotDouble = 999, 999 + local dToolMasterTotLength, dToolMasterTotLengthDouble = 999, 999 + local sToolMasterName = '' + if EgtMdbSetCurrMachining( sMachining) then + -- recupero l'utensile della lavorazione e il suo doppio + sToolMasterName = EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) + if EgtTdbSetCurrTool( sToolMasterName or '') then + dToolMasterTotLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dToolMasterTotLength + local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') + if sToolDoubleName and EgtTdbSetCurrTool( sToolDoubleName) then + dToolMasterTotLengthDouble = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dToolMasterTotLengthDouble + end + end + end + if WD.HEAD_PIVOT_MAIN and WD.HEAD_PIVOT_SECONDARY then + dTipToPivot = dToolMasterTotLength + WD.HEAD_PIVOT_MAIN + dTipToPivotDouble = dToolMasterTotLengthDouble + WD.HEAD_PIVOT_SECONDARY + else + local sOut = 'Error : HEAD_PIVOT_MAIN or HEAD_PIVOT_SECONDARY missing in WallData' + return false, sOut + end + -- cerco eventuale specchiata + local nCurrentMirrorMilling = nCurrentMilling + 1 + while nCurrentMirrorMilling <= #vMillings do + local nOperIdMirror = vMillings[nCurrentMirrorMilling] + EgtSetCurrMachining( nOperIdMirror) + local nClIdMirror = EgtGetFirstNameInGroup( nOperIdMirror, 'CL') + local nPathIdMirror = EgtGetFirstInGroup( nClIdMirror or GDB_ID.NULL) + -- vettore direzione utensile e somma normali facce per lavorazione mirror + local vtToolMirror = EgtGetInfo( nPathIdMirror, 'EXTR', 'v') + local vtNormSumMirror = EgtGetInfo( nOperIdMirror, 'NORM_SUM', 'v') + local ptMinMirror = EgtGetInfo( nClIdMirror, 'MMIN', 'p') + local ptMaxMirror = EgtGetInfo( nClIdMirror, 'MMAX', 'p') + -- box percorso lavorazione mirror + local b3OperationMirror = BBox3d( ptMinMirror, ptMaxMirror) + -- utensile originale lavorazione specchiata + local sOriginalMirrorToolName = EgtGetMachiningParam( MCH_MP.TOOL) + local bIsOriginalMirrorToolSameSize = WM.IsToolDoubleOk( sToolMasterName, sOriginalMirrorToolName) + -- lavorazione mirror adatta alla specchiatura + local bIsMirrorMachiningOk = nOperIdMaster ~= nOperIdMirror + -- lavorazione master più a sinistra + local bIsMirrorSideOk = ( b3OperationMirror:getCenter():getY() - b3Operation:getCenter():getY()) > ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) + -- box delle stesse dimensioni + local bIsMirrorOperationSameDimension = abs( b3Operation:getDimX() - b3OperationMirror:getDimX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and + abs( b3Operation:getDimY() - b3OperationMirror:getDimY()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and + abs( b3Operation:getDimZ() - b3OperationMirror:getDimZ()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) + -- box allineati in X + local bIsMirrorBoxXAligned = abs( b3Operation:getCenter():getX() - b3OperationMirror:getCenter():getX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) and + abs( b3Operation:getCenter():getX() - b3OperationMirror:getCenter():getX()) < ( WD.DOUBLE_HEAD_POCKET_TOLERANCE or 0.5) + -- box che non si intersecano + local bIsNotMirrorBoxOverlapping = not OverlapsXY( b3Operation, b3OperationMirror) + -- distanza minima tra le feature + local dTipToPivotProjectionOnY = dTipToPivot * vtTool:getY() + local dTipToPivotProjectionOnYDouble = dTipToPivotDouble * vtToolMirror:getY() + local dYMinDistance = max( b3Operation:getMin():getY(), b3OperationMirror:getMin():getY()) - min( b3Operation:getMax():getY(), b3OperationMirror:getMax():getY()) + local bIsMirrorOperationDistanceOk = dYMinDistance > dMinimumDistanceMirroredOperations + dTipToPivotProjectionOnY - dTipToPivotProjectionOnYDouble + 10 * GEO.EPS_SMALL + -- vettori utensile e somma normali facce specchiati + local vtToolMirrored = Vector3d( vtTool) + vtToolMirrored:mirror( Y_AX()) + local bIsMirrorVectorOk = false + if AreSameVectorApprox( vtToolMirrored, vtToolMirror) then + if AreSameVectorApprox(vtTool, vtToolMirror) then + if vtNormSum and vtNormSumMirror then + local vtNormSumMirrored = Vector3d( vtNormSum) + vtNormSumMirrored:mirror( Y_AX()) + bIsMirrorVectorOk = AreSameVectorApprox( vtNormSumMirrored, vtNormSumMirror) + end + else + bIsMirrorVectorOk = true + end + end + -- se condizioni corrette, scrivo le note e cancello la specchiata + if bIsOriginalMirrorToolSameSize and bIsMirrorMachiningOk and bIsMirrorSideOk and bIsMirrorOperationSameDimension and bIsMirrorBoxXAligned and bIsNotMirrorBoxOverlapping and bIsMirrorOperationDistanceOk and bIsMirrorVectorOk then + -- calcolo asse di specchiatura + local dYMirrorAx + local b3Tab = EgtGetTableArea() + local ptOnMirrorAx = ( b3Operation:getCenter() + b3OperationMirror:getCenter()) / 2 + dYMirrorAx = ptOnMirrorAx:getY() - b3Tab:getMin():getY() + EgtSetCurrMachining( nOperIdMaster) + -- leggo note esistenti + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) + -- aggiungo note per doppio + sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', 2) + sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', dYMirrorAx) + -- scrivo le note della lavorazione + EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) + -- cancello l'operazione specchiata + EgtRemoveOperation( nOperIdMirror) + -- rimuovo dalla lista le fresature già assegnate + local nCurrentMirrorMillingOldId = nCurrentMirrorMilling + table.remove( vMillings, nCurrentMilling) + -- avendo rimosso un elemento dall'array, potrebbe essere cambiato l'elemento nCurrentMirrorPocket + if nCurrentMirrorMilling > #vMillings or ( vMillings[nCurrentMirrorMilling] ~= nCurrentMirrorMillingOldId) then nCurrentMirrorMilling = nCurrentMirrorMilling - 1 end + table.remove( vMillings, nCurrentMirrorMilling) + nCurrentMilling = 0 + break + end + nCurrentMirrorMilling = nCurrentMirrorMilling + 1 + end + end + nCurrentMilling = nCurrentMilling + 1 + end +end + ------------------------------------------------------------------------------------------------------------- function WallExec.ProcessFeatures() -- errori e stato @@ -650,6 +1084,8 @@ function WallExec.ProcessFeatures() local vPartProc = WallExec.CollectFeatures( vPart[i].Id, b3Raw) vProc = EgtJoinTables( vProc, vPartProc) end + -- classifico topologicamente le feature + ClassifyTopology( vProc) -- classifico le feature ClassifyFeatures( vProc, b3Raw) -- recupero l'elenco delle aree vietate alle chiodature @@ -659,6 +1095,9 @@ function WallExec.ProcessFeatures() if #vNLO == 0 and WD.FindFeaturesInDouble then WD.FindFeaturesInDouble( vProc, b3Raw) end + + SetMirroredFeatures( vProc, b3Raw) + -- debug if EgtGetDebugLevel() >= 1 then PrintFeatures( vProc) @@ -678,12 +1117,59 @@ function WallExec.ProcessFeatures() else table.insert( Stats, {Err=0, Msg='', Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId}) end - elseif not Proc.Double and not Proc.LockOut then + elseif not Proc.Double and not Proc.LockOut then local sMsg = 'Feature not machinable by orientation' table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId}) end end EgtOutLog( ' *** End AddMachinings ***', 1) + + -- setto quali sono le lavorazioni da disattivare perchè specchiate di lavorazioni in doppio + local vProcToDisable = {} + for i = 1, #vProc do + local Proc = vProc[i] + if Proc.Double and Proc.Double > 0 then + for j = 1, #vProc do + local ProcMirror = vProc[j] + if Proc.Mirror.Id == ProcMirror.Id then + -- per i fori l'operazione si basa sulla geometria ausiliaria + if Proc.TopologyLongName == 'DRILLING' then + local AuxId = EgtGetInfo( ProcMirror.Id, 'AUXID', 'i') or 0 + if AuxId then AuxId = AuxId + ProcMirror.Id end + table.insert( vProcToDisable, AuxId) + -- per tutte le altre lavorazioni si usa la geometria della feature + else + table.insert( vProcToDisable, ProcMirror.Id) + end + end + end + end + end + + -- cancello le operazioni legate a lavorazioni specchiate + local nOperId = EgtGetNextOperation( EgtGetPhaseDisposition( 1)) + while nOperId do + EgtSetCurrMachining( nOperId) + local nOperationProcIds = EgtGetMachiningGeometry() + local nCurrentOperId = nOperId + if #nOperationProcIds > 0 then + local nOperationProcId = nOperationProcIds[1][1] + for i = 1, #vProcToDisable do + local ProcId = vProcToDisable[i] + if nOperationProcId == ProcId then + nOperId = EgtGetNextOperation( nOperId) + EgtRemoveOperation( nCurrentOperId) + break + end + end + end + if nCurrentOperId == nOperId then + nOperId = EgtGetNextOperation( nOperId) + end + end + + SetMirroredOperations() + -- se macchina pareti if not WD.BEAM_MACHINE then -- riordino le lavorazioni tra tutti i pezzi @@ -695,7 +1181,7 @@ function WallExec.ProcessFeatures() local nGetPriorityFromBtl = WD.BTL_PRIORITY or 0 if nGetPriorityFromBtl > 0 then local vPriority = {} - local nOperId = EgtGetNextOperation( PrevMch) + nOperId = EgtGetNextOperation( PrevMch) local nCurrentPriorityId = 1 while nOperId do local nPriority = EgtGetInfo( nOperId or GDB_ID.NULL, 'PRIORITY', 'i') diff --git a/LuaLibs/WallLib.lua b/LuaLibs/WallLib.lua index 5d054ea..485adaa 100644 --- a/LuaLibs/WallLib.lua +++ b/LuaLibs/WallLib.lua @@ -1,5 +1,7 @@ -- WallLib.lua by Egaltech s.r.l. 2023/10/16 -- Libreria globale per Pareti +-- 2023/06/26 Spostata qui Is3EdgesApprox da FreeContour. Ora cerca autonomamente il gruppo se non viene passato. +-- 2023/11/14 Aggiunte funzioni GetProcessAffectedFaces, GetProcessDistanceToNearestParts, GetProcessDistanceToRawPart. -- Tabella per definizione modulo local WallLib = {} @@ -316,6 +318,213 @@ function WallLib.GetNearestOrthoOpposite( vtRef, vtNorm) return nil end +--------------------------------------------------------------------- +function WallLib.TestElleShape3( nIdGeom, nNumFacet) + -- valida solo nel caso di tre facce + if nNumFacet ~= 3 then return false end + -- determino se L con una faccia terminale o U con tre facce + local bIsL = true + for i = 1, 3 do + local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1] + -- le conto + local nCount = 0 + for j = 1, #vFacAdj do + if vFacAdj[j] >= 0 then + nCount = nCount + 1 + end + end + if nCount == 1 then + bIsL = false + break + end + end + return bIsL +end + +--------------------------------------------------------------------- +function WallLib.TestElleShape4( nIdGeom, nNumFacet) + -- valida solo nel caso di quattro facce + if nNumFacet ~= 4 then return false end + -- determino se L con due facce terminali o O + local nFac3Adj = 0 + local dMinArea3 = GEO.INFINITO * GEO.INFINITO + local dMaxArea2 = 0 + for i = 1, 4 do + local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1] + -- le conto + local nCount = 0 + for j = 1, #vFacAdj do + if vFacAdj[j] >= 0 then + nCount = nCount + 1 + end + end + local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nIdGeom, i - 1, GDB_ID.ROOT) + local dArea = dH * dV + if nCount == 2 then + dMaxArea2 = max( dMaxArea2, dArea) + elseif nCount == 3 then + dMinArea3 = min( dMinArea3, dArea) + nFac3Adj = nFac3Adj + 1 + end + end + if nFac3Adj ~= 2 then return false end + -- verifico se L profonda oppure lunga + if dMinArea3 < dMaxArea2 then + return 1 + else + return 2 + end +end + +--------------------------------------------------------------------- +-- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce +function WallLib.Is3EdgesApprox( Proc, nFacet, nAddGrpId) + nAddGrpId = nAddGrpId or WallLib.GetAddGroup( Proc.PartId) + -- recupero il contorno della faccia + local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.Id, nFacet, nAddGrpId) + if not nContourId then return false end + EgtMergeCurvesInCurveCompo( nContourId) + -- recupero il numero di lati del contorno + local _, nEntityCount = EgtCurveDomain( nContourId) + if not nEntityCount then return false end + -- se sono già tre, ho finito + if nEntityCount == 3 then return true end + -- rimuovo i lati molto corti dal conteggio totale + local nEdges = nEntityCount + for i = 1, nEntityCount do + local dLength = EgtCurveCompoLength( nContourId, i - 1) + if dLength < 15 then nEdges = nEdges - 1 end + end + -- verifico il numero significativo di lati + local bResult = ( nEdges == 3) + -- cancello tutti i contorni appena creati + EgtErase( EgtTableFill( nContourId, nContourCnt)) + if bResult then + EgtOutLog( 'FreeContour : Face with ' .. tostring( nEntityCount) .. ' edges skipped (approx 3 edges)') + end + return bResult +end + +------------------------------------------------------------------------------------------------------------- +-- restituisce le facce della parte interessate dalla feature Proc +function WallLib.GetProcessAffectedFaces( Proc) + local nBoxSolidId = EgtGetFirstNameInGroup( Proc.PartId or GDB_ID.NULL, 'Box') + local b3Part = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD) + local vtFacesAffected = { Top = false, Bottom = false, Front = false, Back = false, Left = false, Right = false} + if Proc.Box and not Proc.Box:isEmpty() then + if Proc.Box:getMax():getZ() > b3Part:getMax():getZ() - 500 * GEO.EPS_SMALL then + vtFacesAffected.Top = true + end + if Proc.Box:getMin():getZ() < b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then + vtFacesAffected.Bottom = true + end + if Proc.Box:getMin():getY() < b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then + vtFacesAffected.Front = true + end + if Proc.Box:getMax():getY() > b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then + vtFacesAffected.Back = true + end + if Proc.Box:getMin():getX() < b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then + vtFacesAffected.Left = true + end + if Proc.Box:getMax():getX() > b3Part:getMax():getX() - 500 * GEO.EPS_SMALL then + vtFacesAffected.Right = true + end + end + + return vtFacesAffected +end + +------------------------------------------------------------------------------------------------------------- +-- restituisce le distanze XY tra la feature Proc e le altre parti più vicine, secondo le direzioni Y-/Y+/X-/X+ +function WallLib.GetProcessDistanceToNearestParts( Proc) + local b3Proc = Proc.Box + local ptMinProc = b3Proc:getMin() + local ptMaxProc = b3Proc:getMax() + local vtDistances = { Front = 0, Back = 0, Left = 0, Right = 0} + if Proc.AffectedFaces.Front then + vtDistances.Front = GEO.INFINITO + end + if Proc.AffectedFaces.Back then + vtDistances.Back = GEO.INFINITO + end + if Proc.AffectedFaces.Left then + vtDistances.Left = GEO.INFINITO + end + if Proc.AffectedFaces.Right then + vtDistances.Right = GEO.INFINITO + end + local nRawId = EgtGetFirstRawPart() + local nPartId = EgtGetFirstPartInRawPart( nRawId) + while nPartId do + if Proc.PartId ~= nPartId then + local nBoxSolidId = EgtGetFirstNameInGroup( nPartId, 'Box') + local b3Solid = EgtGetBBoxGlob( nBoxSolidId or GDB_ID.NULL, GDB_BB.STANDARD) + b3Solid:expand( - 10 * GEO.EPS_SMALL) + local ptMinPart = b3Solid:getMin() + local ptMaxPart = b3Solid:getMax() + if Proc.AffectedFaces.Front then + if OverlapsXY( b3Proc, b3Solid) then + vtDistances.Front = 0 + elseif OverlapsX( b3Proc, b3Solid) then + if ptMaxPart:getY() < ptMinProc:getY() + 100 * GEO.EPS_SMALL then + vtDistances.Front = min( vtDistances.Front, max( 0, ptMinProc:getY() - ptMaxPart:getY())) + end + end + end + if Proc.AffectedFaces.Back then + if OverlapsXY( b3Proc, b3Solid) then + vtDistances.Back = 0 + elseif OverlapsX( b3Proc, b3Solid) then + if ptMaxProc:getY() < ptMinPart:getY() + 100 * GEO.EPS_SMALL then + vtDistances.Back = min( vtDistances.Back, max( 0, ptMinPart:getY() - ptMaxProc:getY())) + end + end + end + if Proc.AffectedFaces.Left then + if OverlapsXY( b3Proc, b3Solid) then + vtDistances.Left = 0 + elseif OverlapsY( b3Proc, b3Solid) then + if ptMaxPart:getX() < ptMinProc:getX() + 100 * GEO.EPS_SMALL then + vtDistances.Left = min( vtDistances.Left, max( 0, ptMinProc:getX() - ptMaxPart:getX())) + end + end + end + if Proc.AffectedFaces.Right then + if OverlapsXY( b3Proc, b3Solid) then + vtDistances.Right = 0 + elseif OverlapsY( b3Proc, b3Solid) then + if ptMaxProc:getX() < ptMinPart:getX() + 100 * GEO.EPS_SMALL then + vtDistances.Right = min( vtDistances.Right, max( 0, ptMinPart:getX() - ptMaxProc:getX())) + end + end + end + end + nPartId = EgtGetNextPartInRawPart( nPartId) + end + + return vtDistances +end + +------------------------------------------------------------------------------------------------------------- +-- restituisce le distanze XY tra la feature Proc e il termine del grezzo, secondo le direzioni Y-/Y+/X-/X+ +function WallLib.GetProcessDistanceToRawPart( Proc, b3Raw) + local b3Proc = Proc.Box + local ptMinProc = b3Proc:getMin() + local ptMaxProc = b3Proc:getMax() + local ptMinRaw = b3Raw:getMin() + local ptMaxRaw = b3Raw:getMax() + local vtDistances = { Front = GEO.INFINITO, Back = GEO.INFINITO, Left = GEO.INFINITO, Right = GEO.INFINITO} + if EnclosesXY( b3Raw, b3Proc) then + vtDistances.Front = max( 0, ptMinProc:getY() - ptMinRaw:getY()) + vtDistances.Back = max( 0, ptMaxRaw:getY() - ptMaxProc:getY()) + vtDistances.Left = max( 0, ptMinProc:getX() - ptMinRaw:getX()) + vtDistances.Right = max( 0, ptMaxRaw:getX() - ptMaxProc:getX()) + end + + return vtDistances +end + ------------------------------------------------------------------------------------------------------------- function WallLib.GetNailLockOutAreas( vProc) local vNLO = {} diff --git a/UpdateLog.txt b/UpdateLog.txt index 35b4bd6..aa988f9 100644 --- a/UpdateLog.txt +++ b/UpdateLog.txt @@ -1,5 +1,9 @@ ==== Wall Update Log ==== +Versione 2.5k1 (14/11/2023) +- Added : aggiunte lavorazioni in doppio. +- Modif : miglioramenti vari alla lavorazione tasche, in particolare in presenza di pezzi vicini. + Versione 2.5j3 (23/10/2023) - Added : aggiunta gestione aree vietate per chiodature (LockOut for Nail) - Modif : in FreeContour conversione automatica di facce non fattibili con lama per limiti di orientamento in facce da fare con fresa. diff --git a/Version.lua b/Version.lua index 952613c..96fd52b 100644 --- a/Version.lua +++ b/Version.lua @@ -2,5 +2,5 @@ -- Gestione della versione di Wall NAME = 'Wall' -VERSION = '2.5j3' +VERSION = '2.5k1' MIN_EXE = '2.5b3' diff --git a/bin/Images/.placeholder b/bin/Images/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/bin/LuaLibs/.placeholder b/bin/LuaLibs/.placeholder deleted file mode 100644 index e69de29..0000000