-- ProcessLapJoint.lua by Egaltech s.r.l. 2021/12/01 -- Gestione calcolo mezzo-legno per Travi -- 2019/10/08 Agg. gestione OpenPocket. -- 2021/01/24 Con sega a catena ora sempre impostato asse A. -- 2021/02/03 Corretto riconoscimento feature di coda. -- 2021/02/04 Razionalizzata gestione forzatura lama. Corretta gestione diametro minimo utensile per svuotatura. -- 2021/03/04 Due facce con testa da sotto. -- 2021/03/20 Piccole correzioni. -- 2021/03/22 Modificata gestione caso due facce lunghe come la trave con trave corta. -- 2021/04/13 Modificata gestione fessura U con sega a catena (corta ora ok, lunga ancora da correggere). -- 2021/04/14 Correzioni ribasso a U con fresa da sotto. -- 2021/04/15 Aggiunta gestione massima lunghezza fresa da sotto su svuotature. -- 2021/04/21 Anche feature lunga con due facce con opzione lama ora si taglia con lama. -- 2021/04/23 Corretto caso con antischeggia non inseriti perchè inutili. -- 2021/04/27 Antischeggia solo se feature trasversali. -- 2021/05/12 Semplificata gestione diametro minimo utensile per svuotatura. -- 2021/06/04 Su U passante con faccia perpendicolare aggiunta si forza Pocket. -- 2021/06/11 Su U passante e profonda se non bastano due svuotature su faccia ortogonale si fa anche la faccia di fondo per quanto possibile. -- 2021/06/21 Nel caso precedente si fa la terza svuotatura anche se è possibile fare una sola delle prime due (altra da sotto). -- 2021/06/21 Gestione ripresa spigoli o contorno con fresa più piccola ( diametro < 3/4 utensile svuotatura) attivata da parametro Q. -- 2021/07/02 Migliorie e correzioni su svuotature e pulitura spigoli. -- 2021/07/15 Aggiunti antischeggia con fresa. -- 2021/09/08 Aggiunta gestione parametro Q04 per i tagli di lama lungo facce lunghe (con o senza facce di chiusura) -- 2021/09/21 Aggiunta lavorazione/opzione "lamello" con le feature 16, 30, 32, 39, -- che si attiva abilitando il check al tipo milling: SideMillAsBlade (SideMillAsBlade_2) -- 2021/09/23 Gestione migliorata lavorazioni BH (blockhaus) su macchina fast BH, -- migliorata applicazione lavorazioni BH su feature lunghe lavorte a passi -- 2021/10/06 Ad antischeggia con lama in presenza di testa da sotto aggiunta preferenza a testa da sopra. -- 2021/10/19 Corretta gestione inversione per Tunnel. OpenPocket anche se spezzato ma 1 o 2 facce. Introdotta lunghezza minima per lamello. -- 2021/10/21 Migliorato controllo affondamento utensile in U lavorato da 3 parti (anche da sotto). -- 2021/10/27 Migliorato calcolo asse tunnel o similare. -- 2021/11/02 In svuotatura con lati aperti diametro fresa non superiore al doppio del lato piccolo. -- 2021/11/15 Quando si usa sega a catena uso Q10 come massima elevazione. -- 2021/11/22 Corretta segnalazione warning su foro di L20 e L25. -- 2021/12/17 Lettura parametri Q solo all'inizio. -- 2022/01/13 Estrapolazione da MakeMoreFaces() di MakeTwoFaces() e MakeThreeFaces(), e varie ottimizzazioni. -- Tabella per definizione modulo local ProcessLapJoint = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Fbs = require( 'FacesBySaw') local Cut = require( 'ProcessCut') local DoubleCut = require( 'ProcessDoubleCut') local LongCut = require( 'ProcessLongCut') local Long2Cut = require( 'ProcessLongDoubleCut') EgtOutLog( ' ProcessLapJoint started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') -- variabili assegnazione parametri Q local Q_FORCE_BLADE = nil -- i local Q_DEPTH_CHAMFER = 0.0 -- d local Q_MAX_ELEVATION = 0.0 -- d local Q_ONLY_CHAMFER = 0 -- i local Q_USE_MILL = 0 -- i local Q_USE_ROUGH_TOOL = 0 -- i local Q_USE_ROUGH_TOOL_B90 = 0 -- i local Q_USE_ROUGH_TOOL_B0 = 0 -- i local Q_BORE_ON_CORNER = 0 -- i local Q_CONTOUR_SMALL_TOOL = 0 -- i local Q_ONLY_CONTOUR = 0 -- i local Q_SIDE_ROUGH_TOOL = 0 -- i local Q_ANTISPLINT_TYPE = 0 -- i local Q_BLADE_ON_ALONG_FACE = 0 -- i -- variabile smussi local _bMadeChamfer local _nChamfer, _dDepthCham, _sErrCham, _bForceUseBlade -- Settaggi interni local _bTrySidePocketAtFirst = true local _nPhase, _nRawId, _nPartId, _dOvmHead local _b3Raw, _b3Solid local _nAddGrpId --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessLapJoint.Identify( Proc) return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 33) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) or ( Proc.Grp == 4 and Proc.Prc == 37) or ( Proc.Grp == 4 and Proc.Prc == 39) or ( Proc.Grp == 4 and Proc.Prc == 120)) end --------------------------------------------------------------------- local function AssignQValues( Proc) -- reset assegnazione parametri Q Q_FORCE_BLADE = nil Q_BLADE_ON_ALONG_FACE = 0 Q_DEPTH_CHAMFER = 0.0 Q_ONLY_CHAMFER = 0 Q_USE_MILL = 0 Q_USE_ROUGH_TOOL = 0 Q_USE_ROUGH_TOOL_B90 = 0 Q_USE_ROUGH_TOOL_B0 = 0 Q_BORE_ON_CORNER = 0 Q_CONTOUR_SMALL_TOOL = 0 Q_ONLY_CONTOUR = 0 Q_SIDE_ROUGH_TOOL = 0 Q_ANTISPLINT_TYPE = 0 Q_MAX_ELEVATION = EgtGetInfo( Proc.Id, 'Q10', 'd') or 0.0 if ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16 then Q_FORCE_BLADE = EgtGetInfo( Proc.Id, 'Q01', 'i') -- can be nil Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q04', 'd') or 0.0 Q_ONLY_CHAMFER = EgtGetInfo( Proc.Id, 'Q05', 'i') or 0 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17 then Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q01', 'd') or 0.0 Q_ONLY_CHAMFER = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20 then Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q01', 'd') or 0.0 Q_USE_MILL = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0 Q_USE_ROUGH_TOOL = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0 Q_USE_ROUGH_TOOL_B90 = EgtGetInfo( Proc.Id, 'Q04', 'i') or 0 Q_USE_ROUGH_TOOL_B0 = EgtGetInfo( Proc.Id, 'Q05', 'i') or 0 Q_BORE_ON_CORNER = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25 then Q_BORE_ON_CORNER = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then Q_CONTOUR_SMALL_TOOL = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0 Q_ONLY_CONTOUR = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0 Q_SIDE_ROUGH_TOOL = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0 Q_BLADE_ON_ALONG_FACE = EgtGetInfo( Proc.Id, 'Q04', 'i') or 0 Q_ANTISPLINT_TYPE = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0 Q_DEPTH_CHAMFER = EgtGetInfo( Proc.Id, 'Q07', 'd') or 0.0 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32 then Q_SIDE_ROUGH_TOOL = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0 Q_CONTOUR_SMALL_TOOL = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0 Q_ANTISPLINT_TYPE = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34 then Q_CONTOUR_SMALL_TOOL = EgtGetInfo( Proc.Id, 'Q01', 'i') or 0 Q_ANTISPLINT_TYPE = EgtGetInfo( Proc.Id, 'Q06', 'i') or 0 end end --------------------------------------------------------------------- local function EvaluateQParam() local sErr -- verifico che lo smusso sia richiesto local nChamfer = 0 if Q_DEPTH_CHAMFER > 0 then nChamfer = 1 end -- verifico se posso fare solo lo smusso if Q_ONLY_CHAMFER == 1 then if Q_DEPTH_CHAMFER > 0 then nChamfer = nChamfer + 1 -- altrimenti se non ho l'affondamento esco else sErr = 'Error : no chamfer depth' EgtOutLog( sErr) return -1, dDepth, sErr end end -- verifico se devo usare lama invece della sega-catena -- 2020-03-20 forzata abilitazione uso lama se parametro Q non è presente -- xxxx-xx-xx tolta la preferenza alla lama in favore della sega-catena per un caso particolare -- 2021-02-15 re-introdotta la preferenza alla lama se non c'è il parametro Q. Rimane da -- implementare un ulteriore parametro per poter scegliere di prediligere la sega-catena o no al fine di continuare -- a cambiare il codice per gestire il caso particolare local bForceUseBlade = false if Q_FORCE_BLADE == nil or Q_FORCE_BLADE == 1 then bForceUseBlade = true end return nChamfer, dDepth, sErr, bForceUseBlade end --------------------------------------------------------------------- local function InitGlob( Proc, nPhase, nRawId, nPartId, dOvmHead) if not Proc then return false, 'Error : Proc is missing' end -- setto a nil la variabile smussi _bMadeChamfer = nil _nPhase = nPhase _nRawId = nRawId _nPartId = nPartId _dOvmHead = dOvmHead if _nRawId then -- recupero l'ingombro del grezzo di appartenenza _b3Raw = EgtGetRawPartBBox( _nRawId) end if not _nPartId then _nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL) end if _nPartId then -- recupero gruppo per geometria addizionale _nAddGrpId = BL.GetAddGroup( _nPartId) -- recupero l'ingombro della trave _b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( _nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) else local sErr = 'Error : part ID not found' EgtOutLog( sErr) return false, sErr end if not _b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end if not _nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- leggo i valori dei parametri Q AssignQValues( Proc) -- verifico se sono presenti i parametri Q per la profondità smusso e -- per eseguire in esclusiva solo lo smusso _nChamfer, _dDepthCham, _sErrCham, _bForceUseBlade = EvaluateQParam() return true, '' end --------------------------------------------------------------------- local function GetToolInfoForMachining( sMachiningName) if EgtMdbSetCurrMachining( sMachiningName) then local toolInfo = { sTuuid = nil, dLength = nil, dDiam = nil, dThDiam = nil, dMaxMat = nil, dMaxDepth = nil, dSideDepth = nil, dCornerRad = nil, dThick = nil } toolInfo.sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( toolInfo.sTuuid) or '') then toolInfo.dLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) toolInfo.dDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) toolInfo.dThDiam = EgtTdbGetCurrToolThDiam() toolInfo.dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) toolInfo.dMaxDepth = EgtTdbGetCurrToolMaxDepth() toolInfo.dSideDepth = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') toolInfo.dCornerRad = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) toolInfo.dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) return toolInfo end end return nil end --------------------------------------------------------------------- local function FormatWarning( sWarn, sWarn2) if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end return sWarn end --------------------------------------------------------------------- -- Restituisce solo gli indici delle facce adiacenti esistenti (no -1) local function GetValidFacetAdjacencies( nSurfId, nFacet) local vValidAdj local vFacAdj = EgtSurfTmFacetAdjacencies( nSurfId, nFacet)[1] if vFacAdj then vValidAdj = {} for j = 1, #vFacAdj do if vFacAdj[j] >= 0 then table.insert(vValidAdj, vFacAdj[j]) end end end return vValidAdj end --------------------------------------------------------------------- local function TestElleShape3( Proc, bNotProc) local nNumFacet local nProcId -- se non passato il Proc vero e proprio if bNotProc then nProcId = Proc nNumFacet = EgtSurfTmFacetCount( nProcId) else nProcId = Proc.Id nNumFacet = Proc.Fct end -- 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 -- conto le facce adiacenti (solo quelle valide) local vFacAdj = GetValidFacetAdjacencies( nProcId, i - 1) if #vFacAdj == 1 then bIsL = false break end end return bIsL end --------------------------------------------------------------------- local function TestElleShape4( Proc) -- valida solo nel caso di quattro facce if Proc.Fct ~= 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 -- conto le facce adiacenti (solo quelle valide) local vFacAdj = GetValidFacetAdjacencies( Proc.Id, i - 1) local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, i - 1, GDB_ID.ROOT) local dArea = dH * dV if #vFacAdj == 2 then dMaxArea2 = max( dMaxArea2, dArea) elseif #vFacAdj == 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 < 2 * dMaxArea2 then return 1 else return 2 end end --------------------------------------------------------------------- --- Test per facce a forma di U o a forma di L local function TestUL( Proc) local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc)) -- verifico se due facce o L con una o due facce di terminazione local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2) return bIsU, bIsL end --------------------------------------------------------------------- local function GetIdIniEndPoints( ptP1, ptP2, tFac) local nIdIniPoint local nIdEndPoint if ptP1 and ptP2 then if dist( ptP1, tFac[4]) < GEO.EPS_SMALL or dist( ptP2, tFac[4]) < GEO.EPS_SMALL then nIdEndPoint = 4 nIdIniPoint = 5 elseif dist( ptP1, tFac[5]) < GEO.EPS_SMALL or dist( ptP2, tFac[5]) < GEO.EPS_SMALL then nIdEndPoint = 5 nIdIniPoint = 4 end end return nIdIniPoint, nIdEndPoint end --------------------------------------------------------------------- local function GetChainSawBlockedAxis( nInd) if BD.GetChainSawBlockedAxis then return BD.GetChainSawBlockedAxis( nInd) else if nInd == 1 then return EgtIf( BD.C_SIMM, 'A=90', 'A=0') else return EgtIf( BD.C_SIMM, 'A=0', 'A=90') end end end --------------------------------------------------------------------- local function GetChainSawInitAngs( vtN, vtO) if BD.GetChainSawInitAngs then return BD.GetChainSawInitAngs( vtN, vtO) else if BD.C_SIMM then if vtN:getY() > 0 then return 'C=180' else return 'C=-180' end else return '' end end end --------------------------------------------------------------------- local function VerifyChainSaw( Proc, dMinDim, dMaxDim) local bUseChainSaw = false local sMchFind = 'Sawing' local sSawing = ML.FindSawing( sMchFind) local dMaxMat = 0 local dSawCornerRad = 0 local dSawThick = 0 local dMaxDepth = 200 -- se non trova una lavorazione di sawing esco if not sSawing then return bUseChainSaw else -- recupero i dati dell'utensile local dToolLength = 0 local dSawWidth = 75 local TI = GetToolInfoForMachining( sSawing) if TI then dToolLength = TI.dLength or dToolLength dMaxMat = TI.dMaxMat or dMaxMat dSawWidth = TI.dDiam or dSawWidth dSawThick = TI.dThick or dSawThick dSawCornerRad = TI.dCornerRad or dSawCornerRad dMaxDepth = TI.dMaxDepth or dMaxDepth if dSawThick < dMinDim + 10 * GEO.EPS_SMALL and dSawWidth < dMaxDim + 10 * GEO.EPS_SMALL then bUseChainSaw = true end end end return bUseChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick, dMaxDepth end --------------------------------------------------------------------- local function VerifyPocket( Proc, dDiam, dDepth, dMaxTotLen, sMchFindMaster) -- tipo di svuotatura local sMchFind = EgtIf( sMchFindMaster and #sMchFindMaster > 0, sMchFindMaster, 'Pocket') -- ricerca della svuotatura local sPocketing if dDepth then sPocketing = ML.FindPocketing( sMchFind, dDiam, dDepth, dMaxTotLen) or ML.FindPocketing( sMchFind, dDiam, 0.8 * dDepth, dMaxTotLen) or ML.FindPocketing( sMchFind, dDiam, 0.6 * dDepth, dMaxTotLen) or ML.FindPocketing( sMchFind, dDiam, 0.4 * dDepth, dMaxTotLen) or ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen) else sPocketing = ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen) end if not sPocketing then return false end -- recupero i dati dell'utensile local bUsePocketing = false local dMaxDepth = 0 local dToolDiam = 0 local TI = GetToolInfoForMachining( sPocketing) if TI then dToolDiam = TI.dDiam or dToolDiam dMaxDepth = TI.dMaxDepth or dMaxDepth bUsePocketing = true end return bUsePocketing, sPocketing, dMaxDepth, dToolDiam end --------------------------------------------------------------------- local function VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill) local bUseBHSideMill = false local bHead = true local bHeadDir = true local sMilling local dThickTool = 0 local dToolDiam = 0 -- 22/09/2021 Su richiesta di Alessandro Sola, si toglie la richiesta di presenza del parametro Q per poter applicare -- la lavorazione su più features( che non hanno questo parametro Q), quindi questa lavorazione viene verificata se è abilitato il parametro utensile -- che ovviamente tramite la lavorazione è abbinata alla lista lavorazioni con BHSideMill. -- Al fine di mantenere il funzionamento precedente (purtroppo non sono stati descritti i motivi del confrontare il parametro Q) -- si elude il controllo del Q solo se la variabile del Beamdata BD.BH_MACHINE segnala che non è una macchina tipo BH (ha la fresa blockhaus al posto della lama) -- se non feature BlockHausHalfLap o non abilitato parametro Q per lavorarlo di fianco esco if Proc.Prc ~= 37 and Q_SIDE_ROUGH_TOOL == 0 and not BD.BH_MACHINE then return false end -- verifico se U o L local bIsU, bIsL = TestUL( Proc) -- verifico se la funzione è lanciata da IsTailFeature o Classify if bSinglePart == nil then -- se lunghezza non richiede spezzatura setto la variabile bSinglePart per non fare con fresa BH -- perchè deve avere almeno 2 facce if not( ( Proc.Box:getDimX() > BD.LONGCUT_MAXLEN) or ( Proc.Box:getDimX() > 0.8 * _b3Solid:getDimX() and Proc.Box:getDimX() > BD.LONGCUT_ENDLEN)) then bSinglePart = true end end -- ad oggi 22/09/2021 la lavorazione BH non va bene se le facce di chiusura non sono perpendicolari a X, quindi -- se non sono perpendicolari non si applica la lavorazione BH if bIsU or bIsL then local bExit = false for i = 1, Proc.Fct do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT) if abs( vtN:getX()) > 0.001 and abs( vtN:getX()) < 0.999962 then bExit = true break end end if bExit then return false end end -- se forma a U o L verifico che -- se U e lunghezza non richiede spezzatura if ( bIsU or bIsL or ( Proc.Fct == 1 and not bSinglePart) ) and Proc.Box:getDimX() <= BD.LONGCUT_MAXLEN then -- se faccia singola di un passo multiplo e risultato precedente non applicato, riporto il risultato del passo precedente if ( bIsU or bIsL or ( Proc.Fct == 1 and not bSinglePart) ) and bPrevBhSideMill ~= nil and not bPrevBhSideMill then return false end -- recupero la lavorazione sMilling = ML.FindMilling( 'BHSideMill') if sMilling then -- recupero i dati dell'utensile local dToolLength = 0 local dMaxDepth = 0 local TI = GetToolInfoForMachining( sMilling) if TI then dToolLength = TI.dLength or dToolLength dToolDiam = TI.dDiam or dToolDiam dMaxDepth = TI.dMaxDepth or dMaxDepth dThickTool = TI.dThick or dThickTool end -- verifico se la feature è abbastanza vicino a testa/coda da permettere la lavorazione con questo utensile if _b3Solid then local dMinXF = Proc.Box:getMin():getX() local dMaxXF = Proc.Box:getMax():getX() local dMinT = _b3Solid:getMin():getX() local dMaxT = _b3Solid:getMax():getX() -- determino se è più vicino alla testa o al bordo (con offset per evitare problemi a metà) bHeadDir = ( dMaxT - dMinXF) < ( dMaxXF - dMinT) + 50 bHead = bHeadDir -- determino se è compatibile con il massimo affondamento dell'utensile -- nota F.M il 22/09/2021: non sarebbe meglio utilizzare lo spessore lama invece della massima lavorazione? -- questo perchè Alessandro ha settato il parametro Max Material a 80 con spessore lama 42 -- se invece il Max material viene usato per definire fino a che affondamento (lungo l'asse utensile) -- può arrivare prima di collidere con la testa allora si può utilizzare il dMaxDepth bUseBHSideMill = EgtIf( bHead, ( dMaxT - dMinXF), ( dMaxXF - dMinT)) < dMaxDepth -- se diametro maggiore della testa if BD.HEAD_DIM_FOR_BH and dToolDiam > BD.HEAD_DIM_FOR_BH then bHead = true bUseBHSideMill = true end end end end return bUseBHSideMill, bHead, bHeadDir, dThickTool, dToolDiam end --------------------------------------------------------------------- local function GetTunnelDimension( Proc) -- sono necessarie almeno due facce if Proc.Fct < 2 then return 0, 0, 0 end -- recupero centro e normale delle facce local ptC = {} local vtN = {} for i = 1, Proc.Fct do ptC[i], vtN[i] = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT) end -- calcolo l'orientamento del tunnel local vtOrtho local bAdj = EgtSurfTmFacetsContact( Proc.Id, 0, 1) if bAdj then vtOrtho = vtN[1] ^ vtN[2] else if Proc.Fct >= 3 then vtOrtho = vtN[1] ^ vtN[3] else return 0, 0, 0 end end -- ottengo il boundingBox e prendo le dimensioni lungo la direzione (Z locale) che rappresenta la profondità della fessura local frFc = Frame3d( ptC[1], vtOrtho) local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) local dDepth = b3BoxLoc:getDimZ() -- centro del bounding box locale local ptCen = b3BoxLoc:getCenter() ptCen:toGlob( frFc) -- creo superficie intermedia local nSurfInt = EgtSurfTmPlaneInBBox( _nAddGrpId, ptCen, vtOrtho, _b3Solid, GDB_ID.ROOT) if not nSurfInt then return 0, 0, 0 end -- ritaglio la superficie con le facce della fessura for i = 1, Proc.Fct do EgtCutSurfTmPlane( nSurfInt, ptC[i], -vtN[i], false, GDB_ID.ROOT) end local frSurfInt, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) -- cerco la faccia con larghezza pari a dimensione massima della fessura local nLongIdFace = 0 for i = 1, Proc.Fct do if abs( vtN[i] * frSurfInt:getVersX()) < 0.5 then nLongIdFace = i - 1 break end end return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt end --------------------------------------------------------------------- local function GetFaceAdj( Proc, nFacInd, dH, dV) -- Recupero le facce adiacenti alla principale (solo quelle esistenti) local vAdj = GetValidFacetAdjacencies( Proc.Id, nFacInd) if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' return -1, sErr end EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 4) -- Riordino le dimensioni per avere dH > dV if dH < dV then dH, dV = dV, dH end -- Cerco una faccia adiacente alla principale sul lato lungo local nFacAdj for i = 1, #vAdj do local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) local dLen = dist( ptP1, ptP2) if dLen > 0.5 * dH then nFacAdj = vAdj[i] EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 4) break end end if not nFacAdj then local sErr = 'Error : main face without long adjacent face' return -1, sErr end return nFacAdj end --------------------------------------------------------------------- local function CalcCollisionSafety( vtDir) local dCollSic = 10 * BD.COLL_SIC if abs( vtDir:getX()) > 0.999 or abs( vtDir:getY()) > 0.999 or abs( vtDir:getZ()) > 0.999 then dCollSic = 0 elseif abs( vtDir:getX()) > 0.996 or abs( vtDir:getY()) > 0.996 or abs( vtDir:getZ()) > 0.996 then dCollSic = 1 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.89 or abs( vtDir:getY()) > 0.89 or abs( vtDir:getZ()) > 0.89 then dCollSic = 2.5 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.866 or abs( vtDir:getY()) > 0.866 or abs( vtDir:getZ()) > 0.866 then dCollSic = 4 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.707 or abs( vtDir:getY()) > 0.707 or abs( vtDir:getZ()) > 0.707 then dCollSic = 5.5 * BD.COLL_SIC end return dCollSic end --------------------------------------------------------------------- -- Verifica se feature di testa function ProcessLapJoint.IsHeadFeature( Proc, b3Raw, dCurrOvmH) if not InitGlob( Proc) then return false end -- se una sola faccia if Proc.Fct == 1 then local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) if vtN0:getX() > 0.1 then return true end end -- verifico se è in testa if Proc.Box:getMax():getX() < b3Raw:getMax():getX() - dCurrOvmH - BD.MAX_DIST_HTFEA then return false end -- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 * b3Raw:getDimX()) then return false end -- se una o due facce e interessa veramente la testa, allora di testa if Proc.Fct <= 2 then if Proc.Box:getMax():getX() > _b3Solid:getMax():getX() - 1. then return true elseif Proc.Box:getMax():getX() < _b3Solid:getMax():getX() - 5. then return false end end -- deve avere la normale principale diretta verso la testa local nFacInd, _ = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) if vtN and vtN:getX() < 0.499 then return false elseif Proc.Fct >= 5 then return true end -- deve occupare la maggior parte dell'area if Proc.Box:getDimY() > 0.75 * b3Raw:getDimY() or Proc.Box:getDimZ() > 0.75 * b3Raw:getDimZ() then return true end -- non è di testa return false end --------------------------------------------------------------------- -- Verifica se feature di coda function ProcessLapJoint.IsTailFeature( Proc, b3Raw) if not InitGlob( Proc) then return false end -- se una sola faccia if Proc.Fct == 1 then local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) if vtN0:getX() < -0.1 then return true end end -- se può essere fatto con utensile tipo lama local bUseBHSideMill, bHead, bHeadDir = VerifyBHSideMill( Proc) if bUseBHSideMill then Proc.HeadDir = bHeadDir return not bHead end -- verifico se è in coda local dEndDist = Proc.Box:getMin():getX() - _b3Solid:getMin():getX() if dEndDist > BD.MAX_DIST_HTFEA then return false end -- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 * b3Raw:getDimX()) then return false end -- se una o due facce e interessa veramente la coda, allora di coda if Proc.Fct <= 2 then if Proc.Box:getMin():getX() < _b3Solid:getMin():getX() + 1. then return true elseif Proc.Box:getMin():getX() > _b3Solid:getMin():getX() + 5. then return false end end -- deve avere la normale principale diretta verso la coda (oppure tunnel) local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) if vtN and vtN:getZ() < BD.NZ_MINA and nFacInd2 then _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) dElev = dElev2 end if not vtN or vtN:getX() > -0.001 or dEndDist + vtN:getX() * dElev > 0 then return false else return true end end --------------------------------------------------------------------- -- Classificazione della feature function ProcessLapJoint.Classify( Proc, b3Raw) if not InitGlob( Proc) then return false end -- se 1 faccia if Proc.Fct == 1 then -- dati della faccia --local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- verifico se è lavorabile solo dal basso --local bDown = ( vtN:getZ() < BD.NZ_MINA) --return true, bDown return true, false -- se 2 facce elseif Proc.Fct == 2 then -- dati delle facce local vtN = {} _, vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) _, vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- verifico se è lavorabile solo dal basso local bSmall = ( ( Proc.Head or Proc.Tail) and Proc.Box:getDimX() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ())) or ( not ( Proc.Head or Proc.Tail) and Proc.Box:getDimY() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ())) local bDown = ( vtN[1]:getZ() < BD.NZ_MINB and vtN[2]:getZ() < BD.NZ_MINB) or ( vtN[1]:getZ() < BD.NZ_MINA and ( vtN[2]:getZ() < -0.1 or not bSmall)) or ( vtN[2]:getZ() < BD.NZ_MINA and ( vtN[1]:getZ() < -0.1 or not bSmall)) bDown = ( bDown and not BD.DOWN_HEAD) return true, bDown -- se più di 2 facce else local bClosedOrthoFaces local nDeletedFace -- recupero la faccia con il maggior numero di adiacenze e minor elevazione local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 else return false end end -- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura for i = 1, Proc.Fct do local nNewProc = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL -- elimino una faccia nDeletedFace = i - 1 if EgtSurfTmRemoveFacet( nNewProc, nDeletedFace) then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( nNewProc, _nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 EgtErase( nNewProc) break else EgtErase( nNewProc) return false end end -- altrimenti esco else EgtErase( nNewProc) break end end -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo if bClosedOrthoFaces then nFacInd = nDeletedFace -- rendo nulla la faccia opzionale perchè si tratta di una fessura nFacInd2 = nil dElev = BL.GetFaceElevation( Proc.Id, nFacInd) bClosedOrthoFaces = false -- non lo setto come tunnel end end -- se facce formano un tunnel e sono ortogonali if bClosedOrthoFaces then -- ottengo le dimensioni del tunnel local dDimMin, dDimMax, _, _, _, nSurfInt = GetTunnelDimension( Proc) EgtErase( nSurfInt) -- verifico se può essere fatto con svuotatura if VerifyPocket( Proc, dDimMin) then return true, false elseif VerifyChainSaw( Proc, dDimMin, dDimMax) then return true, false else return false end else local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- se può essere fatto con utensile tipo lama local bUseBHSideMill, _, _, dMaxMat = VerifyBHSideMill( Proc) -- if bUseBHSideMill and ( dMaxMat <= dV + 15 * GEO.EPS_SMALL) then if bUseBHSideMill and ( dMaxMat <= dH + 15 * GEO.EPS_SMALL) then return true, false -- altrimenti controllo se deve essere ruotato con le altre lavorazioni else -- dati della faccia local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) -- cerco se c'è faccia adiacente sul lato più lungo local nFaceAdj = GetFaceAdj( Proc, nFacInd, dH, dV) or -1 local _, bIsL = TestUL( Proc) -- verifico se è lavorabile solo dal basso local bDown = ( vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD) -- se verso il basso, verifico se utilizzabile seconda faccia if bDown then if nFacInd2 and dElev2 < 2 * dElev then local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) elseif not nFacInd2 and bIsL and nFaceAdj >= 0 then local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFaceAdj, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) end -- verifico se la faccia principale è sottosquadra, ha forma L ed esiste la faccia adiacente elseif vtN:getZ() < -0.2589 and bIsL and nFaceAdj >= 0 then -- se il numero di facce > 2 o il box della feature supera una certa distanza dalle teste allora controllo la z della faccia ausiliaria if Proc.Fct > 2 or ( Proc.Box:getMax():getX() < _b3Solid:getMin():getX() - 150) or ( Proc.Box:getMin():getX() > _b3Solid:getMax():getX() + 150) then local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFaceAdj, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) end end return true, bDown end end end end --------------------------------------------------------------------- -- Lavorazione con fresa --------------------------------------------------------------------- local function MakeOneFaceByMill( Proc) -- verifico il numero di facce della tacca assert( ( Proc.Fct == 1), 'Error : MakeOneFaceByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces') -- dati della faccia local _, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- verifico se orientata verso l'alto local bUp = ( vtN:getZ() >= BD.NZ_MINA) -- scelta faccia da lavorare local nFacInd = 0 -- recupero la lavorazione local sMilling = ML.FindMilling( 'BirdsMouth') if not sMilling then local sErr = 'Error : BirdsMouth not found in library' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso faccia e lato correzione if vtN:getX() > 0 then EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_LEFT, MCH_MILL_FU.PARAL_LEFT)) else EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_RIGHT, MCH_MILL_FU.PARAL_RIGHT)) end -- imposto lato di correzione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) if not bUp then EgtSetMachiningParam( MCH_MP.INVERT, true) end -- imposto posizione braccio porta testa if vtN:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- dichiaro non si generano sfridi per VMill EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- eventuale segnalazione ingombro di testa o coda local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * _b3Raw:getDimZ()) if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < _b3Raw:getMin():getZ() + dMinHIng then if Proc.Head then local dOffs = _b3Solid:getMax():getX() - Proc.Box:getMin():getX() BL.UpdateHCING( _nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - _b3Solid:getMin():getX() BL.UpdateTCING( _nRawId, dOffs) end end return true end --------------------------------------------------------------------- local function DoMill( Proc, sMilling, offset, nFacInd, nFac2Ind, vtN) -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso faccia e lato correzione local nFaceUse = BL.GetNearestOrthoOpposite( vtN[nFac2Ind + 1]) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto lato di correzione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- tolgo l'inversione EgtSetMachiningParam( MCH_MP.INVERT, false) -- aggiungo offset laterale if offset then EgtSetMachiningParam( MCH_MP.OFFSR, offset) end -- imposto posizione braccio porta testa if vtN[nFacInd + 1]:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- dichiaro non si generano sfridi per VMill EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end return true end --------------------------------------------------------------------- local function MakeTwoFacesByMill( Proc, bDownHead) -- verifico il numero di facce della tacca assert( ( Proc.Fct == 2), 'Error : MakeTwoFacesByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces') -- recupero la lavorazione local sMilling if Q_USE_MILL and Q_USE_MILL == 1 then sMilling = ML.FindMilling( 'LongSmallCut' .. EgtIf( bDownHead, '_H2', '')) else sMilling = ML.FindMilling( 'BirdsMouth' .. EgtIf( bDownHead, '_H2', '')) end if not sMilling then local sErr = 'Error : LongSmallCut & BirdsMouth not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dTDiam = 0 local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam end -- dati delle facce local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- dati medi local ptM = ( ptC[1] + ptC[2]) / 2 -- verifico non siano orientate verso il basso local bFaceOk = {} bFaceOk[1] = ( vtN[1]:getZ() >= BD.NZ_MINB) bFaceOk[2] = ( vtN[2]:getZ() >= BD.NZ_MINB) if not bDownHead and not bFaceOk[1] and not bFaceOk[2] then local sErr = 'Error : LapJoint from bottom impossible' EgtOutLog( sErr) return false, sErr end -- scelta faccia da lavorare local nFacInd -- se entrambe possibili if bFaceOk[1] and bFaceOk[2] then -- se in testa, scelgo quella orientata verso la testa if Proc.Head then if vtN[1]:getX() > vtN[2]:getX() then nFacInd = 0 else nFacInd = 1 end -- se altrimenti in coda, scelgo quella orientata verso la coda elseif Proc.Tail then if vtN[1]:getX() < vtN[2]:getX() then nFacInd = 0 else nFacInd = 1 end -- altrimenti, scelgo quella con la normale più perpendicolare all'asse trave (se uguali, quella verso X+) else if abs( abs( vtN[1]:getX()) - abs( vtN[2]:getX())) < GEO.EPS_SMALL then if ptM:getX() > _b3Raw:getCenter():getX() then nFacInd = EgtIf( vtN[1]:getX() > vtN[2]:getX(), 0, 1) else nFacInd = EgtIf( vtN[1]:getX() < vtN[2]:getX(), 0, 1) end else nFacInd = EgtIf( abs( vtN[1]:getX()) < abs( vtN[2]:getX()), 0, 1) end end elseif bFaceOk[1] then nFacInd = 0 else nFacInd = 1 end local nOthInd = 1 - nFacInd local bOk, sErr -- se forzato uso fresa controllo se posso fare in una o più passate if Q_USE_MILL and Q_USE_MILL == 1 then bOk, sErr = DoMill( Proc, sMilling, dTDiam / 2, nFacInd, nOthInd, vtN) if not bOk then return bOk, sErr end end bOk, sErr = DoMill( Proc, sMilling, 0, nFacInd, nOthInd, vtN) if not bOk then return bOk, sErr end -- eventuale segnalazione ingombro di testa o coda local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * _b3Raw:getDimZ()) if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < _b3Raw:getMin():getZ() + dMinHIng then if Proc.Head then local dOffs = _b3Solid:getMax():getX() - Proc.Box:getMin():getX() BL.UpdateHCING( _nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - _b3Solid:getMin():getX() BL.UpdateTCING( _nRawId, dOffs) elseif Proc.Box:getCenter():getX() > _b3Solid:getCenter():getX() then local dOffs = _b3Solid:getMax():getX() - Proc.Box:getMin():getX() local dDist = _b3Solid:getMax():getX() - Proc.Box:getMax():getX() -- sempre concavo aumento la distanza (rimane una punta...) dDist = dDist + 10 BL.UpdateHCING( _nRawId, dOffs, dDist) end end return true end --------------------------------------------------------------------- local function MakePreCuts( Proc) -- se interessa l'intera sezione della trave, necessaria sgrossatura if _nChamfer < 2 and Proc.Box:getDimY() > 0.9 * _b3Raw:getDimY() and Proc.Box:getDimZ() > 0.9 * _b3Raw:getDimZ() then -- aggiungo sgrossatura e la lavoro local AddId = EgtSurfTmConvexHullInBBox( _nAddGrpId, Proc.Id, _b3Raw, GDB_RT.GLOB) if AddId then EgtSetName( AddId, 'AddCut_' .. tostring( Proc.Id)) -- applico lavorazione local CutProc = { Id = AddId, Grp = Proc.Grp, Prc = Proc.Prc, Box = Proc.Box, Fct = Proc.Fct, Flg = Proc.Flg, Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId} local nCutFacet = EgtSurfTmFacetCount( AddId) if nCutFacet == 1 then return Cut.Make( CutProc, _nPhase, _nRawId, _nPartId, _dOvmHead) elseif nCutFacet == 2 then return DoubleCut.Make( CutProc, _nPhase, _nRawId, _nPartId, _dOvmHead) end end end return true end --------------------------------------------------------------------- local function MakeByMill( Proc, nFacInd, rfFac, dH, dV, dElev, dCollSic, bSpecialApp, sMillMaster, nFacInd2, dFacElev2) -- Cerco una faccia adiacente alla principale sul lato lungo local nFacAdj, sErr = GetFaceAdj( Proc, nFacInd, dH, dV) if nFacAdj < 0 then EgtOutLog( sErr) return false, sErr end -- Determino se estremi aperti o chiusi e faccia adiacente da aggiungere alla lavorazione local bOpenStart = false local bOpenEnd = false local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1] EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3) local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacAdj, GDB_ID.ROOT) -- Riordino le dimensioni per avere dH > dV if dH2 < dV2 then dH2, dV2 = dV2, dH2 end local nFacAdj2 for j = 1, #vAdj2 do if vAdj2[j] == nFacInd then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == nFacInd do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == nFacInd do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) end -- decommentare questa parte per concatenare due facce --if bSpecialApp and vAdj2[j] >= 0 then -- local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacAdj, vAdj2[j], GDB_ID.ROOT) -- local dLen = dist( ptP1, ptP2) -- if abs( dLen - dV2) < 10 * GEO.EPS_SMALL then -- nFacAdj2 = vAdj2[j] -- end --end end -- Recupero la lavorazione di fresa local sMilling if bSpecialApp then sMilling = sMillMaster else sMilling = ML.FindMilling( 'LongSmallCut') if not sMilling then sErr = 'Error : LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr end end -- recupero i dati dell'utensile local dTDiam = 50 local dMaxMat = 0 local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam dMaxMat = TI.dMaxMat or dMaxMat end -- Se massimo materiale utensile è molto inferiore dell'elevazione non faccio la lavorazione e do un warning if dMaxMat > 0 and dMaxMat + 15 < dElev + dCollSic then local sWarn = 'Warning : skipped milling; elevation bigger than max tool depth' return true, sWarn, dMaxMat end -- Calcolo uso faccia local nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ()) -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria if nFacAdj2 then EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj},{ Proc.Id, nFacAdj2}}) else EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}}) end -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_YM if rfFac:getVersZ():getY() > 100 * GEO.EPS_ZERO then nSCC = MCH_SCC.ADIR_YP end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- lato di lavoro e direzione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) EgtSetMachiningParam( MCH_MP.INVERT, true) -- tipo di attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR) -- imposto accorciamento iniziale/finale per estremi aperti/chiusi if bSpecialApp then -- applico gli allungamenti o accorciamenti considerando che la lavorazione è invertita if nFacAdj2 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, dTDiam / 2, - dTDiam / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, dTDiam / 2, - dTDiam / 2)) -- confronto la faccia applicata nella lavorazione (faccia adiacente) con la seconda faccia passata nella funzione -- se corrispondono allora aggiungo una estensione nei lati chiusi pari all'elevazione della stessa faccia corrispondente if nFacAdj == nFacInd2 then if not bOpenStart then EgtSetMachiningParam( MCH_MP.LOPERP, dFacElev2) EgtSetMachiningParam( MCH_MP.LOTANG, 0) end if not bOpenEnd then EgtSetMachiningParam( MCH_MP.LIPERP, dFacElev2) EgtSetMachiningParam( MCH_MP.LITANG, 0) end end end -- applico elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, 0, - dTDiam / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, 0, - dTDiam / 2)) end -- eseguo if not EgtApplyMachining( true, false) then _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end return true, '', dTDiam end --------------------------------------------------------------------- local function ChooseCorner( Proc, nFacInd) -- Recupero le adiacenze della faccia principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] -- Cerco i corner tra le facce adiacenti alla principale local tFacAdj = {} for i = 1, #vAdj do if vAdj[i] >= 0 then for j = i + 1, #vAdj do if vAdj[j] >= 0 then local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, vAdj[i], vAdj[j], GDB_ID.ROOT) if ptP1 and ptP2 and dAng < 0 then local dLen = dist( ptP1, ptP2) table.insert( tFacAdj, { vAdj[i], vAdj[j], dLen, ptP1, ptP2, dAng}) end end end end end -- Tra le linee dei corner determino la più lunga local dMaxLen = 0 local nIdLine for i = 1, #tFacAdj do if tFacAdj[i][3] > dMaxLen then nIdLine = i dMaxLen = tFacAdj[i][3] end end return dMaxLen, nIdLine, tFacAdj end --------------------------------------------------------------------- local function ChooseContour( Proc, nFacInd, bVerifyCorner) -- Recupero le adiacenze della faccia principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] -- Se richiesto, verifico che ci siano facce adiacenti consecutive (sicuramente con angolo) if bVerifyCorner then local bCorner = false for i = 1, #vAdj do local j = EgtIf( i > 1, i - 1, #vAdj) if vAdj[i] >= 0 and vAdj[j] >= 0 then bCorner = true break end end if not bCorner then return {} end end -- Cerco le facce adiacenti con angolo convesso local tFacAdjMain = {} for i = 1, #vAdj do if vAdj[i] >= 0 then local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) if ptP1 and ptP2 and dAng < 0 then local dLen = dist( ptP1, ptP2) table.insert( tFacAdjMain, { vAdj[i], dLen, ptP1, ptP2, dAng}) end end end return tFacAdjMain end --------------------------------------------------------------------- local function CheckToInvert( AuxId, bPositive) -- recupero versore estrusione local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT) -- faccio una copia del percorso local sParnt = EgtGetParent( AuxId) local nNewEntId = EgtCopyGlob( AuxId, sParnt) -- chiudo il percorso if EgtCloseCurveCompo( nNewEntId) then local vtMPlane, _, dArea = EgtCurveArea( nNewEntId) -- cancello percorso copia EgtErase( nNewEntId) if dArea and abs(dArea) > 1 then local frEnt = EgtGetGlobFrame( AuxId) if vtMPlane then vtMPlane:toGlob(frEnt) if dArea and dArea * ( vtMPlane * vtExtr) < 0 then if bPositive then return true end elseif dArea and dArea * ( vtMPlane * vtExtr) > 0 then if not bPositive then return true end end end end else -- cancello percorso copia EgtErase(nNewEntId) end return false end --------------------------------------------------------------------- local function TestPoints( nPathInt, idx, dDiff, pP1, pP2, sAxis) local pPini = EgtIf( sAxis == 'X', pP1:getX(), EgtIf( sAxis == 'Y', pP1:getY(), pP1:getZ())) local pPend = EgtIf( sAxis == 'X', pP2:getX(), EgtIf( sAxis == 'Y', pP2:getY(), pP2:getZ())) local b3SolidMin = EgtIf( sAxis == 'X', _b3Solid:getMin():getX(), EgtIf( sAxis == 'Y', _b3Solid:getMin():getY(), _b3Solid:getMin():getZ())) local b3SolidMax = EgtIf( sAxis == 'X', _b3Solid:getMax():getX(), EgtIf( sAxis == 'Y', _b3Solid:getMax():getY(), _b3Solid:getMax():getZ())) if ( abs( pPini - b3SolidMax) < dDiff and abs( pPend - b3SolidMax) < dDiff) or ( abs( pPini - b3SolidMin) < dDiff and abs( pPend - b3SolidMin) < dDiff) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. idx) else EgtSetInfo( nPathInt, 'OPEN', idx) end return true else return false end end --------------------------------------------------------------------- local function SetOpenSide( nPathInt, vtOrtho, nStartPoint) -- fondo tra loro le curve compatibili EgtMergeCurvesInCurveCompo( nPathInt) local nStartIdEnt, nNumEnt = EgtCurveDomain( nPathInt) local pLastPIni, pLastPEnd -- faccio una copia della curva e la esplodo if nStartIdEnt then -- prendo i punti for i = 1, nNumEnt do local pPini = EgtUP( nPathInt, (i - 1), GDB_RT.GLOB) local pPend = EgtUP( nPathInt, EgtIf( i == nNumEnt, 0, i), GDB_RT.GLOB) -- Se normale lungo la Z considero il box in X e Y if abs(vtOrtho:getZ()) > 0.999 then -- se corrisponde a X prendo i punti per eventuale modifica del punto di inizio percorso if TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'X') then pLastPIni = pPini pLastPEnd = pPend -- altrimenti se corrisponde a Y prendo i punti per eventuale modifica del punto di inizio percorso elseif TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Y') then pLastPIni = pPini pLastPEnd = pPend end -- altrimenti se normale lungo la Y considero il box in X e Z elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.999 then -- se corrisponde a X prendo i punti per eventuale modifica del punto di inizio percorso if TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'X') then pLastPIni = pPini pLastPEnd = pPend -- altrimenti se corrisponde a Z prendo i punti per eventuale modifica del punto di inizio percorso elseif TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Z') then pLastPIni = pPini pLastPEnd = pPend end -- caso che non dovrebbe mai capitare ma gestito per completezza -- altrimenti se normale lungo la X considero il box in Y e Z elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.999 then -- se corrisponde a Y prendo i punti per eventuale modifica del punto di inizio percorso if TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Y') then pLastPIni = pPini pLastPEnd = pPend -- altrimenti se corrisponde a Z prendo i punti per eventuale modifica del punto di inizio percorso elseif TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Z') then pLastPIni = pPini pLastPEnd = pPend end -- se asse Z orizzontale verifico se si avvicina piú a Y elseif abs(vtOrtho:getZ()) < 0.001 then if abs(vtOrtho:getY()) > 0.75 then -- se corrisponde a Z prendo i punti per eventuale modifica del punto di inizio percorso if TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Z') then pLastPIni = pPini pLastPEnd = pPend end end -- se asse Y a 0 (fresa ne davanti ne dietro) verifico se si avvicina piú a Z+ elseif abs(vtOrtho:getY()) < 0.001 then if abs(vtOrtho:getZ()) > 0.75 then -- se corrisponde a Y prendo i punti per eventuale modifica del punto di inizio percorso if TestPoints(nPathInt, i - 1, 10 * GEO.EPS_SMALL, pPini, pPend, 'Y') then pLastPIni = pPini pLastPEnd = pPend end end end end -- se devo cambiare il punto di partenza if nStartPoint then if pLastPIni and pLastPEnd then -- calcolo il punto medio con gli ultimi punti utilizzati local ptPs = ( pLastPIni + pLastPEnd) / 2 EgtChangeClosedCurveStartPoint( nPathInt, ptPs, GDB_RT.GLOB) -- se devo eliminare la parte open if nStartPoint == 2 then EgtRemoveCurveCompoCurve( nPathInt, true) EgtRemoveCurveCompoCurve( nPathInt, false) return true end end end end return false end --------------------------------------------------------------------- local function MakeRoundCleanCorner( Proc, nFacInd, dDiam, bMillDown, bDoubleSide) -- recupero la lavorazione senza considerare l'elevazione local sMilling = ML.FindMilling( 'SmallToolContour' .. EgtIf( bMillDown and not bDoubleSide, '_H2', '')) if not sMilling then local sMyWarn = 'Warning : SmallToolContour not found in library' EgtOutLog( sMyWarn) return true, sMyWarn end -- recupero i dati dell'utensile local dTDiam = 50 local dTMaxDepth = 0 local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam dTMaxDepth = TI.dMaxDepth or dTMaxDepth end -- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco if dTDiam > ( 0.75 * dDiam) then local sMyWarn = 'Warning : tool diameter not enough small' EgtOutLog( sMyWarn) return true, sMyWarn end -- ottengo gli angoli dove applicare il percorso con fresa più piccola local _, _, tFacAdj = ChooseCorner( Proc, nFacInd) -- se non trovato nessun angolo interno valido esco if #tFacAdj == 0 then return true end -- recupero la normale della faccia di fondo local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) -- se fresatura da sotto salto la lavorazione if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then local sErr = 'Error : milling from bottom ' EgtOutLog( sErr) return false, sErr end -- ciclo su tutti gli angoli trovati local sMyWarn = '' for i = 1, #tFacAdj do local pAuxId = {} -- le 2 facce di contatto devono essere perpendicolari e non sottosquadra rispetto alla faccia di fondo local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][1], GDB_ID.ROOT) local _, ptP1x, ptP2x, dAngx = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][2], GDB_ID.ROOT) if dAng >= 0 or dAng < -90 - 10 * GEO.EPS_SMALL or dAngx >= 0 or dAngx < -90 - 10 * GEO.EPS_SMALL then goto continue end -- prendo la lunghezza di adiacenza delle due linee local dLen1 = dist( ptP1, ptP2) local dLen2 = dist( ptP1x, ptP2x) -- cerco il punto tra le 3 facce: nIdEndPoint local _, nIdEndPoint = GetIdIniEndPoints(ptP1, ptP2, tFacAdj[i]) -- devo avere un punto comune if not nIdEndPoint then goto continue end -- calcolo lunghezza minima in base all'angolo tra le due pareti local dMinDist = (( dDiam / 2) / tan( ( 180 + tFacAdj[i][6]) / 2)) + 2 -- verifico che entrambe le linee siano maggiori delle lunghezza minima if dLen1 <= dMinDist or dLen2 <= dMinDist then sMyWarn = 'Warning : impossible make clean corner path' goto continue end -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro local ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1) < 10 * GEO.EPS_SMALL, ptP2, ptP1) -- prima linea local nAuxId = EgtLine( _nAddGrpId, ptApPoint, tFacAdj[i][nIdEndPoint], GDB_RT.GLOB) -- calcolo arretramento local dTrimDist = dLen1 - dMinDist -- se arretramento valido if dTrimDist > 100 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint, GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- se il punto finale corrisponde con il punto comune, uso l'altro ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1x) < 10 * GEO.EPS_SMALL, ptP2x, ptP1x) -- seconda linea nAuxId = EgtLine( _nAddGrpId, tFacAdj[i][nIdEndPoint], ptApPoint, GDB_RT.GLOB) -- calcolo arretramento dTrimDist = dLen2 - dMinDist -- se arretramento valido if dTrimDist > 100 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint, GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- trasformo in percorso local AuxId if #pAuxId > 0 then AuxId = EgtCurveCompo( _nAddGrpId, pAuxId, true) end -- deve esserci il percorso if not AuxId then sMyWarn = 'Warning : impossible make clean corner path' goto continue end -- modifico versore direzione EgtModifyCurveExtrusion( AuxId, vtN1, GDB_RT.GLOB) -- inserisco la lavorazione local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling goto continue end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto lato di lavoro sinistro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- annullo allungamenti iniziale e finale EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) -- setto massimo affondamento possibile local dDepth = 0 if tFacAdj[i][3] > dTMaxDepth then dDepth = dTMaxDepth - tFacAdj[i][3] end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- setto se devo invertire il percorso local bInvert = CheckToInvert( AuxId, true) EgtSetMachiningParam( MCH_MP.INVERT, bInvert) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;' sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( tFacAdj[i][3] + dDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) end -- altrimenti lavorazione non applicata else _, sMyWarn = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end ::continue:: end if #sMyWarn > 0 then EgtOutLog( sMyWarn) end return true, sMyWarn end --------------------------------------------------------------------- local function MakeRoundCleanContour( Proc, nFacInd, dDiam, bMillDown, bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot) -- recupero la lavorazione senza considerare l'elevazione perché viene calcolata l'elevazione utile local sMilling = ML.FindMilling( 'SmallToolContour' .. EgtIf( bMillDown and not bDoubleSide, '_H2', '')) if not sMilling then local sMyWarn = 'Warning : SmallToolContour not found in library' EgtOutLog( sMyWarn) return true, sMyWarn end -- recupero i dati dell'utensile local dTDiam = 50 local dTMaxDepth = 0 local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam dTMaxDepth = TI.dMaxDepth or dTMaxDepth end local sMillingDn = ML.FindMilling( 'SmallToolContour' .. EgtIf( bMillDown and bDoubleSide, '_H2', '')) if not sMillingDn then local sMyWarn = 'Warning : Opposite SmallToolContour not found in library' EgtOutLog( sMyWarn) return true, sMyWarn end -- recupero i dati dell'utensile testa da sotto local dTDiamDn = 50 local dTMaxDepthDn = 0 local TI = GetToolInfoForMachining( sMillingDn) if TI then dTDiamDn = TI.dDiam or dTDiamDn dTMaxDepthDn = TI.dMaxDepth or dTMaxDepthDn end -- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco if dTDiam > ( 0.75 * dDiam) then local sMyWarn = 'Warning : tool diameter not enough small' EgtOutLog( sMyWarn) return true, sMyWarn end local vtN1 local nFirstId, nNumId local dMaxElev local dCollSic = 0 local dExtraDepth = 0 -- se non ho la faccia aggiunta if not nPathInt then -- cerco gli angoli dove applicare il percorso con fresa piú piccola e i lati in comune local tFacAdjMain = ChooseContour( Proc, nFacInd, true) -- se non trovato nessun angolo interno da pulire esco if #tFacAdjMain == 0 then return true end -- normale alla faccia di fondo vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) -- se fresatura da sotto salto la lavorazione if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then local sErr = 'Error : milling from bottom' EgtOutLog( sErr) return false, sErr end -- distanza di sicurezza per evitare collisioni dCollSic = CalcCollisionSafety( vtN1) -- elevazione massima della faccia dMaxElev = BL.GetFaceElevation( Proc.Id, nFacInd, _nPartId) -- ciclo tutta la tabella local tPaths = {} local ptIniPath local ptMidDist local dMaxLen = 0 for i = 1, #tFacAdjMain do -- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo local ptP1, ptP2, dAng ptP1 = tFacAdjMain[i][3] ptP2 = tFacAdjMain[i][4] dAng = tFacAdjMain[i][5] if ( dAng < 0 and dAng >= -90 - 10 * GEO.EPS_SMALL) then -- creo la linea da P1 a P2 local nAuxId = EgtLine( _nAddGrpId, ptP1, ptP2, GDB_RT.GLOB) table.insert( tPaths, nAuxId) -- prendo la lunghezza massima e il punto medio if tFacAdjMain[i][2] > dMaxLen then ptIniPath = ptP1 dMaxLen = tFacAdjMain[i][2] ptMidDist = ( ptP1 + ptP2) / 2 end end end -- costruisco il/i percorso/i nFirstId, nNumId = EgtCurveCompoByReorder( _nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB) if nFirstId then -- se un solo percorso e chiuso cambio il punto di inizio nell'entitá piú lunga if nNumId == 1 and EgtCurveIsClosed( nFirstId) then EgtChangeClosedCurveStartPoint( nFirstId, ptMidDist, GDB_RT.GLOB) end -- modifico versore direzione for i = 1, nNumId do EgtModifyCurveExtrusion( nFirstId + i - 1, vtN1, GDB_RT.GLOB) end end -- alrimenti ho la faccia aggiunta else -- assegno il percorso nFirstId = EgtCopyGlob( nPathInt, _nAddGrpId) nNumId = 1 -- distanza di sicurezza per evitare collisioni dCollSic = CalcCollisionSafety( vtOrtho) -- calcolo elevazione dalla faccia trasversale aggiunta local dSurfIntElev = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) if bDoubleSide then dMaxElev = dSurfIntElev else dMaxElev = dDepth -- se la precedente svuotatura è stata fatta completamente in una sola volta -- valuto di nuovo se devo fare due passate o una sola if bOneShot then -- se non è possibile svuotare completamente da una sola parte if dTMaxDepth <= ( dMaxElev + BD.CUT_EXTRA + dCollSic) then bDoubleSide = true dMaxElev = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) else dExtraDepth = dMaxElev - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end -- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie else dExtraDepth = dMaxElev - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end end -- normale alla faccia aggiunta vtN1 = Vector3d( vtOrtho) -- imposto i lati aperti SetOpenSide( nFirstId, vtOrtho, 2) end -- se non trovato il percorso, esco if not nFirstId then local sMyWarn = 'Warning : impossible make clean corner path' EgtOutLog( sMyWarn) return true, sMyWarn end -- assegno lavorazioni ad ogni percorso local sMyWarn = '' for i = 1, nNumId do local nIdPath = nFirstId + i - 1 local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling goto continue end -- aggiungo geometria EgtSetMachiningGeometry( {{ nIdPath, -1}}) -- imposto lato di lavoro sinistro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- inversione direzione utensile local bInvertMach = false if nPathInt then -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true -- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true end end -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- gestione attacco e uscita if EgtCurveIsClosed( nIdPath) then -- attacco e uscita a quarto di cerchio senza allungamenti a inizio e fine EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) EgtSetMachiningParam( MCH_MP.LITANG, 0) EgtSetMachiningParam( MCH_MP.LIPERP, 0.5 * dTDiam) EgtSetMachiningParam( MCH_MP.LIELEV, 0) EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) else -- nessun attacco e uscita, allungo inizio e fine di 3/4 del diametro utensile EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0.75 * dTDiam) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0.75 * dTDiam) end -- setto massimo affondamento possibile local dMachDepth = 0 if ( dMaxElev + dCollSic) > dTMaxDepth then dMachDepth = dTMaxDepth - ( dMaxElev + dCollSic) end EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth + dExtraDepth) -- setto se devo invertire il percorso local bInvert = CheckToInvert( nIdPath, true) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertMach, not bInvert, bInvert)) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;' sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) end -- altrimenti lavorazione non applicata else _, sMyWarn = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end -- se devo applicare la contornatura anche sul lato opposto if bDoubleSide then if bMillDown then sMilling = sMillingDn dTDiam = dTDiamDn dTMaxDepth = dTMaxDepthDn end sName = 'CleanOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) nMchId = EgtAddMachining( sName, sMilling) if not nMchId then sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling goto continue end -- aggiungo geometria EgtSetMachiningGeometry( {{ nIdPath, -1}}) -- imposto lato di lavoro sinistro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- imposto direzione utensile opposta EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- allungo inizio e fine di 3/4 del diametro utensile EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam * 0.75) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam * 0.75) -- setto massimo affondamento possibile local dMachDepth = 0 if ( dMaxElev + dCollSic) > dTMaxDepth then dMachDepth = dTMaxDepth - ( dMaxElev + dCollSic) end EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- setto se devo invertire il percorso local bInvert = CheckToInvert( nIdPath, true) EgtSetMachiningParam( MCH_MP.INVERT, not bInvert) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;' sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) end -- altrimenti lavorazione non applicata else _, sMyWarn = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end end ::continue:: end if #sMyWarn > 0 then EgtOutLog( sMyWarn) end return true, sMyWarn end --------------------------------------------------------------------- local function MakeRoundCleanCornerOrContour( Proc, nFacInd, dDiam, nFunction, bMillDown, bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot) -- se modalitá pulitura spigoli e lavorazione di lato forzo a fare il contorno if nFunction == 2 and nPathInt then nFunction = 1 end -- se richiesta pulitura del contorno if nFunction == 1 then return MakeRoundCleanContour( Proc, nFacInd, dDiam, bMillDown, bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot) -- se richiesta pulitura dei soli corner elseif nFunction == 2 then return MakeRoundCleanCorner( Proc, nFacInd, dDiam, bMillDown, bDoubleSide) -- altri casi non previsti else return true end end --------------------------------------------------------------------- local function MakeSharpCleanCorner( Proc, nFacInd, dDiam) local sMyWarn = '' local pAuxId = {} local nAuxId local AuxId local ptApPoint local dLenTrimExt local sMilling local dMaxDepth = 0 -- cerco l'angolo di riferimento dove applicare il percorso di pulitura, altrimenti esco local _, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd) if #tFacAdj == 0 then return true end -- prendo il primo versore local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT) local vtN3 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT) -- trovo il punto sulla superfice di riferimento local _, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT) local nIdIniPoint, nIdEndPoint = GetIdIniEndPoints(ptLocP1, ptLocP2, tFacAdj[nIdLine]) -- versore direzione local vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint] vtExtr:normalize() -- inserisco le prime tre linee if nIdIniPoint and nIdEndPoint then -- se fresatura da sotto salto la lavorazione if vtExtr:getZ() < BD.DRILL_VZ_MIN then local sErr = 'Error : clean corner milling from bottom impossible' EgtOutLog( sErr) return false, sErr end -- sommo i tre versori per avre una direzione media vtExtr = vtN1 + vtN2 + vtN3 vtExtr:normalize() -- recupero la lavorazione non calcolando l'elevazione sMilling = ML.FindMilling( 'CleanCorner', ( 0.5 * dDiam)) if not sMilling then local sErr = 'Error : CleanCorner not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile ( temporaneo, per compensare errore nella lavorazione) local TI = GetToolInfoForMachining( sMilling) if TI then dMaxDepth = TI.dMaxMat or dMaxDepth end -- l'altezza di taglio del tagliente corrisponde al raggio del raccordo che si riesce a coprire -- quindi confronto l'elevazione con il raggio utensile utilizzato per la svuotatura if dMaxDepth < ( dDiam * 0.5) - 100 * GEO.EPS_SMALL then sMyWarn = 'Warning : skip clean corner (the cut heigth is smaller to machine the corner radius)' EgtOutLog( sMyWarn) return false, sMyWarn end nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdIniPoint], tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then ptApPoint = ptLocP2 else ptApPoint = ptLocP1 end nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB) dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - (( dDiam / 2) + 2) -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta if dLenTrimExt > 10 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint , GDB_RT.GLOB) -- prendo il nuovo punto finale ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- creo linea di ritorno nAuxId = EgtLine( _nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end -- inserisco le ultime tre linee + uscita discostata rispetto all'ingresso -- trovo il secondo punto sulla superfice di riferimento _, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][2], GDB_ID.ROOT) if ptLocP1 and ptLocP2 then -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then ptApPoint = ptLocP2 else ptApPoint = ptLocP1 end nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB) dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - (( dDiam / 2) + 2) -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta if dLenTrimExt > 10 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint , GDB_RT.GLOB) -- prendo il nuovo punto finale ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- creo linea di ritorno nAuxId = EgtLine( _nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- piccolo scostamento di 2mm dall'angolo nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- ultima linea di risalita nAuxId = EgtLine( _nAddGrpId, tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), tFacAdj[nIdLine][nIdIniPoint] + ( 2 * vtExtr), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end -- trasformo in percorso if #pAuxId > 0 then AuxId = EgtCurveCompo( _nAddGrpId, pAuxId, true) end -- se non c'é il percorso do errore if not AuxId then local sErr = 'Error : impossible make clean corner path' EgtOutLog( sErr) return false, sErr end -- modifico versore direzione EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB) -- inserisco la lavorazione local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- allungo inizio e fine di 10mm EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10) -- setto affondamento 0 EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;MaxElev=' .. EgtNumToString( dMaxDepth, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr else local _, sWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) return false, sWarn else return true, ( sMyWarn or sWarn) end end return true, sMyWarn end --------------------------------------------------------------------- local function MakeDrillOnCorner( Proc, nFacInd, dDiam, bSpecialMach) local sMyWarn = '' -- ottengo l'angolo dove applicare il foro local dMaxLen, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd) -- se non trovato nessun angolo interno valido esco if #tFacAdj == 0 then return true, sMyWarn end -- trovo il punto sulla superfice di riferimento local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT) local nIdIniPoint, nIdEndPoint = GetIdIniEndPoints(ptLocP1, ptLocP2, tFacAdj[nIdLine]) -- inserisco foro if nIdIniPoint and nIdEndPoint then local vtExtr if bSpecialMach then local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local _, vtN1 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT) local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT) vtExtr = vtN0 + vtN1 + vtN2 else -- versore direzione vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint] end vtExtr:normalize() -- se foratura da sotto salto la lavorazione if vtExtr:getZ() < BD.DRILL_VZ_MIN then local sErr = 'Error : drilling from bottom impossible' EgtOutLog( sErr) return false, sErr end -- recupero la lavorazione local sDrilling, nType = ML.FindDrilling( dDiam) if not sDrilling then local sErr = 'Error : drilling not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dMaxDepth = 20 local dDiamTool = 20 local dDiamTh = 35 local bIsDrilling local TI = GetToolInfoForMachining( sDrilling) if TI then bIsDrilling = ( EgtMdbGetCurrMachiningParam( MCH_MP.TYPE) == MCH_MY.DRILLING) if bIsDrilling then dMaxDepth = TI.dMaxMat or dMaxDepth else dMaxDepth = TI.dMaxDepth or dMaxDepth end dDiamTool = TI.dDiam or dDiamTool dDiamTh = TI.dThDiam or dDiamTh end -- se foro inclinato, limito il massimo affondamento local CosB = abs( vtExtr:getX()) if CosB < BD.DRILL_VX_MAX then local TgA = CosB / sqrt( 1 - CosB * CosB) dMaxDepth = dMaxDepth - dDiamTh / 2 * TgA else dMaxDepth = 0 end -- setto griglia if bSpecialMach then EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdEndPoint], vtExtr)) else EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdIniPoint], vtExtr)) end -- creo geometria local AuxId = EgtCircle( _nAddGrpId, {0, 0, 0}, EgtIf( bIsDrilling, dDiamTool / 2, ( dDiamTool / 2) + 0.1), GDB_RT.GRID) -- riporto la griglia a globale EgtSetGridFrame() -- calcolo spessore local dDepthBore = dMaxLen if bSpecialMach then -- calcolo l'elevazione local dLenIn, dLedOut = BL.GetPointDirDepth( _nPartId, tFacAdj[nIdLine][nIdEndPoint], vtExtr) if dLenIn > 0 then dDepthBore = dLenIn elseif dLedOut then dDepthBore = dLedOut end EgtModifyCurveThickness( AuxId, dDepthBore) else EgtModifyCurveThickness( AuxId, -dMaxLen) end -- inserisco la lavorazione local sName = 'Drill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sDrilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sDrilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_YM if vtExtr:getY() > 100 * GEO.EPS_ZERO then nSCC = MCH_SCC.ADIR_YP end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- aggiusto l'affondamento local dDepth if bSpecialMach then dDepth = dDepthBore else dDepth = dMaxLen if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then sMyWarn = 'Warning in drill : depth (' .. EgtNumToString( dDepth, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' dDepth = dMaxDepth EgtOutLog( sMyWarn) end end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill local sUserNotes = 'VMRS=0;' -- aggiungo alle note massima elevazione (coincide con affondamento) sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dDepth, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr else local _, sWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) return false, sWarn else return true, ( sMyWarn or sWarn) end end end return true, sMyWarn end --------------------------------------------------------------------- local function ErasePathIfNecessary( nPathId, sDeleteByDir, dDiff) local ptP1 = EgtSP( nPathId, GDB_RT.GLOB) local ptP2 = EgtEP( nPathId, GDB_RT.GLOB) if abs( EgtIf( sDeleteByDir == 'X', (ptP1:getX() - ptP2:getX()), EgtIf( sDeleteByDir == 'Y', (ptP1:getY() - ptP2:getY()), (ptP1:getZ() - ptP2:getZ())))) > dDiff then EgtErase( nPathId) end end --------------------------------------------------------------------- local function TestPaths( sDeleteByDir, nStartId, nNumIds, dDiff) local tPaths = {} local dMaxVal, dMinVal for i = 1, nNumIds do local bInsTab local nIdx = nStartId + i - 1 local ptP1 = EgtSP( nIdx, GDB_RT.GLOB) if ptP1 then for j = 1, #tPaths do local dLocalVal = tPaths[j][2] if abs( EgtIf( sDeleteByDir == 'X', ptP1:getX() - dLocalVal, EgtIf( sDeleteByDir == 'Y', ptP1:getY() - dLocalVal, ptP1:getZ() - dLocalVal))) < dDiff then local tLocIds = tPaths[j][1] table.insert( tLocIds, ( nIdx)) tPaths[j][1] = tLocIds bInsTab = true end end -- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella if not bInsTab then table.insert( tPaths, {{( nIdx)}, ptP1:getX()}) dMaxVal = EgtIf( sDeleteByDir == 'X', _b3Solid:getMax():getX(), EgtIf( sDeleteByDir == 'Y', _b3Solid:getMax():getY(), _b3Solid:getMax():getZ())) dMinVal = EgtIf( sDeleteByDir == 'X', _b3Solid:getMin():getX(), EgtIf( sDeleteByDir == 'Y', _b3Solid:getMin():getY(), _b3Solid:getMin():getZ())) end end end return tPaths, dMaxVal, dMinVal end --------------------------------------------------------------------- local function ModifyPathExtrusion(tPath, sDeleteByDir, dMaxVal, dDiff) local ptP1 = EgtSP( tPath, GDB_RT.GLOB) if abs( EgtIf( sDeleteByDir == 'X', ptP1:getX(), EgtIf( sDeleteByDir == 'Y', ptP1:getY(), ptP1:getZ())) - dMaxVal) < dDiff then EgtModifyCurveExtrusion( tPath, EgtIf( sDeleteByDir == 'X', X_AX(), EgtIf( sDeleteByDir == 'Y', Y_AX(), Z_AX())), GDB_RT.GLOB) else EgtModifyCurveExtrusion( tPath, EgtIf( sDeleteByDir == 'X', -X_AX(), EgtIf( sDeleteByDir == 'Y', -Y_AX(), -Z_AX())), GDB_RT.GLOB) end end --------------------------------------------------------------------- local function ExtractExternalPaths( nPathInt, nNumIdAux, vtOrtho) local nAuxId1, nAuxId2 if nNumIdAux == 1 then -- fondo tra loro le curve compatibili EgtMergeCurvesInCurveCompo( nPathInt) -- esplodo il percorso in modo da avere entià separate per poterle controllare local nStartId, nNumIds = EgtExplodeCurveCompo( nPathInt) if nStartId then local sDeleteByDir -- Se normale lungo la Z elimino le entità che hanno differenza in Z if abs(vtOrtho:getZ()) > 0.7 then sDeleteByDir = 'Z' -- altrimenti se normale lungo la Y elimino le entità che hanno variazione in Y -- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.7 then elseif abs(vtOrtho:getY()) > 0.7 then sDeleteByDir = 'Y' -- caso che non dovrebbe mai capitare ma gestito per completezza -- altrimenti se normale lungo la X elimino le entità che hanno variazione in X -- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.7 then elseif abs(vtOrtho:getX()) > 0.7 then sDeleteByDir = 'X' end if sDeleteByDir then for i = 1, nNumIds do ErasePathIfNecessary( nStartId + i - 1, sDeleteByDir, 10 * GEO.EPS_SMALL) end -- ricreo i vari percorsi local tPaths, dMaxVal, dMinVal = TestPaths( sDeleteByDir, nStartId, nNumIds, 10 * GEO.EPS_SMALL) if tPaths then local tChamPath = {} -- elimino quelle che non corrispondono agli estremi for i = 1, #tPaths do -- se non corrisponde ai limiti elimino l'elemento if abs( tPaths[i][2] - dMaxVal) > 10 * GEO.EPS_SMALL and abs( tPaths[i][2] - dMinVal) > 10 * GEO.EPS_SMALL then tPaths[i] = nil else local tNoMatch = {} local tPathLoc = tPaths[i][1] local pIniLoc = EgtSP( tPathLoc[1], GDB_RT.GLOB) local pEndLoc = EgtEP( tPathLoc[1], GDB_RT.GLOB) -- ciclo sui percorsi per trovare i punti non coincidenti (se percorso non chiuso) for j = 2, #tPathLoc do -- prendo i punti del percorso successivo local pAddIni = EgtSP( tPathLoc[j], GDB_RT.GLOB) local pAddEnd = EgtEP( tPathLoc[j], GDB_RT.GLOB) -- se consecutivi if AreSamePointApprox( pEndLoc, pAddIni) then pEndLoc = pAddEnd elseif AreSamePointApprox( pIniLoc, pAddEnd) then pIniLoc = pAddIni else table.insert( tNoMatch, tPathLoc[j]) end end -- controllo eventuali percorsi scartati for j = 1, #tNoMatch do -- prendo i punti del percorso successivo local pAddIni = EgtSP( tNoMatch[j], GDB_RT.GLOB) local pAddEnd = EgtEP( tNoMatch[j], GDB_RT.GLOB) -- se consecutivi if AreSamePointApprox( pEndLoc, pAddIni) then pEndLoc = pAddEnd elseif AreSamePointApprox( pIniLoc, pAddEnd) then pIniLoc = pAddIni end end -- creo concatenamento partendo dal punto iniziale local nIdLoc = EgtCurveCompoByReorder( _nAddGrpId, tPathLoc, pIniLoc, true) if nIdLoc then table.insert( tChamPath, nIdLoc) end end end for i = 1, #tChamPath do -- modifico estrusione percorso ModifyPathExtrusion(tChamPath[i], sDeleteByDir, dMaxVal, 10 * GEO.EPS_SMALL) end if #tChamPath == 1 then return tChamPath[1], 1, nil elseif #tChamPath == 2 then return tChamPath[1], 2, tChamPath[2] else for i = 1, nNumIds do EgtErase( nStartId + i - 1) end for i = 1, #tChamPath do EgtErase( tChamPath[i]) end end else for i = 1, nNumIds do EgtErase( nStartId + i - 1) end end -- altrimenti cancello tutte le emtità e restituisco nil else for i = 1, nNumIds do EgtErase( nStartId + i - 1) end end end end return nil, 0, nil end --------------------------------------------------------------------- local function MakeChamfer( Proc, bIs3Faces, vtOrtho, nSurfInt) -- Se variabile globale indica che lo smusso è già stato fatto, esco if _bMadeChamfer then return 0 end _bMadeChamfer = true -- recupero la lavorazione local sMilling = ML.FindMilling( 'Mark') if not sMilling then local sErr = 'Error : Mark not found in library' EgtOutLog( sErr) return -1, sErr end -- ottengo le curve di contorno libero local nAuxId1, nAuxId2, nNumIdAux if bIs3Faces then -- nAuxId1, _ = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) -- EgtModifyCurveExtrusion( nAuxId1, vtOrtho, GDB_RT.GLOB) -- SetOpenSide( nAuxId1, vtOrtho, b3Solid, nAddGrpId, 1) -- nNumIdAux = 2 -- estraggo i percorsi nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, _nAddGrpId) -- se percorso creato estraggo solo i percorsi delle facce interessate, non di testa if nAuxId1 then nAuxId1, nNumIdAux, nAuxId2 = ExtractExternalPaths( nAuxId1, nNumIdAux, vtOrtho) end else nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, _nAddGrpId) if not nNumIdAux then nNumIdAux = 0 end end local dExtra = 2 for i = 1, nNumIdAux do local AuxId local vtExtr if bIs3Faces then if i == 1 then AuxId = nAuxId1 else -- faccio la copia del percorso -- AuxId = EgtCopyGlob( nAuxId1, nAddGrpId) AuxId = nAuxId2 end if AuxId then vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) end else AuxId = nAuxId1 + i - 1 vtExtr, _, _ = EgtCurveArea( AuxId) end if vtExtr then if not bIs3Faces then local fFrCurve = EgtGetGlobFrame( AuxId) vtExtr:toGlob( fFrCurve) end -- if bIs3Faces and i == nNumIdAux then -- vtExtr = -vtExtr -- end -- Se normale entro certi limiti -- if vtExtr:getZ() > -0.707 and ( abs(vtOrtho:getX()) > 0.99 or abs(vtOrtho:getY()) > 0.99 or abs(vtOrtho:getZ()) > 0.99) then if vtExtr:getZ() > -0.707 and ( abs(vtExtr:getX()) > 0.99 or abs(vtExtr:getY()) > 0.99 or abs(vtExtr:getZ()) > 0.99) then -- inserisco la lavorazione local sNameCh = 'Cham_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchId = EgtAddMachining( sNameCh, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sNameCh .. '-' .. sMilling EgtOutLog( sErr) return -1, sErr end -- modifico estrusione percorso EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB) -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa if vtExtr:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- assegno affondamento e offset radiale -- EgtSetMachiningParam( MCH_MP.DEPTH, _dDepthCham + dExtra - EgtIf( bIs3Faces, (dDepth / 2), 0)) EgtSetMachiningParam( MCH_MP.DEPTH, _dDepthCham + dExtra) EgtSetMachiningParam( MCH_MP.OFFSR, dExtra) -- se opero su 3 facce e sono al secondo e ultimo percorso inverto la lavorazione -- if bIs3Faces and i == nNumIdAux then -- EgtSetMachiningParam( MCH_MP.INVERT, true) -- end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return -1, sErr end -- se non perpendicolare emetto un warning -- else -- sWarn = 'Warning : chamfer skipped because not perpendicular to face or from bottom' -- EgtOutLog( sWarn) end --emetto un warning -- else -- sWarn = 'Warning : chamfer skipped because not perpendicular to face' -- EgtOutLog( sWarn) end end return 0 end --------------------------------------------------------------------- local function MakeByMillAsSaw( Proc, nFacInd, rfFac, dH, dV, dElev, nBottomFace, sMillingOnSide, dSawDiam, dSawThick) local sWarn -- ottengo la distanza tra la fine del pezzo e il pezzo successivo local dDistToNextPiece = EgtGetInfo( _nRawId, 'BDST', 'd') or 5. -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd1, _, _, _ = BL.GetFaceWithMostAdj( Proc.Id, _nPartId, true) if not nFacInd1 or nFacInd1 < 0 then if not nFacInd1 == -1 then local sErr = 'Error : MakeByMillAsSaw could not find reference face' EgtOutLog( sErr) return false, sErr end end -- Recupero le facce adiacenti alla principale (solo quelle esistenti) local vAdj = GetValidFacetAdjacencies( Proc.Id, nFacInd) if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' EgtOutLog( sErr) return false, sErr end EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3) -- Cerco una faccia adiacente alla principale sul lato più lungo local nFacAdj local dMaxLen = 0 for i = 1, #vAdj do local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) local dLen = dist( ptP1, ptP2) if dLen > dMaxLen then nFacAdj = vAdj[i] dMaxLen = dLen EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 3) end end if not nFacAdj then local sErr = 'Error : long adjacent face not found' EgtOutLog( sErr) return false, sErr end -- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacAdj, GDB_ID.ROOT) if abs( vtN * rfFac:getVersX()) > abs( vtN * rfFac:getVersY()) then dH, dV = dV, dH end -- Determino se estremi aperti o chiusi local bOpenStart = false local bOpenEnd = false -- se non ho la faccia di fondo ( che comporta essere una fessura) verifico se ho lati aperti if not nBottomFace then local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1] EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3) for j = 1, #vAdj2 do if vAdj2[j] == nFacInd then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == nFacInd do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- se è chiusa acquisisco vettore faccia tappo if not bOpenStart and vAdj2[i] >= 0 then _, vtNS = EgtSurfTmFacetCenter( Proc.Id, vAdj2[i], GDB_ID.ROOT) end -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == nFacInd do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) -- se è chiusa acquisisco vettore faccia tappo if not bOpenEnd and vAdj2[k] >= 0 then _, vtNE = EgtSurfTmFacetCenter( Proc.Id, vAdj2[k], GDB_ID.ROOT) end end end end -- Se possibile, lavoro con la lama if _bForceUseBlade then -- Recupero la lavorazione di lama local sCutting = sMillingOnSide -- Calcolo uso faccia local nFaceUse = BL.GetNearestOrthoOpposite( rfFac:getVersZ()) local dStartDist = -1 local dEndDist = -1 -- calcolo eventuali arretramenti lama if not bOpenStart then local dRadius = dSawDiam / 2 local dCat1 = dRadius - dElev dStartDist = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) end if not bOpenEnd then if not bOpenStart then dEndDist = dStartDist else local dRadius = dSawDiam / 2 local dCat1 = dRadius - dElev dEndDist = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) end end -- Eseguo i tagli local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dV - dSawThick) / ( nStep - 1) end for i = 1, nStep do local dOffs = ( i - 1) * dStep if vtN:getZ() < BD.NZ_MINA then dOffs = dOffs + dSawThick end local bOk, sErr, nMchId = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 0, BD.CUT_SIC, dOffs, dStartDist, dEndDist, nil, _b3Raw) if not bOk then return bOk, sErr end -- setto l'elevazione local sNotes = 'MaxElev=' .. EgtNumToString( 0, 1) .. ';' -- applico elevazione EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- tolgo eventuale step EgtSetMachiningParam( MCH_MP.STEP, 0) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end end -- in base all'elevazione calcolo l'impronta della lama local dUsedBladeLen = sqrt( ((dSawDiam / 2) * (dSawDiam / 2)) - ( ( (dSawDiam / 2) - dElev) * ( (dSawDiam / 2) - dElev))) -- controllo direzione taglio e se il minimo della feature sborda in coda if abs( vtN:getX()) < GEO.EPS_SMALL and abs( _b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then -- do avviso che la lama può sbordare nel pezzo successivo sWarn = 'Warning on mill side as blade : Cut machining can damage next piece' EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')') end end return true, sWarn end --------------------------------------------------------------------- local function MakeByChainOrSaw( Proc, nFacInd, rfFac, dH, dV, dElev, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFacesMaster, nBottomFace, nSurfInt, bIs3Faces) local bOrthoFaces local sWarn -- ottengo la distanza tra la fine del pezzo e il pezzo successivo local dDistToNextPiece = EgtGetInfo( _nRawId, 'BDST', 'd') or 5.4 if bIs3Faces then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd1, _, nFacInd2, _ = BL.GetFaceWithMostAdj( Proc.Id, _nPartId, bIs3Faces) if not nFacInd1 or nFacInd1 < 0 then if nFacInd1 == -1 then bOrthoFaces = nFacInd2 else local sErr = 'Error : MakeByChainOrSaw could not find reference face' EgtOutLog( sErr) return false, sErr end end else bOrthoFaces = bOrthoFacesMaster end if bOrthoFaces then -- ottengo le dimensioni del tunnel dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc) -- verifico la direzione -- se devo inserire il chamfer if _nChamfer > 0 then local nOk, sErr = MakeChamfer( Proc, bIs3Faces, vtOrtho, nSurfInt) if nOk < 0 then return false, sErr end end end -- Recupero le facce adiacenti alla principale (solo quelle esistenti) local vAdj = GetValidFacetAdjacencies( Proc.Id, nFacInd) if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' EgtOutLog( sErr) return false, sErr end EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3) -- Cerco una faccia adiacente alla principale sul lato più lungo local nFacAdj local dMaxLen = 0 for i = 1, #vAdj do local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) local dLen = dist( ptP1, ptP2) if dLen > dMaxLen then nFacAdj = vAdj[i] dMaxLen = dLen EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 3) end end if not nFacAdj then local sErr = 'Error : long adjacent face not found' EgtOutLog( sErr) return false, sErr end -- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacAdj, GDB_ID.ROOT) if abs( vtN * rfFac:getVersX()) > abs( vtN * rfFac:getVersY()) then dH, dV = dV, dH end -- Determino se estremi aperti o chiusi local bOpenStart = false local bOpenEnd = false local vtNS, vtNE -- se non ho la faccia di fondo ( che comporta essere una fessura) verifico se ho lati aperti if not nBottomFace then local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1] EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3) for j = 1, #vAdj2 do if vAdj2[j] == nFacInd then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == nFacInd do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- se è chiusa acquisisco vettore faccia tappo if not bOpenStart and vAdj2[i] >= 0 then _, vtNS = EgtSurfTmFacetCenter( Proc.Id, vAdj2[i], GDB_ID.ROOT) end -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == nFacInd do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) -- se è chiusa acquisisco vettore faccia tappo if not bOpenEnd and vAdj2[k] >= 0 then _, vtNE = EgtSurfTmFacetCenter( Proc.Id, vAdj2[k], GDB_ID.ROOT) end end end end -- Recupero il massimo affondamento possibile con la lama local dSawMaxDepth = 0 local sCutting = ML.FindCutting( 'HeadSide') if sCutting then local TI = GetToolInfoForMachining( sCutting) if TI then dSawMaxDepth = TI.dMaxDepth or dSawMaxDepth end end -- se lavorazione sulle teste e altezza trave supera il limite ( che causa collisione con la forcella) e direzione taglio lungo la Z -- e limite profondità BeamData è maggiore del taglio massimo lama, assegno il massimo affondamento pari al limite profondità del BeamData if bOpenStart and bOpenEnd and _bForceUseBlade and ( Proc.Head or Proc.Tail) and abs(rfFac:getVersY():getY()) > 0.866 and _b3Solid:getDimZ() > BD.MIN_DIM_HBEAM and dSawMaxDepth > BD.MAX_DIM_HTCUT_HBEAM then dSawMaxDepth = BD.MAX_DIM_HTCUT_HBEAM end -- Se entrambi gli estremi sono aperti e possibile, lavoro con la lama if bOpenStart and bOpenEnd and _bForceUseBlade and dElev < dSawMaxDepth + 10 * GEO.EPS_SMALL then -- Recupero la lavorazione di lama local sCutting = ML.FindCutting( 'HeadSide') if not sCutting then local sErr = 'Error : HeadSide (cutting) not found in library' EgtOutLog( sErr) return false, sErr, 'MNF' end -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 4 local TI = GetToolInfoForMachining( sCutting) if TI then dSawDiam = TI.dDiam or dSawDiam dSawThick = TI.dThick end if dSawThick > dV + 10 * GEO.EPS_SMALL then local sErr = 'Error : sawblade too thick' EgtOutLog( sErr) return false, sErr end -- Calcolo uso faccia local nFaceUse = BL.GetNearestOrthoOpposite( rfFac:getVersZ()) -- Eseguo i tagli local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dV - dSawThick) / ( nStep - 1) end for i = 1, nStep do local dOffs = ( i - 1) * dStep local bOk, sErr = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 0, BD.CUT_SIC, dOffs, 0, 0, nil, _b3Raw) if not bOk then return bOk, sErr end end -- in base all'elevazione calcolo l'impronta della lama local dUsedBladeLen = sqrt( ((dSawDiam / 2) * (dSawDiam / 2)) - ( ( (dSawDiam / 2) - dElev) * ( (dSawDiam / 2) - dElev))) -- controllo direzione taglio e se il minimo della feature sborda in coda if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( _b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then -- do avviso che la lama può sbordare nel pezzo successivo sWarn = 'Warning on saw cut : Cut machining can damage next piece' EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')') end -- altrimenti con sega a catena else -- Recupero la lavorazione local sSawing = ML.FindSawing( 'Sawing') if not sSawing then local sErr = 'Error : Sawing not found in library' EgtOutLog( sErr) return false, sErr, 'MNF' end -- Recupero i dati dell'utensile local dSawWidth = 75 local dSawThick = 8 local dMaxDepth = 200 local TI = GetToolInfoForMachining( sSawing) if TI then dSawWidth = TI.dDiam or dSawWidth dSawThick = TI.dThick or dSawThick dMaxDepth = TI.dMaxDepth or dMaxDepth end if dSawThick > dV + 10 * GEO.EPS_SMALL then local sErr = 'Error : chainsaw too thick' EgtOutLog( sErr) return false, sErr end local bGoFromHead = true -- se la lunghezza utensile non riesce ad arrivare sul fondo assegno la possibilità di lavorare di testa o di fianco if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then -- lavora di testa se è un tunnel, lavora di fianco se non è un tunnel bGoFromHead = not bOrthoFaces end -- se continuo a lavorare di testa if bGoFromHead then -- Calcolo uso faccia local nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ()) -- Calcolo normale faccia adiacente local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT) -- Verifico se necessarie più passate local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dV - dSawThick) / ( nStep - 1) end for i = 1, nStep do -- Applico la lavorazione con sega a catena a questa faccia local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = EgtAddMachining( sName, sSawing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- controllo direzione taglio e se il minimo della feature sborda in coda if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( _b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL then -- se ho lato partenza aperto e lato uscita chiuso e direzione lato chiuso è negativa, allora controllo uscita lama if bOpenStart and not bOpenEnd and vtNE:getX() < -0.99 and dDistToNextPiece < (dSawWidth / 2) then -- imposto accorciamento iniziale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, dDistToNextPiece - 1 - (dSawWidth / 2)) else -- imposto accorciamento iniziale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2)) end -- se ho lato uscita aperto e lato partenza chiuso e direzione lato partenza è negativa, allora controllo uscita lama if bOpenEnd and not bOpenStart and vtNS:getX() < -0.99 and dDistToNextPiece < (dSawWidth / 2) then -- imposto accorciamento finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.ENDADDLEN, dDistToNextPiece - 1 - (dSawWidth / 2)) else -- imposto accorciamento finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2)) end else -- imposto accorciamento iniziale/finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2)) end -- imposto angolo 3° asse rot e eventuale angolo suggerito per inizio EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1)) EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, rfFac:getVersZ())) -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se necessario, limito l'affondamento if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' dDepth = dMaxDepth - dElev EgtOutLog( sWarn) EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH '..EgtNumToString( dDepth, 1)) end -- imposto elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 2) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- impostazione alternativa angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2)) EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, rfFac:getVersZ())) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end -- altrimenti segacatena di fianco else -- verifico se posso farlo con la sega-catena local bMakeChainSaw, sSawing2, dMaxMat2, dSawCornerRad2, dSawThick2 = VerifyChainSaw( Proc, dDimMin, dDimMax) if bMakeChainSaw then -- Verifico se necessarie più passate local nStep = ceil( ( dDimMin - 10 * GEO.EPS_SMALL) / dSawThick2) local dStep = 0 if nStep > 1 then dStep = ( dDimMin - dSawThick2) / ( nStep - 1) end for i = 1, nStep do -- inserisco la lavorazione di sawing local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = EgtAddMachining( sName, sSawing2) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing2 EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nLundIdFace}}) -- imposto uso del lato faccia local nFaceUse -- se non è un tunnel a 4 facce if Proc.Fct < 4 then nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ(), vtN) -- altrimenti vero tunnel (solo sopra-sotto o davanti-dietro) else if abs( vtOrtho:getZ()) >= 0.707 then nFaceUse = MCH_MILL_FU.PARAL_DOWN else nFaceUse = MCH_MILL_FU.PARAL_BACK end end EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1)) EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho)) -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se non è un tunnel a 4 facce if Proc.Fct < 4 then -- imposto sempre massimo affondamento local dBoxDepth if nFaceUse == MCH_MILL_FU.PARAL_LEFT or nFaceUse == MCH_MILL_FU.PARAL_RIGHT then dBoxDepth = Proc.Box:getDimX() elseif nFaceUse == MCH_MILL_FU.PARAL_FRONT or nFaceUse == MCH_MILL_FU.PARAL_BACK then dBoxDepth = Proc.Box:getDimY() else dBoxDepth = Proc.Box:getDimZ() end EgtSetMachiningParam( MCH_MP.DEPTH, dBoxDepth) if dBoxDepth > dMaxMat2 then sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- sistemo inizio e fine if bOpenStart then EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) end if bOpenEnd then EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) end -- altrimenti vero tunnel (solo sopra-sotto o davanti-dietro) else -- se possibile aumento l'affondamento pari al raggio corner + 1 if dMaxMat2 > (dDepth + dSawCornerRad2 + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dDepth + dSawCornerRad2 + 1)) -- se massimo affondamento supera altezza fessura, uso massimo affondamento elseif dMaxMat2 > (dDepth + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dMaxMat2 - 1)) -- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning elseif dMaxMat2 < dDepth then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat2) sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end end if Q_MAX_ELEVATION and Q_MAX_ELEVATION > 10 then local sNotes = 'MaxElev=' .. EgtNumToString( Q_MAX_ELEVATION, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) end -- eseguo if not EgtApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- impostazione alternativa angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2)) EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho)) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end end end end return true, sWarn end --------------------------------------------------------------------- local function MakeAntiSplintBySaw( Proc, nFacet, vtN, nFacInd, bReduceDepth, bMillDown) -- Recupero la lavorazione di lama local sCutting = ML.FindCutting( 'HeadSide' .. EgtIf( bMillDown, '_H2', '')) if not sCutting then local sErr = 'Error : HeadSide (cutting) not found in library' EgtOutLog( sErr) return false, sErr end -- valuto l'angolo tra le due facce local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacet, GDB_ID.ROOT) local ptPm = (ptP1 + ptP2) / 2 -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta l'elevazione della faccia -- laterale sul punto medio della linea in comune local frFc = Frame3d( ptPm, vtN) local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) local dDepth = b3BoxLoc:getDimZ() or 0 -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 0 local dMaxDepth = 0 local TI = GetToolInfoForMachining( sCutting) if TI then dSawDiam = TI.dDiam or dSawDiam dSawThick = TI.dThick or dSawThick dMaxDepth = TI.dMaxDepth or dMaxDepth end local dExtraOffs = 0 -- se profondità superiore al massimo lama modifico elevazione if dDepth > dMaxDepth then dExtraOffs = dMaxDepth - dDepth end -- se devo ridurre l'affondamento if bReduceDepth then local dLimitDepth = 100 -- se ho ridotto l'affondamento ne riduco ulteriormente l'affondamento (50mm) if abs(dExtraOffs) > 0 then if dMaxDepth > dLimitDepth then dExtraOffs = dLimitDepth - dDepth end else if dDepth > dLimitDepth then dExtraOffs = dLimitDepth - dDepth else dExtraOffs = - (dDepth/2) end end end -- eseguo il taglio local bMadeASbyBld, sWarn, nIdMach = Fbs.MakeOne( Proc.Id, nFacet, sCutting, dSawDiam, vtN, nil, ( -0.5 + dExtraOffs), BD.CUT_SIC, 0, 0, 0, nil, _b3Raw) if bMadeASbyBld then sWarn = nil if abs(dExtraOffs) > 0 then sWarn = 'Warning : antisplint elevation is bigger than max tool depth' end end return bMadeASbyBld, sWarn, nIdMach, dSawThick, dMaxDepth, dAng end --------------------------------------------------------------------- local function MakePocket( Proc, ptPs, tvtN, nFaceRef, sMchFind, nUseRoughTool, sMasterPocket, dPrevFaceElev, tDimAndRef, dAng) -- calcolo l'elevazione dal punto medio local dElev local dLenIn, dLedOut = BL.GetPointDirDepth( _nPartId, ptPs, tvtN[2]) if dLenIn > 0 then dElev = dLenIn elseif dLedOut then dElev = dLedOut end local dCollSic = 2 * BD.COLL_SIC -- calcolo il diametro utensile local dDiamTool local dFaceDiamTool if tDimAndRef then -- prendo il valore dalle dimensioni minime delle facce dFaceDiamTool = min( tDimAndRef[2][1], tDimAndRef[2][2]) end -- se ho lavorazione precedente ricalcolo grossolanamente l'elevazione if dPrevFaceElev and dPrevFaceElev > 0 and dAng then dElev = dElev + ( sqrt( ( dElev * dElev) - ( dPrevFaceElev * dPrevFaceElev)) * sin(dAng)) elseif dPrevFaceElev and dPrevFaceElev > dElev then dElev = dPrevFaceElev end local sPocketing if sMasterPocket then sPocketing = sMasterPocket else sPocketing = ML.FindPocketing( sMchFind, dFaceDiamTool, dElev + dCollSic) end if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end dDiamTool = 20 local dMaxDepth = 0 local sTuuidPk if EgtMdbSetCurrMachining( sPocketing) then sTuuidPk = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then dMaxDepth = ( EgtTdbGetCurrToolMaxDepth() or dMaxDepth) dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM) end end -- se nome svuotatura non è stato ricalcolato, confronto il diametro utensile utilizzato con il minimo faccia e se non sono compatibili esco if sMasterPocket and dFaceDiamTool and dDiamTool >= dFaceDiamTool then return false, '', sTuuidPk, dDiamTool, dElev end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. 'F' .. tostring( nFaceRef) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, (nFaceRef)}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = MCH_SCC.ADIR_YM if AreSameVectorApprox( tvtN[2], Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( tvtN[2]:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( EgtGetCurrPhase()), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif tvtN[2]:getY() > 0.1 then nSCC = MCH_SCC.ADIR_YP end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta e non lavorata col truciolatore, imposto opportuno attacco if sMchFind == 'OpenPocket' and nUseRoughTool == 0 then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local sWarn if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxDepth - dElev) dElev = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true, sWarn, sTuuidPk, dDiamTool end --------------------------------------------------------------------- local function MachineByMill( Proc, tvtN, nBaseFace, nSideFace, ptPs, tDimAndRef, nDiffWidth, nUseRoughTool, dAng, sPocketing, sTuuidPk, dPrevFaceElev) local sMchFind = 'Pocket' local dAngLimit = 40 -- se feature é larga come trave imposto openpocket if nDiffWidth == 0 then sMchFind = 'OpenPocket' -- altrimenti non è passante disabilito il truciolatore else nUseRoughTool = 0 end -- se angolo tra le facce maggiore di 90, inserisco la contornatura o svuotatura del lato più corto if ( 180 + dAng) > 90.1 then -- calcolo l'angolo dalla verticale dall'angolo tra le due facce, perchè la feature potrebbe essere ruotata sulla Z locale della -- faccia principale e quindi la componente X del versore della faccia potrebbe dare un valore non coerente local dDiffFromSqAng = dAng + 90 -- se l'angolo dalla verticale si discosta di più dell'angolo limite impostato, utilizzo la svuotatura if cos( dDiffFromSqAng) < cos( dAngLimit) then -- applico la svuotatura local bOk, sWarn, sTuuidPk, dDiamTool, dElev = MakePocket( Proc, ptPs, tvtN, nSideFace, sMchFind, nUseRoughTool, sPocketing, dPrevFaceElev, tDimAndRef, dAng) if not bOk then -- se ho id utensile e diametro è perchè non ha fatto svuotatura perchè la faccia è più stretta del diametro utensile -- e provo ad inserire singola passata di testa if sTuuidPk and dDiamTool then -- recupero la lavorazione local sMilling = ML.FindMilling( 'Long2Cut', dElev, sTuuidPk) if not sMilling then local sErr = 'Error : Long2Cut not found in library' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione local sName = 'Prof_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nSideFace}}) -- imposto uso faccia local nFaceUse = BL.GetNearestOrthoOpposite(tvtN[1]) -- aggiusto i parametri EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH') EgtSetMachiningParam( MCH_MP.OFFSR, 0) EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, 1) -- imposto posizione braccio porta testa if tvtN[2]:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end else return false, sWarn end else return bOk, sWarn end -- altrimenti contornatura di fianco else local bOpenStart = false local bOpenEnd = false if nDiffWidth == 0 then bOpenStart = true bOpenEnd = true else local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, (nBaseFace))[1] for j = 1, #vAdj2 do if vAdj2[j] == nSideFace then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == nSideFace do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == nSideFace do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) end end end local sMilling if nUseRoughTool > 0 then sMilling = ML.FindMilling( 'Long2Cut', nil, sTuuidPk) else sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk) end if not sMilling then local sErr = 'Error : Long2Cut & LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dTDiam = 50 local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam end -- Calcolo uso faccia local nFaceUse = BL.GetNearestParalOpposite( tDimAndRef[1][3]:getVersZ()) -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, (nSideFace)}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- setto inversione del percorso EgtSetMachiningParam( MCH_MP.INVERT, true) -- setto a 0 eventuali offset EgtSetMachiningParam( MCH_MP.OFFSR, 0) -- calcolo elevazione per allungamenti attacchi con fianchi chiusi local dElev local dLenIn, dLedOut = BL.GetPointDirDepth( _nPartId, ptPs, tvtN[2]) if dLenIn > 0 then dElev = dLenIn elseif dLedOut then dElev = dLedOut end -- applico gli allungamenti o accorciamenti if bOpenStart then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, -dTDiam / 2) if dElev > 0 then EgtSetMachiningParam( MCH_MP.LIPERP, dElev) end end if bOpenEnd then EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.ENDADDLEN, -dTDiam / 2) if dElev > 0 then EgtSetMachiningParam( MCH_MP.LOPERP, dElev) end end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end return true end --------------------------------------------------------------------- local function GetUShapeWidth( Proc, nFacInd) -- Recupero le facce adiacenti alla principale (solo quelle esistenti) local vAdj = GetValidFacetAdjacencies( Proc.Id, nFacInd) -- se non ho facce adiacenti esco subito if not vAdj or #vAdj == 0 then return nil end -- Normale della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) -- Cerco le facce adiacenti alla principale con angolo concavo >= 90 local dWidth = 0 for i = 1, #vAdj do -- verifico l'angolo tra le facce ( esco se angolo compreso < 90) local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) if bAdj and dAng < -90 - 20 * GEO.EPS_ANG_SMALL then return nil end -- larghezza della faccia ortogonalmente alla adiacente local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT) local vtX = vtN2 ^ vtN local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2) local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef) if b3Ref then dWidth = max( dWidth, b3Ref:getDimY()) end end return dWidth end --------------------------------------------------------------------- local function MakeByPockets( Proc, sMchFindMaster, bIs3Faces, bOrthoFacesMaster, bMillDown) local nFirstMachId local bOrthoFaces local sWarn local sMchFind = 'Pocket' local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt local bBadMach = false if sMchFindMaster and #sMchFindMaster > 0 then sMchFind = sMchFindMaster end if bIs3Faces then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd, _, nFacInd2, _ = BL.GetFaceWithMostAdj( Proc.Id, _nPartId, bIs3Faces) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bOrthoFaces = nFacInd2 else local sErr = 'Error : MakeByPockets could not find reference face' EgtOutLog( sErr) return -1, sErr end end else bOrthoFaces = bOrthoFacesMaster end -- se è un tunnel verifico se è possibile usare la svuotatura if bOrthoFaces then -- ottengo le dimensioni del tunnel dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc) local nPathInt -- se devo inserire il chamfer if _nChamfer > 0 then local nOk, sErr = MakeChamfer( Proc, bIs3Faces, vtOrtho, nSurfInt) if nOk < 0 then return -1, sErr end end -- se smusso non è esclusivo if _nChamfer < 2 then -- ricalcolo se è lavorabile da sotto bMillDown = ( BD.DOWN_HEAD == true) -- verifico se può essere fatto con svuotatura local bMakePocket, sPocketing, dMaxDepth, dDiamTool = VerifyPocket( Proc, dDimMin, dDepth / 2, nil, sMchFind) local bMakePocketDn, sPocketingDn, dMaxDepthDn if bMillDown then bMakePocketDn, sPocketingDn, dMaxDepthDn = VerifyPocket( Proc, dDimMin, dDepth / 2, nil, sMchFind..'_H2') -- se è negativo inverto il versore e la faccia if vtOrtho:getZ() < 0 then vtOrtho = -vtOrtho EgtInvertSurf( nSurfInt) end end if bMakePocket then -- gestione svuotatura da un solo lato o anche dal lato opposto (se non verticale) -- estraggo il contorno dalla superfice per evitare i problemi con la svuotatura -- e assegno l'estrusione nPathInt = EgtExtractSurfTmLoops( nSurfInt, _nAddGrpId) EgtModifyCurveExtrusion( nPathInt, vtOrtho, GDB_RT.GLOB) -- se ho 3 facce, ciclo sulle entità del percorso per segnare quelle che sono aperte if bIs3Faces then SetOpenSide( nPathInt, vtOrtho) end -- variabili per parametri lavorazione local dMachDepth local dElev = 0 local bDoubleSide local bOneShot local bComplete = true -- imposto altezza aggiuntiva di elevazione local dCollSic = CalcCollisionSafety( vtOrtho) -- se possibile svuotare completamente da una sola parte if dMaxDepth > ( dDepth + BD.CUT_EXTRA + dCollSic) then dMachDepth = ( dDepth / 2) + BD.CUT_EXTRA dElev = dDepth + BD.CUT_EXTRA bOneShot = true else -- se direzione verso la verticale setto max affondamento possibile ed -- emetto messaggio di warning perché non lavorabile interamente if abs( vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic dElev = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) bComplete = false -- altrimenti setto il flag per fare la svuotatura da due parti else -- se l'altezza utensile riesce a lavorare completamente da due parti if dMaxDepth > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then dMachDepth = BD.CUT_EXTRA_MIN dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN -- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione else dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic dElev = dMaxDepth -- se molto inclinato rispetto alla normale della faccia di riferimento, lavorazione non idonea per probabili collisioni local vtRef = Y_AX() if abs( vtOrtho:getX()) > abs( vtOrtho:getY()) and abs( vtOrtho:getX()) > abs( vtOrtho:getZ()) then vtRef = X_AX() elseif abs( vtOrtho:getZ()) > abs( vtOrtho:getX()) and abs( vtOrtho:getZ()) > abs( vtOrtho:getY()) then vtRef = Z_AX() end if abs( vtOrtho * vtRef) < 0.5 then bBadMach = true end end bDoubleSide = true end end -- se lavorazione non idonea esco if bIs3Faces and bBadMach then local sErr = 'Impossible apply perpendicular pocketing: ' .. sPocketing return -2, sErr end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return -1, sErr end -- prendo l'id della prima lavorazione inserita if not nFirstMachId then nFirstMachId = nMchFId end -- aggiungo geometria EgtSetMachiningGeometry( {{ nPathInt, -1}}) -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) local bInvertMach if vtOrtho:getZ() < BD.NZ_MINA and abs(vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true -- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti elseif not bDoubleSide and vtOrtho:getY() > GEO.EPS_SMALL and not ( -(vtOrtho:getZ()) < BD.NZ_MINA) then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true end -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtOrtho, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtOrtho:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtOrtho:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- inverto il percorso di lavorazione per lavorare sinistro EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposto affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return -1, sErr end end -- se posso applicare la svuotatura sul lato opposto if bDoubleSide then -- se ho la lavorazione da sotto ricalcolo in base a questa lavorazione if bMakePocketDn then -- sPocketing = sPocketingDn -- dMaxDepth = dMaxDepthDn -- dDiamTool = dDiamToolDn -- se l'altezza utensile riesce a lavorare completamente da due parti if dMaxDepthDn > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then dMachDepth = BD.CUT_EXTRA_MIN dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN -- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione else dMachDepth = dMaxDepthDn - ( dDepth / 2) - dCollSic dElev = dMaxDepthDn bComplete = false sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end else -- se anche lavorando dal lato opposto non riesco a svuotare completamente la fessura -- setto i parametri affondamento ed emetto warning if dMaxDepth < ( dDepth / 2) + BD.CUT_EXTRA + dCollSic then dMachDepth = dMaxDepth - (dDepth / 2) - dCollSic dElev = dMaxDepth bComplete = false sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end end -- inserisco la lavorazione di svuotatura local sName = 'PockOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, EgtIf( bMakePocketDn, sPocketingDn, sPocketing)) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. EgtIf( bMakePocketDn, sPocketingDn, sPocketing) EgtOutLog( sErr) return -1, sErr end -- prendo l'id della prima lavorazione inserita if not nFirstMachId then nFirstMachId = nMchFId end -- aggiungo geometria EgtSetMachiningGeometry( {{ nPathInt, -1}}) -- imposto direzione utensile opposta EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameVectorApprox( vtOrtho, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtOrtho:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtOrtho:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- inverto il percorso di lavorazione per lavorare sinistro EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposo affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return -1, sErr end end end -- se non completo e U, cerco di lavorare anche la faccia di fondo (con il massimo affondamento possibile) if not bComplete and bIs3Faces then -- recupero la faccia da lavorare local nFacInd, dFacElev = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) local vtN local bPock3rd = false if nFacInd then vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) bPock3rd = ( vtN and ( vtN:getZ() >= BD.NZ_MINA or bMakePocketDn)) end if bPock3rd then -- recupero la distanza di sicurezza aggiuntiva local dFacCollSic = CalcCollisionSafety( vtN) -- scelgo se lavorare da sotto local bFacPocketDn = ( bMakePocketDn and vtN:getZ() < -0.174) -- inserisco la lavorazione di svuotatura local sName = EgtIf( bDoubleSide, 'Pock3rd_', 'Pock2nd_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, EgtIf( bFacPocketDn, sPocketingDn, sPocketing)) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return -1, sErr end -- prendo l'id della prima lavorazione inserita if not nFirstMachId then nFirstMachId = nMchFId end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YM else nSCC = MCH_SCC.ADIR_YP end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- inverto il percorso di lavorazione per lavorare sinistro EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposto affondamento local dDepth = 0 local dActMaxDepth = EgtIf( bFacPocketDn, dMaxDepthDn, dMaxDepth) if dActMaxDepth < dFacElev + dFacCollSic then dDepth = dActMaxDepth - ( dFacElev + dFacCollSic) end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- dichiaro non si generano sfridi per VMill local sNotes = 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return -1, sErr end end end end return 1, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId end end end return 0, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces end --------------------------------------------------------------------- local function ManageAntiSplintBySaw( Proc, bIsU, vtN, nFacInd, sWarn, bMillDown, bReduceDepth) local bMadeASbyBld = false local nNumFac = EgtIf( bIsU, 2, 1) local nPrefSide = 1 -- di preferenza il motore è meglio tenerlo sinistra -- se a U cerco di ottimizzare il lato di lavoro della lama if bIsU then if abs( vtN:getY()) > 0.996 then nPrefSide = 0 elseif abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then -- se X è negativa allora devo tenere il motore a destra if vtN:getX() < -(10 * GEO.EPS_SMALL) then nPrefSide = 2 end end end -- va eseguito sulle facce diverse dalla principale local nPrevSCC = nil for nFacet = 0, nNumFac do if nFacet ~= nFacInd then -- lavoro local dSawThick = 0 local dAng, sWarn2, nIdMach bMadeASbyBld, sWarn2, nIdMach, dSawThick, dMaxDepth, dAng = MakeAntiSplintBySaw( Proc, nFacet, vtN, nFacInd, bReduceDepth, bMillDown) if not bMadeASbyBld then return bMadeASbyBld, false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) -- se antischeggia veramente inserito perchè necessario if nIdMach then -- verifico se da invertire local bInvertMach = false if bIsU then if abs(vtN:getZ()) > 0.63 or abs(vtN:getY()) > 0.63 then -- if abs(vtN:getZ()) > 0.7 or abs(vtN:getY()) > 0.7 then -- prendo il vettore normale alla faccia local _, vtNFc = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) -- se superficie principale parallela al piano XZ if nPrefSide == 0 then -- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto) if vtNFc:getX() * vtNFc:getZ() > 0 then nPrefSide = 2 -- altrimenti facce inclinate // quindi mandrino a sinistra (per essere ancora verso l'alto) else nPrefSide = 1 end end -- se faccia verso X+ e mandrino verso sinistra if vtNFc:getX() > 0 and nPrefSide == 1 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end -- se faccia verso X- e mandrino verso destra elseif vtNFc:getX() < 0 and nPrefSide == 2 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end end end end -- eseguo inversione if bInvertMach then local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT) local nWS = EgtGetMachiningParam( MCH_MP.WORKSIDE) local nInvWS = EgtIf( nWS == MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT) local nFaceUse = EgtGetMachiningParam( MCH_MP.FACEUSE) local bOrtUp = ( nFaceUse >= MCH_MILL_FU.ORTUP_DOWN and nFaceUse <= MCH_MILL_FU.ORTUP_RIGHT) if not bOrtUp then -- assegno i parametri invertiti EgtSetMachiningParam( MCH_MP.WORKSIDE, nInvWS) EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert) -- setto l'offset pari allo spessore lama EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick) end end -- posizione del braccio : se primo taglio la recupero, altrimenti la imposto if not nPrevSCC then nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC) else EgtSetMachiningParam( MCH_MP.SCC, nPrevSCC) end -- rieseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nIdMach, false) return false, false, sErr end end end end return bMadeASbyBld, true, sWarn end --------------------------------------------------------------------- local function MakePathsOnExtremePoints( nIdPath, pPaths, dTDiam) local dLength = 2 if not nIdPath then return pPaths end -- prendo i punti iniziali e finali del percorso e i versori direzione local ptIni = EgtSP( nIdPath, GDB_RT.GLOB) local ptEnd = EgtEP( nIdPath, GDB_RT.GLOB) -- se distanza tra i punti è <= del diametro utensile esco if dist( ptIni, ptEnd) <= dTDiam then return pPaths end -- prendo i versori iniziali e finali local vtIni = EgtSV( nIdPath, GDB_RT.GLOB) local vtEnd = EgtEV( nIdPath, GDB_RT.GLOB) local ptIniP = ptIni local ptEndP = ptIniP + (vtIni * dLength) local nAuxId = EgtLine( _nAddGrpId, ptIniP, ptEndP, GDB_RT.GLOB) table.insert( pPaths, { nAuxId, 1, ptIniP}) ptIniP = ptEnd ptEndP = ptEnd - ( vtEnd * dLength) nAuxId = EgtLine( _nAddGrpId, ptIniP, ptEndP, GDB_RT.GLOB) table.insert( pPaths, { nAuxId, 2, ptIniP}) return pPaths end --------------------------------------------------------------------- local function MakeAntiSplintByMill( Proc, pPaths, nPathInt, vtN1, bDoubleSide, bOppoSide, sMilling, sMyWarn, dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId) local sMyWarn2 -- assegno lavorazioni ad ogni percorso for i = 1, #pPaths do local nIdPath = pPaths[i][1] local nSide = pPaths[i][2] -- modifico versore direzione EgtModifyCurveExtrusion( nIdPath, vtN1, GDB_RT.GLOB) local sName if bOppoSide then sName = 'AntiSplintOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) else sName = 'AntiSplint_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) end local nMchId = EgtAddMachining( sName, sMilling) if nMchId then -- aggiungo geometria EgtSetMachiningGeometry( {{ nIdPath, -1}}) if ( bOppoSide and nSide == 1) or ( not bOppoSide and nSide == 2) then -- imposto lato di lavoro destro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) else -- imposto lato di lavoro sinistro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) end local nSCC if bOppoSide then -- imposto direzione utensile opposta EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) -- imposto posizione braccio porta testa nSCC = MCH_SCC.ADIR_YM if not BD.C_SIMM then if AreSameVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end else local bInvertMach = false if not nPathInt then -- imposto posizione braccio porta testa nSCC = MCH_SCC.ADIR_YM if vtN1:getY() > 100 * GEO.EPS_ZERO then nSCC = MCH_SCC.ADIR_YP end else -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true -- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true end -- imposto posizione braccio porta testa nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( _nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- parametri attacco EgtSetMachiningParam( MCH_MP.LEADINTYPE, 1) -- allungo inizio EgtSetMachiningParam( MCH_MP.STARTADDLEN, 2) EgtSetMachiningParam( MCH_MP.LITANG, 10) EgtSetMachiningParam( MCH_MP.LIPERP, -5) -- parametri uscita EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 0) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) local dMachDepth = 0 local dExtraElev = 0 if bDoubleSide then dExtraElev = BL.GetFaceElevationFromPointDir( Proc.Id, _nPartId, pPaths[i][3], EgtIf( bOppoSide, -vtN1, vtN1)) - dMaxElevMaster end local dMaxElev = dMaxElevMaster + dExtraElev if ( dMaxElev + BD.CUT_EXTRA + dCollSic) > dMaxDepth then dMachDepth = dMaxDepth - ( dMaxElev + dCollSic) end -- setto se devo invertire il percorso local bInvert = CheckToInvert( nIdPath, true) if bOppoSide then EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) EgtSetMachiningParam( MCH_MP.INVERT, bInvert) else EgtSetMachiningParam( MCH_MP.DEPTH, (dMachDepth+dExtraDepth)) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertMach, not bInvert, bInvert)) end -- Note utente con dichiarazione nessuna generazione sfridi per Vmill local sUserNotes = 'VMRS=0;' -- aggiungo alle note massima elevazione sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn2 = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) else -- se ho la lavorazione di svuotatura riloco la lavorazione antischeggia prima di questa if nFirstMachId then EgtRelocateGlob( nMchId, nFirstMachId, GDB_IN.BEFORE) end end -- altrimenti lavorazione non applicata else _, sMyWarn2 = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end -- altrimenti non è stata inserita lavorazione else sMyWarn2 = 'warning adding machining ' .. sName .. '-' .. sMilling end end if sMyWarn2 and #sMyWarn2 > 0 then sMyWarn = sMyWarn .. '\n' .. sMyWarn2 end return sMyWarn end --------------------------------------------------------------------- local function ManageAntiSplintByMill( Proc, nFacInd, bMillDown, bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot, nFirstMachId) local sMyWarn = '' local pPaths = {} local nAuxId local sMilling -- recupero la lavorazione tenendo conto dell'elevazione local dCheckDepth if bDoubleSide then dCheckDepth = 0.5 * dDepth else if not nPathInt then dCheckDepth = BL.GetFaceElevation( Proc.Id, nFacInd) else dCheckDepth = dDepth end end sMilling = ML.FindMilling( 'AntiSplintMillCut' .. EgtIf( bMillDown and not bDoubleSide, '_H2', ''), dCheckDepth) or ML.FindMilling( 'AntiSplintMillCut' .. EgtIf( bMillDown and not bDoubleSide, '_H2', ''), 2/3 * dCheckDepth) or ML.FindMilling( 'AntiSplintMillCut' .. EgtIf( bMillDown and not bDoubleSide, '_H2', '')) if sMilling then local vtN1 local nFirstId, nNumId local dMaxElevMaster local dExtraDepth = 0 local dCollSic -- recupero i dati dell'utensile local dTDiam = 50 local dMaxDepth = 0 local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam dMaxDepth = TI.dMaxDepth or dMaxDepth end -- se non ho la faccia aggiunta if not nPathInt then -- ottengo i percorsi da cui estrapolare il percorso di antischeggia local tFacAdjMain = ChooseContour( Proc, nFacInd, false) local tPaths = {} -- se non trovato nessun angolo interno valido esco if #tFacAdjMain == 0 then return true, sMyWarn end -- prendo il primo versore _, vtN1 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) dCollSic = CalcCollisionSafety( vtN1) or 0 -- se direzione tende verso una delle alle 3 direzioni azzero l'altezza extra if abs( vtN1:getX()) > 0.7 or abs( vtN1:getY()) > 0.7 or abs( vtN1:getZ()) > 0.7 then dCollSic = 0 end -- se fresatura da sotto salto la lavorazione if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then local sErr = 'Error : milling from bottom ' EgtOutLog( sErr) return false, sErr end local ptIniPath local nMaxLen = 0 dMaxElevMaster = BL.GetFaceElevation( Proc.Id, nFacInd) -- ciclo tutta la tabella for i = 1, #tFacAdjMain do -- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo local ptP1, ptP2, dAng ptP1 = tFacAdjMain[i][3] ptP2 = tFacAdjMain[i][4] dAng = tFacAdjMain[i][5] if ( dAng < 0 and 180 + dAng >= 90 - 10 * GEO.EPS_SMALL) then -- creo la linea da P1 a P2 nAuxId = EgtLine( _nAddGrpId, ptP1, ptP2, GDB_RT.GLOB) table.insert( tPaths, nAuxId) -- prendo la lunghezza massima e il punto medio if tFacAdjMain[i][2] > nMaxLen then ptIniPath = ptP1 nMaxLen = tFacAdjMain[i][2] ptMidDist = ( ptP1 + ptP2) / 2 end end end -- costruisco il/i percorso/i nFirstId, nNumId = EgtCurveCompoByReorder( _nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB) local bOkPath = true for i = 1, nNumId do local nIdPath = nFirstId + i - 1 if EgtCurveIsClosed( nIdPath) then bOkPath = false end end -- se ho un percorso chiuso cancello tutto if not bOkPath then for i = 1, nNumId do local nIdPath = nFirstId + i - 1 EgtErase(nIdPath) end else -- creo percorsi antisplint dagli estremi dei percorsi di contorno trovati for i = 1, nNumId do local nIdPath = nFirstId + i - 1 pPaths = MakePathsOnExtremePoints( nIdPath, pPaths, dTDiam) end end -- alrimenti ho la faccia aggiunta else dCollSic = CalcCollisionSafety( vtOrtho) nFirstId = EgtCopyGlob( nPathInt, _nAddGrpId) nNumId = 1 -- calcolo elevazione dalla faccia trasversale aggiunta if bDoubleSide then dMaxElevMaster = 0.5 * dDepth else dMaxElevMaster = dDepth -- se la precedente svuotatura è stata fatta completamente in una sola volta -- valuto di nuovo se devo fare due passate o una sola if bOneShot then -- se non è possibile svuotare completamente da una sola parte if dMaxDepth <= ( dMaxElevMaster + BD.CUT_EXTRA + dCollSic) then bDoubleSide = true dMaxElevMaster = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) else dExtraDepth = dMaxElevMaster - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end -- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie else dExtraDepth = dMaxElevMaster - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end end vtN1 = Vector3d(vtOrtho) local bOkPath = SetOpenSide( nFirstId, vtOrtho, 2) -- se non ho un percorso chiuso estraggo i percorsi if bOkPath then -- creo percorsi antisplint dagli estremi dei percorsi di contorno trovati pPaths = MakePathsOnExtremePoints( nFirstId, pPaths, dTDiam) end EgtErase(nFirstId) end if #pPaths > 0 then sMyWarn = MakeAntiSplintByMill( Proc, pPaths, nPathInt, vtN1, bDoubleSide, false, sMilling, sMyWarn, dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId) if bDoubleSide then if bMillDown then local sMillingDn = ML.FindMilling( 'AntiSplintMillCut_H2', dCheckDepth) or ML.FindMilling( 'AntiSplintMillCut_H2', 2/3 * dCheckDepth) or ML.FindMilling( 'AntiSplintMillCut_H2') sMilling = sMillingDn -- controllo dati lavorazione local TI = GetToolInfoForMachining( sMilling) if TI then dTDiam = TI.dDiam or dTDiam dMaxDepth = TI.dMaxDepth or dMaxDepth end end -- se lavorazione valida if sMilling then sMyWarn = MakeAntiSplintByMill( Proc, pPaths, nPathInt, vtN1, bDoubleSide, true, sMilling, sMyWarn, dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId) else sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' clean corner milling/tool not found in library' end end -- altrimenti non c'è il percorso else sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' impossible make clean corner path' end -- altrimenti non è stata trovata lavorazione else sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' clean corner milling/tool not found in library' end if #sMyWarn > 0 then EgtOutLog( sMyWarn) end return true, sMyWarn end --------------------------------------------------------------------- local function MakeBySideMill( Proc, ptC, vtN, nFacInd, dMaxMat, dFacElev, dToolDiam, bHeadDir) local dH, dV -- recupero la larghezza della faccia perpendicolarmente alle altre 2 local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( nFacInd == 0, 1, 0), GDB_ID.ROOT) local vtX = vtN2 ^ vtN local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2) local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef) if b3Ref then dV = b3Ref:getDimY() dH = b3Ref:getDimX() end -- se lavorazione da sotto e lunga, va divisa in due metà local bHalf = ( vtN:getZ() < -0.5 and dH > ( BD.MAX_LEN_BH_FROM_BOTTOM or 200)) -- inserisco la lavorazione di fresatura local sName = 'BHMill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end sName = EgtGetName( nMchFId) -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso del lato faccia EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bHeadDir, MCH_MILL_FU.PARAL_LEFT, MCH_MILL_FU.PARAL_RIGHT)) -- calcolo step effettivo ed elevazione local dVcalc = dV - dMaxMat local dStep = EgtMdbGetCurrMachiningParam( MCH_MP.STEP) or dMaxMat local nStep = ceil( dVcalc / dStep) if vtN:getZ() < - 0.5 and ( nStep % 2) == 0 then nStep = nStep + 1 end dStep = dVcalc / nStep + 0.1 EgtSetMachiningParam( MCH_MP.STEP, dStep) -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dVcalc + dStep, 2) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- attacchi e uscite if vtN:getZ() > -0.5 then EgtSetMachiningParam( MCH_MP.LITANG, 0) EgtSetMachiningParam( MCH_MP.LIPERP, dFacElev + BD.CUT_SIC) else EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + BD.CUT_SIC) EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR) EgtSetMachiningParam( MCH_MP.LOTANG, 0) EgtSetMachiningParam( MCH_MP.LOPERP, dFacElev + BD.COLL_SIC) if bHalf then EgtSetMachiningParam( MCH_MP.ENDADDLEN, - dH / 2) end end -- tipo passate multiple local nStepType = EgtIf( ( Proc.HeadDir and vtN:getY() < -0.5) or ( not Proc.HeadDir and vtN:getY() > 0.5), MCH_MILL_ST.ONEWAY, MCH_MILL_ST.ZIGZAG) EgtSetMachiningParam( MCH_MP.STEPTYPE, nStepType) -- imposto posizione braccio porta testa local nSCC = EgtIf( ( vtN:getY() > 0.5 or ( bHeadDir and vtN:getZ() > 0.5 ) or ( not bHeadDir and vtN:getZ() < -0.5)), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- se divisa in due metà if bHalf then local nMchFNId = EgtCopyMachining( sName .. '_2', sName) if not nMchFNId then local sErr = 'Error copying machining ' .. sName EgtOutLog( sErr) return false, sErr end -- inverto direzione e lato di lavoro e direzione ausiliaria local bInvert = EgtGetMachiningParam( MCH_MP.INVERT) EgtSetMachiningParam( MCH_MP.INVERT, not bInvert) local nWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE) EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( nWorkSide == MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) EgtSetMachiningParam( MCH_MP.SCC, EgtIf( nSCC == MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFNId, false) return false, sErr end end return true, '' end --------------------------------------------------------------------- local function MakeSpecialThreeFaces( Proc) local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) -- entrambe le facce non devono essere orientate verso il basso local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) -- se orientata verso il basso, verifico l'alternativa if vtN:getZ() < BD.NZ_MINA and vtN2:getZ() < BD.NZ_MINA then local sErr = 'Error : special LapJoint from bottom impossible' EgtOutLog( sErr) return false, sErr end local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) local rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd2, GDB_ID.ROOT) -- eventuali tagli preliminari do local bOk, sErr = MakePreCuts( Proc) if not bOk then return false, sErr end end -- Recupero la lavorazione di fresa local sMilling = ML.FindMilling( 'LongSmallCut') if not sMilling then local sErr = 'Error : LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr end -- Recupero la lavorazione di svuotatura local sMchFind = 'Pocket' -- se forzato uso truciolatore if Q_USE_ROUGH_TOOL == 1 then sMchFind = 'OpenPocket' end local dDiam = min( dH, dV) local dDiam2 = min( dH2, dV2) local dCollSic = 2 * BD.COLL_SIC local dCollSic2 = 2 * BD.COLL_SIC if abs( vtN:getX()) > 0.7 or abs( vtN:getY()) > 0.7 or abs( vtN:getZ()) > 0.7 then dCollSic = 0 end if abs( vtN2:getX()) > 0.7 or abs( vtN2:getY()) > 0.7 or abs( vtN2:getZ()) > 0.7 then dCollSic2 = 0 end local sPocketing = ML.FindPocketing( sMchFind, dDiam2, dFacElev2 + dCollSic2) local nPockFace = nFacInd2 -- se non trova una svuotatura adatta provo ad assegnarla all'altra faccia if not sPocketing then dDiam, dDiam2 = dDiam2, dDiam dCollSic, dCollSic2 = dCollSic2, dCollSic nFacInd, nFacInd2 = nFacInd2, nFacInd dH, dH2 = dH2, dH dV, dV2 = dV2, dV dFacElev, dFacElev2 = dFacElev2, dFacElev rfFac, rfFac2 = rfFac2, rfFac vtN, vtN2 = vtN2, vtN -- prendo a riferimento la seconda faccia per la svuotatura sPocketing = ML.FindPocketing( sMchFind, dDiam2, dFacElev2 + dCollSic2) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end end -- provo con contornatura local dDiamTool = 20 -- verifico se forma ad L local _, bIsL = TestUL( Proc) if bIsL then local bOk, sWarn bOk, sWarn, _ = MakeByMill( Proc, nFacInd, rfFac, dH, dV, dFacElev, dCollSic, true, sMilling, nFacInd2, dFacElev2) if not bOk then return bOk, sWarn end else local sErr = 'Error : Impossible mill special LapJoint' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nPockFace}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) -- imposto posizione braccio porta testa if vtN:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- imposto elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dFacElev2, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- se abilitato dal parametro Q inserisco foro sullo spigolo if Q_BORE_ON_CORNER == 1 then local bOk, sWarn = MakeDrillOnCorner( Proc, 0, dDiamTool, true) if not bOk then return false, sWarn end -- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura elseif Q_BORE_ON_CORNER == 2 then local bOk, sWarn = MakeSharpCleanCorner( Proc, 0, dDiamTool) if not bOk then return false, sWarn end end return true, '' end --------------------------------------------------------------------- local function MakeByChainsaw( Proc, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace) -- verifico se posso farlo con la sega-catena local bMakeChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick = VerifyChainSaw( Proc, dDimMin, dDimMax) if bMakeChainSaw then -- Verifico se necessarie più passate local nStep = ceil( ( dDimMin - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dDimMin - dSawThick) / ( nStep - 1) end for i = 1, nStep do -- inserisco la lavorazione di sawing local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = EgtAddMachining( sName, sSawing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nLundIdFace}}) -- imposto uso del lato faccia -- al momento, dato che la fessura è passante da parte a parte, gestisco solo la lavorazione -- dall'alto e di fronte (da dietro è disabilitata perchè ho exracorsa con la FAST). -- Questa feature non è applicata su facce di testa e quindi non controllo l'entrata in X if abs(vtOrtho:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) else EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_BACK) end local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nLundIdFace, GDB_ID.ROOT) -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1)) EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho)) -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se possibile aumento l'affondamento pari al raggio corner + 1 if dMaxMat > (dDepth + dSawCornerRad + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dDepth + dSawCornerRad + 1)) -- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning elseif dMaxMat < dDepth then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat) sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- eseguo if not EgtApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2)) EgtSetMachiningParam( MCH_MP.INITANGS, GetChainSawInitAngs( vtN, vtOrtho)) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end end return true end --------------------------------------------------------------------- local function MakeSidePocketings( Proc, nFacInd, rfFac, dH, dV, vtN, dFacElev, bSpecialMillOnSide, nBottomFace, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide, bSinglePart, bIsU, bIsL, dDiam, bMillDown, bMillUp, sMchFind, sMchFindBackUp) local bTryWithBlades = true local nOk, bOk, sStat, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces, nSurfInt if bSpecialMillOnSide then -- eseguo bOk, sWarn = MakeByMillAsSaw( Proc, nFacInd, rfFac, dH, dV, dFacElev, nBottomFace, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide) if bOk then return 1, true, sWarn end end -- se feature 16 o 17 e se forzata lama provo prima con questa e poi con la fresa if ( Proc.Prc == 16 or Proc.Prc == 17) and _bForceUseBlade then -- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame if bTryWithBlades and _nChamfer < 2 then -- anche su macchine con testa da sotto, la sega a catena è solo da sopra if vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and nFacInd2 then nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) end -- eseguo (come 3 faces) bOk, sWarn, sStat = MakeByChainOrSaw( Proc, nFacInd, rfFac, dH, dV, dFacElev, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces, nBottomFace, nSurfInt, true) if not bOk then -- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e -- se non è possibile allora provo in seguito con lama o segacatena -- o passare subito dalla lavorazione con lama/sega catena if Proc.Fct == 3 and bIsU then -- lavoro con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, _, _, _, _, _, _, _, bOrthoFaces = MakeByPockets( Proc, sMyMchFind, true, nil, bMillDown) -- se lavorazione non idonee ( asse della feature troppo inclinato e impossibile lavorare completamente da due parti) if nOk == -2 then if not sMchFind then sMchFind = sMchFindBackUp end sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return 1, false, sErr end elseif nOk < 0 then return 1, false, sErr elseif nOk == 0 then if sStat == 'MNF' then sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return 1, false, sErr end else return 1, bOk, sWarn end else bOk = true return 1, bOk, sErr end else sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return 1, false, sErr end end else return 1, bOk, sWarn end else -- se devo inserire il chamfer if ( ( Proc.Fct == 3 and bIsU) or (Proc.Fct == 2 and bIsL)) and _nChamfer > 0 then -- ottengo le dimensioni dello pseudotunnel local _, _, _, vtOrtho, _, nSurfInt = GetTunnelDimension( Proc) local nOk, sErr = MakeChamfer( Proc, true, vtOrtho, nSurfInt) if nOk < 0 then return 1, false, sErr end end bOk = true return 1, bOk, sWarn end else -- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo -- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa -- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z -- 2021.07.16 Per poter eseguire antischeggia di lama su feature che non sono passanti da faccia a faccia -- ma che sono su un angolo (coinvolgono 2 facce contigue) è stato modificato il confronto in: -- esegue antischeggia di lama se forma U o L con feature passante in Y o Z, oppure se feature a furma U e con 3 facce oppore a forma a L e con 2 facce local bPassThrou = ( Proc.Box:getDimY() > _b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > _b3Raw:getDimZ() - 1) local bPassEdge = ((( bIsU and Proc.Fct == 3) or ( bIsL and Proc.Fct == 2)) and bSinglePart and Proc.Box:getDimX() < 0.9 * _b3Raw:getDimX()) if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 1 and (( bIsU or bIsL) and ( bPassThrou or bPassEdge)) then local bOk local bSawDown = ( bMillDown and not bMillUp) _, bOk, sWarn = ManageAntiSplintBySaw( Proc, bIsU, vtN, nFacInd, sWarn, bSawDown, true) if not bOk then return 1, false, sWarn end end -- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e -- se non è possibile allora provo in seguito con lama o segacatena -- o passare subito dalla lavorazione con lama/sega catena if _bTrySidePocketAtFirst and Proc.Fct == 3 and bIsU then -- lavoro con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' local dDiamTool = 100 local nPathInt, nSurfInt, bOneShot, nFirstMachId, bDoubleSide nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces = MakeByPockets( Proc, sMyMchFind, true, nil, bMillDown) if nOk == -2 then if not sMchFind then sMchFind = sMchFindBackUp end sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr2 = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr2) return 1, false, sErr2 end bTryWithBlades = false sWarn = sErr elseif nOk < 0 then return 1, false, sErr elseif nOk > 0 then bTryWithBlades = false sWarn = sErr -- se ho antischeggia con fresa le inserisco if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 2 then local _, sWarn2 = ManageAntiSplintByMill( Proc, nFacInd, bMillDown, bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot, nFirstMachId) sWarn = FormatWarning(sWarn, sWarn2) end -- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola if Q_CONTOUR_SMALL_TOOL > 0 then local bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nFacInd, dDiamTool, Q_CONTOUR_SMALL_TOOL, bMillDown, bDoubleSide, vtOrtho, nPathInt, nSurfInt, dDepth, bOneShotm) if not bOk then return 1, false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) end end bOk = true end -- 03/09/2020 da conferma di Fabio Squaratti: Per ora solo sulla feature 016: -- se ha fallito la fresatura (qua sopra) allora di default ( anche se il flag Q della lama è disattivato) prima provo la lama if Proc.Prc == 16 then _bForceUseBlade = true end -- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame if bTryWithBlades and _nChamfer < 2 then -- anche su macchine con testa da sotto, la sega a catena è solo da sopra if vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and nFacInd2 then nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) end -- eseguo (non 3 faces) bOk, sWarn, sStat = MakeByChainOrSaw( Proc, nFacInd, rfFac, dH, dV, dFacElev, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces, nBottomFace, nSurfInt) if not bOk and sStat == 'MNF' then _, sPocketing = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, nil, sMchFind) if sPocketing then sWarn = '' else local sErr2 = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr2) return 1, false, sErr2 end else -- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola if Q_CONTOUR_SMALL_TOOL > 0 then local bOk, sWarn2 bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nFacInd, 100, Q_CONTOUR_SMALL_TOOL, bMillDown) if not bOk then return 1, false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) end return 1, bOk, sWarn end -- altrimenti verifico se ho già svuotato dal fianco, se si esco else -- se non ho annullato la/le svuotatura/e dal fianco if nOk ~= -2 then return 1, bOk, sWarn end end end return 0, true, '' end --------------------------------------------------------------------- local function MakePocketingOrMilling( Proc, nFacInd, nFacInd2, bSinglePart, dFacElev, dFacElev2) -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- verifico se forma ad U o L local bIsU, bIsL = TestUL( Proc) local bUseOtherFace -- se orientata verso il basso e non c'è testa da sotto, verifico l'alternativa if vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD and nFacInd2 then ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev bUseOtherFace = true end -- verifico non sia orientata verso il basso o ci sia una testa dal basso local bFaceDown = ( vtN:getZ() < BD.NZ_MINA) if bFaceDown and not BD.DOWN_HEAD then local sErr = 'Error : LapJoint from bottom impossible' EgtOutLog( sErr) return false, sErr end -- se forma a L e la componente in X è maggiore di 60° e non in testa allora verifico se posso utilizzare la faccia secondaria if bIsL and abs( vtN:getX()) > 0.866 and ( Proc.Box:getMax():getX() < _b3Solid:getMax():getX() - 10 or vtN:getX() < 0) and ( not Proc.Tail or vtN:getX() > 0) then -- se non ho scambiato la faccia if not bUseOtherFace then if nFacInd2 then nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- altrimenti cerco la faccia secondaria per adiacenza alla principale else -- Cerco una faccia adiacente alla principale sul lato lungo local nFacAdj, sErr = GetFaceAdj( Proc, nFacInd, dH, dV) if nFacAdj < 0 then EgtOutLog( sErr) return false, sErr end nFacInd = nFacAdj dFacElev = BL.GetFaceElevation( Proc.Id, nFacInd) ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) end -- altrimenti se ho già cambiato faccia do errore per impossibilità di lavorazione else local sErr = 'Error : impossible to machine by side angle too big that cause collision' EgtOutLog( sErr) return false, sErr end end -- eventuali tagli preliminari do local bOk, sErr = MakePreCuts( Proc) if not bOk then return false, sErr end end -- imposto altezza aggiuntiva di elevazione local dCollSic = CalcCollisionSafety( vtN) -- abilitazione lavorazione da sotto local bMillUp = ( BD.DOWN_HEAD and vtN:getZ() > -0.259) local bMillDown = ( BD.DOWN_HEAD and vtN:getZ() < 0.342) -- settaggio voluto da Alessandro/Fabio (per fare angoli con fresa piccola) local sMchFind = 'Pocket' local dDiam = min( dH, dV) local bTailOnSide = ( Proc.Box:getMin():getX() - _b3Solid:getMin():getX() < 0.1 and not Proc.Tail) if ( Proc.Fct == 1) or (( Proc.Fct == 2 or Proc.Fct == 3) and bIsL) or ((( Proc.Fct == 3 and bIsU) or ( Proc.Fct == 4 and not bTailOnSide)) and bSinglePart) then sMchFind = 'OpenPocket' if bIsU then dDiam = GetUShapeWidth( Proc, nFacInd) or dDiam elseif Proc.Fct == 4 then -- per rifinire gli angoli premio utensile diam 25 o da BD dDiam = min( dDiam, BD.MAXDIAM_POCK_CORNER or 30) elseif Proc.Fct == 3 and bIsL then -- per rifinire gli angoli premio utensile diam 25 o da BD dDiam = min( 2 * dDiam, BD.MAXDIAM_POCK_CORNER or 30) else dDiam = 2 * dDiam end end sMchFindBackUp = sMchFind local nUseRoughTool = EgtIf( bSinglePart, 0, 1) -- 04/08/2020 Se settato parametro uso truciolatore (parametro Q), non si devono prendere altre frese, si da errore (Fabio) -- Questa opzione si scontra facilmente con altre interpretazioni dello stasso parametro Q (per tornare indietro bNewCheck = false) local bNewCheck = true -- se processo 20 e non sto usando il truciolatore if bNewCheck and Proc.Prc == 20 and nUseRoughTool == 0 then -- verifico se forzato uso truciolatore if Q_USE_ROUGH_TOOL and Q_USE_ROUGH_TOOL ~= 0 then sMchFind = 'OpenPocket' nUseRoughTool = 1 end end -- 03/12/2020 aggiunto controllo su feature 30 senza uso truciolatore if bNewCheck and Proc.Prc == 30 and nUseRoughTool == 0 then -- verifico se forzato uso truciolatore if Q_SIDE_ROUGH_TOOL and Q_SIDE_ROUGH_TOOL ~= 0 then sMchFind = 'OpenPocket' nUseRoughTool = 1 end end -- se processo 20 e non sto usando il truciolatore if Proc.Prc == 20 and nUseRoughTool == 0 then if Q_USE_ROUGH_TOOL and Q_USE_ROUGH_TOOL ~= 0 then sMchFind = 'OpenPocket' nUseRoughTool = 1 end end -- se da sotto, imposto massima lunghezza secondo la direzione local dMaxTotLen if bMillDown and BD.GetBottomToolMaxTotLen then dMaxTotLen = BD.GetBottomToolMaxTotLen( vtN) end -- ricerca lavorazione local sPocketing local _, sMyPocketing, dMyTMaxDepth, _ = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind .. EgtIf( bMillDown, '_H2', '')) if not sMyPocketing and bMillUp then _, sMyPocketing, dMyTMaxDepth, _ = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind) bMillDown = false end --local sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, dFacElev + dCollSic, dMaxTotLen) --if not sMyPocketing then -- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, nil, dMaxTotLen) --end --if not sMyPocketing and bMillUp then -- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam, dFacElev + dCollSic) -- if not sMyPocketing then -- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam) -- end -- bMillDown = false --end if sMyPocketing and ( dMyTMaxDepth > dFacElev + dCollSic - 10 * GEO.EPS_SMALL or ( dMyTMaxDepth > 0.8 * dFacElev + dCollSic and not bIsU) or ( bIsL and nUseRoughTool == 0)) then sPocketing = sMyPocketing end if bMillDown then sMchFind = sMchFind .. '_H2' end -- 2021.09.16 Richiesta di Fabio Squaratti per lavorazione "Lamello": -- se ho attiva questo tipo di lavorazione (delle fresature) e una di queste feature: L016, L030, L032, L039 -- verifico se sono compatibili con questa lavorazione forma a U e larga più dell'altezza tagliente e profondità compatibile con local bSpecialMillOnSide local dThickMillOnSide = 0 local sMillingOnSide local dToolDiamOnSide = 0 local dMaxDepthOnSide = 0 if ( Proc.Prc == 16 or Proc.Prc == 30 or Proc.Prc == 32 or Proc.Prc == 39) then -- verifico se ho una gola con 3 facce ed eventualmente delle facce terminali: -- faccio una copia della superfice ed elimino le facce che hanno dimensione X < 1 e le facce risultanti devono essere una U local nTestId = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL if nTestId then local bNewIsU local bExit local nFaces = EgtSurfTmFacetCount( nTestId) while not bExit and nFaces >= 3 do local bDeleteFace local nInt = 0 while not bDeleteFace and nInt < nFaces do nInt = nInt + 1 local b3Facet = EgtSurfTmGetFacetBBoxGlob( nTestId, nInt - 1, GDB_BB.STANDARD) local vtN = EgtSurfTmFacetNormVersor( nTestId, nInt - 1, GDB_ID.ROOT) -- se dimensione faccia sulla X if b3Facet:getDimX() < 1 or abs( vtN:getX()) > 0.1 then EgtSurfTmRemoveFacet( nTestId, nInt - 1) bDeleteFace = true end end nFaces = EgtSurfTmFacetCount( nTestId) -- se non ho cancellato una faccia faccio il test per forma ad U if not bDeleteFace then -- ottengo il numero di facce rimanenti bNewIsU = ( nFaces == 3 and not TestElleShape3( nTestId, true)) bExit = true end end -- verifico che la componente x della faccia 0 deve essere nulla local vtN1 = EgtSurfTmFacetNormVersor( nTestId, 0, GDB_ID.ROOT) if bNewIsU and abs( vtN1:getX()) > 0.01 then bNewIsU = false end -- cancello la copia del percorso EgtErase( nTestId) if bNewIsU and ( not BD.MIN_LEN_LAMELLO or ( Proc.TotBox and Proc.TotBox:getDimX() > BD.MIN_LEN_LAMELLO) or ( not Proc.TotBox and Proc.Box:getDimX() > BD.MIN_LEN_LAMELLO)) then -- recupero la lavorazione if BD.DOWN_HEAD and vtN:getZ() < BD.NZ_MINA then sMillingOnSide = ML.FindMilling( 'SideMillAsBlade_H2') else sMillingOnSide = ML.FindMilling( 'SideMillAsBlade') end if sMillingOnSide then -- recupero i dati dell'utensile local dToolLength = 0 local TI = GetToolInfoForMachining( sMillingOnSide) if TI then dToolLength = TI.dLength or dToolLength dToolDiamOnSide = TI.dDiam or dToolDiamOnSide dThickMillOnSide = TI.dMaxMat or dThickMillOnSide dMaxDepthOnSide = TI.dSideDepth or dMaxDepthOnSide end -- 2021.09.17 Su conferma di Fabio Squaratti, se la gola è più stretta dell'utensile o la profondità della gole è maggiore -- del valore parametro SIDEDEPTH (preso dalle note utente dell'utensile) allora si prosegue come se non fosse abilitata -- questo tipo di lavorazione SideMillAsBlade if dDiam > dThickMillOnSide - 10 * GEO.EPS_SMALL and dFacElev < dMaxDepthOnSide + 10 * GEO.EPS_SMALL then bSpecialMillOnSide = true -- disabilito eventuale svuotatura sPocketing = nil end end end end end -- se feature 16 e forzata lama e forma ad U, annulla la svuotatura if Proc.Prc == 16 and _bForceUseBlade and Proc.Fct == 3 and bIsU then sPocketing = nil end -- se lavorazione fresa come lama disabilito eventuale antischegggia if bSpecialMillOnSide then Q_ANTISPLINT_TYPE = 0 end -- se non trova una svuotatura adatta if not sPocketing then -- se forma a L provo con contornatura if bIsL and not bSpecialMillOnSide then -- se smusso non è esclusivo if _nChamfer < 2 then return MakeByMill( Proc, nFacInd, rfFac, dH, dV, dFacElev, dCollSic) end -- altrimenti, in base alla forma, provo con svuotature di fianco o con la sega a catena o lama else local stat, bOk, sWarn = MakeSidePocketings( Proc, nFacInd, rfFac, dH, dV, vtN, dFacElev, bSpecialMillOnSide, nBottomFace, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide, bSinglePart, bIsU, bIsL, dDiam, bMillDown, bMillUp, sMchFind, sMchFindBackUp) if stat == 1 then return bOk, sWarn end end else -- se devo inserire il chamfer if ( ( Proc.Fct == 3 and bIsU) or (Proc.Fct == 2 and bIsL)) and _nChamfer > 0 then -- ottengo le dimensioni dello pseudotunnel local _, _, _, vtOrtho, _, nSurfInt = GetTunnelDimension( Proc) local nOk, sErr = MakeChamfer( Proc, true, vtOrtho, nSurfInt) if nOk < 0 then return false, sErr end end end -- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo -- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa -- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z -- 2021.07.16 Per poter eseguire antischeggia di lama su feature che non sono passanti da faccia a faccia -- ma che sono su un angolo (coinvolgono 2 facce contigue) è stato modificato il confronto in: -- esegue antischeggia di lama se forma U o L con feature passante in Y o Z, oppure se feature a furma U e con 3 facce oppore a forma a L e con 2 facce local bMadeASbyBld = false local bPassThrou = ( Proc.Box:getDimY() > _b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > _b3Raw:getDimZ() - 1) local bPassEdge = ((( bIsU and Proc.Fct == 3) or ( bIsL and Proc.Fct == 2)) and bSinglePart and Proc.Box:getDimX() < 0.9 * _b3Raw:getDimX()) if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 1 and (( bIsU or bIsL) and ( bPassThrou or bPassEdge)) then local bOk local bSawDown = ( bMillDown and not bMillUp) bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, bIsU, vtN, nFacInd, sWarn, bSawDown) if not bOk then return false, sWarn end end if _nChamfer < 2 and Q_ANTISPLINT_TYPE == 2 then local bOk, sWarn2 bOk, sWarn2 = ManageAntiSplintByMill( Proc, nFacInd, bMillDown) if not bOk then return false, sWarn2 end end -- se smusso non esclusivo if _nChamfer < 2 then -- eseguo la svuotatura della faccia principale, mi restituisce id utensile, il diametro utensile per il foro opzionale local tvtNx = {} tvtNx[2] = vtN local bOk, sWarn2, sTuuidPk, dDiamTool bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, ptC, tvtNx, nFacInd, sMchFind, nUseRoughTool, sPocketing, dFacElev + dCollSic) if not bOk then return false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) -- se ho più di 3 facce e non di forma ad u oppure ho 3 facce e di forma ad u -- e non sono stati inseriti antischeggia di lama -- controllo se c'è una faccia non ortogonale alla principale e la lavoro con una contornatura o svuotatura if ( ( Proc.Fct > 3 and not bIsU) or ( Proc.Fct == 3 and bIsU)) and not bMadeASbyBld then -- Recupero le facce adiacenti alla principale (solo quelle esistenti) local vAdj = GetValidFacetAdjacencies( Proc.Id, nFacInd) if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' EgtOutLog( sErr) return false, sErr end -- Cerco una faccia adiacente alla principale con angolo > 90 local tDimAndRef = {} tvtNx = {} tvtNx[1] = vtN tDimAndRef[1] = {dH, dV, rfFac} for i = 1, #vAdj do local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) if bAdj and dAng < 0 and 180 + dAng > 90.1 then local rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, vAdj[i], GDB_ID.ROOT) _, tvtNx[2] = EgtSurfTmFacetCenter( Proc.Id, vAdj[i], GDB_ID.ROOT) tDimAndRef[2] = {dH2, dV2, rfFac2} local ptPs = ( ptP1 + ptP2) / 2 local bOk, sWarn2 = MachineByMill( Proc, tvtNx, nFacInd, vAdj[i], ptPs, tDimAndRef, EgtIf( ( Proc.Fct == 3 and bIsU), 0, 2), nUseRoughTool, dAng, sPocketing, sTuuidPk, dFacElev) if not bOk then return bOk, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) end end end -- se abilitato dal parametro Q inserisco foro sullo spigolo if Q_BORE_ON_CORNER == 1 then local bOk, sWarn2 bOk, sWarn2 = MakeDrillOnCorner( Proc, nFacInd, dDiamTool) if not bOk then return false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) -- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura elseif Q_BORE_ON_CORNER == 2 then local bOk, sWarn2 bOk, sWarn2 = MakeSharpCleanCorner( Proc, nFacInd, dDiamTool) if not bOk then return false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) -- altrimenti se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola elseif Q_CONTOUR_SMALL_TOOL > 0 then local bOk, sWarn2 bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nFacInd, dDiamTool, Q_CONTOUR_SMALL_TOOL, bMillDown) if not bOk then return false, sWarn2 end sWarn = FormatWarning(sWarn, sWarn2) end end return true, '' end --------------------------------------------------------------------- local function MakeTwoFaces( Proc, bSinglePart, bPrevBhSideMill) -- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer -- genero errore e non faccio nulla if _nChamfer < 0 then return false, _sErrCham end -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) if not nFacInd or nFacInd < 0 then local sErr = 'Error : MakeTwoFaces could not find reference face' EgtOutLog( sErr) return false, sErr end local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local _, dH, _ = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia local bMakeBySideMill, _, bHeadDir, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill) if bPrevBhSideMill == nil then bPrevBhSideMill = bMakeBySideMill end if bMakeBySideMill and ( dMaxMat <= dH + 15 * GEO.EPS_SMALL) then -- se smusso non è esclusivo if _nChamfer < 2 then local bOk, sErr = MakeBySideMill(Proc, ptC, vtN, nFacInd, dMaxMat, dFacElev, dToolDiam, bHeadDir) return bOk, sErr end -- altrimenti lavoro con svuotatura else local bOk, sErr = MakePocketingOrMilling( Proc, nFacInd, nFacInd2, bSinglePart, dFacElev, dFacElev2) return bOk, sErr end return true, '', bPrevBhSideMill end --------------------------------------------------------------------- local function MakeThreeFaces( Proc, bSinglePart, bPrevBhSideMill) -- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer -- genero errore e non faccio nulla if _nChamfer < 0 then return false, _sErrCham end -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) if not nFacInd or nFacInd < 0 then local sErr = 'Error : MakeThreeFaces could not find reference face' EgtOutLog( sErr) return false, sErr end local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia local bMakeBySideMill, _, bHeadDir, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill) if bPrevBhSideMill == nil then bPrevBhSideMill = bMakeBySideMill end --if bMakeBySideMill and ( dMaxMat <= dV + 15 * GEO.EPS_SMALL) then if bMakeBySideMill and ( dMaxMat <= dH + 15 * GEO.EPS_SMALL) then -- se smusso non è esclusivo if _nChamfer < 2 then local bOk, sErr = MakeBySideMill(Proc, ptC, vtN, nFacInd, dMaxMat, dFacElev, dToolDiam, bHeadDir) return bOk, sErr end -- altrimenti lavoro con svuotatura else local bSpecial3faces = false local bBoxF = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfFac) if dH * dV < 0.9 * ( bBoxF:getDimX() * bBoxF:getDimY()) then bSpecial3faces = true end -- se riconosciuta gestione special (limitata per ora alla feature 20) if bSpecial3faces and Proc.Prc == 20 and nFacInd2 then -- se smusso non è esclusivo if _nChamfer < 2 then local bOk, sErr = MakeSpecialThreeFaces( Proc) return bOk, sErr end -- altrimenti lavorazione di svuotatura o contornatura else local bOk, sErr = MakePocketingOrMilling( Proc, nFacInd, nFacInd2, bSinglePart, dFacElev, dFacElev2) return bOk, sErr end end return true, '', bPrevBhSideMill end --------------------------------------------------------------------- local function MakeMoreFaces( Proc, bSinglePart, bPrevBhSideMill) local bClosedOrthoFaces local nBottomFace -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, _nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 else local sErr = 'Error : MakeMoreFaces could not find reference face' EgtOutLog( sErr) return false, sErr end end -- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura for i = 1, Proc.Fct do local nNewProc = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL -- elimino una faccia nBottomFace = i - 1 if EgtSurfTmRemoveFacet( nNewProc, nBottomFace) then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( nNewProc, _nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 EgtErase( nNewProc) break else EgtErase( nNewProc) local sErr = 'Error : MakeMoreFaces could not find reference face' EgtOutLog( sErr) return false, sErr end end -- altrimenti esco else EgtErase( nNewProc) break end end -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo if bClosedOrthoFaces then nFacInd = nBottomFace -- rendo nulla la faccia opzionale perchè si tratta di una fessura nFacInd2 = nil dFacElev = BL.GetFaceElevation( Proc.Id, nFacInd) bClosedOrthoFaces = false -- non setto come tunnel end end -- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer -- genero errore e non faccio nulla if _nChamfer < 0 then return false, _sErrCham end -- se è un tunnel provo a vedere se è possibile lavorarlo con la svuotatura o con la sega catena if bClosedOrthoFaces then local bTryWithBlades = true -- lavoro fessura con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' local nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace = MakeByPockets( Proc, sMyMchFind, false, bClosedOrthoFaces) if nOk < 0 then return false, sErr elseif nOk > 0 then bTryWithBlades = false end -- Se la svuotatura precedente non è stata fatta e chamfer non è mutuamente esclusivo provo con la sega-catena if bTryWithBlades and _nChamfer < 2 then -- verifico se posso farlo con la sega-catena local bOk, sErr = MakeByChainsaw(Proc, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace) if not bOk then return false, sErr end end -- altrimenti non è una fessura else local bOk, sErr = MakePocketingOrMilling( Proc, nFacInd, nFacInd2, bSinglePart, dFacElev, dFacElev2) return bOk, sErr, bPrevBhSideMill end return true, '', bPrevBhSideMill end --------------------------------------------------------------------- local function MakeLongFaces( Proc, Func) -- divido in parti lungo la X local vAddId = {} local nPart = max( ceil( Proc.Box:getDimX() / BD.LONGCUT_MAXLEN), 2) local dPartLen = Proc.Box:getDimX() / nPart local Xmin = Proc.Box:getMin():getX() for i = 1, nPart do -- eseguo divisione local AddId = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL EgtSetName( AddId, 'AddPart_' .. tostring( Proc.Id) .. '_' .. tostring( i)) if i > 1 then local ptOn = Point3d( Xmin + ( i - 1) * dPartLen, 0, 0) EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB) end if i < nPart then local ptOn = Point3d( Xmin + i * dPartLen, 0, 0) EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB) end -- eseguo inserimento in modo da ordinare da X+ a X- table.insert( vAddId, 1, AddId) end -- applico le lavorazioni sulle diverse parti local sWarn local bPrevBhSideMill for i = 1, #vAddId do local b3Box = EgtGetBBoxGlob( vAddId[i], GDB_BB.STANDARD) local nFct = EgtSurfTmFacetCount( vAddId[i]) local AddProc = { Id = vAddId[i], Grp = Proc.Grp, Prc = Proc.Prc, Box = b3Box, TotBox = Proc.Box, Fct = nFct, Flg = Proc.Flg} local bOk, sMyWarn -- richiamo la funzione necessaria (passata come parametro) bOk, sMyWarn, bPrevBhSideMill = Func( AddProc, false, bPrevBhSideMill) if not sWarn then sWarn = sMyWarn end if not bOk then return bOk, sWarn end end return true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione --------------------------------------------------------------------- function ProcessLapJoint.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) -- inizializzo variabili globali al modulo local bOk, sErr = InitGlob( Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOk then return bOk, sErr end -- limiti di fresatura semplice local MAX_MILL_LIN = 80 -- se non forzate frese, uso la lama local bUseBlade = Q_USE_ROUGH_TOOL ~= 1 and Q_USE_MILL ~= 1 local nForceUseBladeOnNotContinueFace -- se ho attivo la lama e ho la feature 30, verifico i parametri Q propri della feature if bUseBlade then if Proc.Prc == 30 then nForceUseBladeOnNotContinueFace = Q_BLADE_ON_ALONG_FACE -- se antischeggia di fresa o abilitato sgrossatore di fianco if Q_ANTISPLINT_TYPE == 2 or Q_SIDE_ROUGH_TOOL == 1 then bUseBlade = false end -- se ho attivo la lama e ho la feature 32, verifico i parametri Q propri della feature elseif Proc.Prc == 32 then -- se antischeggia di fresa o abilitato sgrossatore di fianco if Q_ANTISPLINT_TYPE == 2 or Q_SIDE_ROUGH_TOOL == 1 then bUseBlade = false end -- se ho attivo la lama e ho la feature 34, verifico i parametri Q propri della feature elseif Proc.Prc == 34 then -- se antischeggia di fresa o abilitato sgrossatore di fianco if Q_ANTISPLINT_TYPE == 2 then bUseBlade = false end end end -- se lunghezza richiede spezzatura if ( Proc.Box:getDimX() > BD.LONGCUT_MAXLEN) or ( Proc.Box:getDimX() > 0.8 * _b3Solid:getDimX() and Proc.Box:getDimX() > BD.LONGCUT_ENDLEN) then -- una faccia if Proc.Fct == 1 then if bUseBlade and nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, nForceUseBladeOnNotContinueFace) else return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId) end -- due facce elseif Proc.Fct == 2 then -- determino se due facce lunghe oppure una lunga e l'altra terminale local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD) local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD) if abs( b3Fac1:getDimX() - b3Fac2:getDimX()) < 50 then -- leggo i parametri Q per utilizzare la fresa di fianco e/o lama return Long2Cut.Make( Proc, _nPhase, _nRawId, _nPartId, Q_ANTISPLINT_TYPE == 1, Q_SIDE_ROUGH_TOOL) elseif b3Fac1:getDimX() < 1 or b3Fac2:getDimX() < 1 then -- la faccia 0 deve essere quella lunga if b3Fac1:getDimX() < 1 then EgtSurfTmSwapFacets( Proc.Id, 0, 1) end if bUseBlade then if nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, nForceUseBladeOnNotContinueFace) else return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide') end else return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId) end else if bUseBlade then return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide') else return MakeLongFaces( Proc, MakeTwoFaces) end end -- tre facce elseif Proc.Fct == 3 then -- determino se due facce lunghe oppure una lunga e l'altra terminale local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD) local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD) local b3Fac3 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 2, GDB_BB.STANDARD) local bApplyBladeOnLongNotContinueFace if b3Fac1:getDimX() < 1 and b3Fac3:getDimX() < 1 then -- la faccia 0 deve essere quella lunga EgtSurfTmSwapFacets( Proc.Id, 0, 1) bApplyBladeOnLongNotContinueFace = true elseif b3Fac1:getDimX() < 1 and b3Fac2:getDimX() < 1 then -- la faccia 0 deve essere quella lunga EgtSurfTmSwapFacets( Proc.Id, 0, 2) bApplyBladeOnLongNotContinueFace = true elseif b3Fac2:getDimX() < 1 and b3Fac3:getDimX() < 1 then bApplyBladeOnLongNotContinueFace = true end if bApplyBladeOnLongNotContinueFace and bUseBlade and nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, nForceUseBladeOnNotContinueFace) else return MakeLongFaces( Proc, MakeThreeFaces) end -- 4 o 5 facce else return MakeLongFaces( Proc, MakeMoreFaces) end -- altrimenti lavorazione unica else -- una faccia if Proc.Fct == 1 then -- se piccola, con fresa if not bUseBlade and ( Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN)) then return MakeOneFaceByMill( Proc) -- altrimenti, con lama else return Cut.Make( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead) end -- due facce elseif Proc.Fct == 2 then -- se praticamente è lunga come la trave if Proc.Box:getDimX() > 0.8 * _b3Solid:getDimX() then return Long2Cut.Make( Proc, _nPhase, _nRawId, _nPartId, bUseBlade, Q_SIDE_ROUGH_TOOL) -- altrimenti else -- verifico se da lavorare con testa da sotto local bDownHead = false if BD.DOWN_HEAD then local vtN = {} _, vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) _, vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) local vtNm = ( vtN[1] + vtN[2]) vtNm:normalize() bDownHead = ( vtNm:getZ() < -0.5) end -- determino l'angolo tra le facce local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) -- se ortogonali e non forzata lama oppure con testa da sotto, con fresa if ( not bUseBlade or bDownHead) and bAdj and abs( dAng + 90) < 1 then -- se piccole if Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN) then return MakeTwoFacesByMill( Proc, bDownHead) else return MakeTwoFaces( Proc, true) end -- altrimenti, con lama else -- verifico se due facce o L con una o due facce di terminazione local _, bIsL = TestUL( Proc) if bIsL and _nChamfer > 0 then local _, _, _, vtOrtho, _, nSurfInt = GetTunnelDimension( Proc) local nOk, sErr = MakeChamfer( Proc, true, vtOrtho, _b3Solid, nSurfInt) if nOk < 0 then return false, sErr end end return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead) end end -- tre facce elseif Proc.Fct == 3 then return MakeThreeFaces( Proc, true) -- 4 o 5 facce else return MakeMoreFaces( Proc, true) end end end --------------------------------------------------------------------- return ProcessLapJoint