diff --git a/LuaLibs/ProcessLapJointNew.lua b/LuaLibs/ProcessLapJointNew.lua new file mode 100644 index 0000000..2eb55f7 --- /dev/null +++ b/LuaLibs/ProcessLapJointNew.lua @@ -0,0 +1,5177 @@ +-- ProcessLapJoint.lua by Egaltech s.r.l. 2022/01/28 +-- 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 una volta sola all'inizio. +-- 2022/01/13 Estrapolazione da MakeMoreFaces() di MakeTwoFaces() e MakeThreeFaces(), e varie ottimizzazioni. +-- 2022/01/19 Cambiata % lunghezza pezzo per spezzatura. Tolta correzione spessore fresa a disco con superficie da lavorare verso Z-. +-- 2022/01/26 Migliorato controllo uso testa da sotto nel caso due facce con lama. +-- 2022/01/28 Aggiunte funzioni DoClean, DoPocketing, DoHeadChainSaw, DoSideChainSaw e DoHeadCut. + +-- 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 EvaluateChamfer() + 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 per la profondità smusso e + -- per eseguire in esclusiva solo lo smusso + _nChamfer, _dDepthCham, _sErrCham, _bForceUseBlade = EvaluateChamfer() + + return true, '' +end + +--------------------------------------------------------------------- +local function UpdateFacet1Data( nProcId, tFData, nFacInd, dFacElev) + if not tFData then + tFData = {} + end + tFData.nFacInd = nFacInd + if dFacElev then + tFData.dFacElev = dFacElev + end + if tFData.nFacInd and tFData.nFacInd > -1 then + tFData.ptC, tFData.vtN = EgtSurfTmFacetCenter( nProcId, tFData.nFacInd, GDB_ID.ROOT) + tFData.rfFac, tFData.dH, tFData.dV = EgtSurfTmFacetMinAreaRectangle( nProcId, tFData.nFacInd, GDB_ID.ROOT) + end + return tFData +end + +--------------------------------------------------------------------- +local function UpdateFacet2Data( nProcId, tFData, nFacInd2, dFacElev2) + if not tFData then + tFData = {} + end + tFData.nFacInd2 = nFacInd2 + if dFacElev2 then + tFData.dFacElev2 = dFacElev2 + end + if tFData.nFacInd2 and tFData.nFacInd2 ~= true and tFData.nFacInd2 > -1 then + tFData.ptC2, tFData.vtN2 = EgtSurfTmFacetCenter( nProcId, tFData.nFacInd2, GDB_ID.ROOT) + tFData.rfFac2, tFData.dH2, tFData.dV2 = EgtSurfTmFacetMinAreaRectangle( nProcId, tFData.nFacInd2, GDB_ID.ROOT) + end + return tFData +end + +--------------------------------------------------------------------- +local function GetFacetsData( nProcId) + local tFData = {} + local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( nProcId, _nPartId) + if nFacInd then + tFData = UpdateFacet1Data( nProcId, tFData, nFacInd, dFacElev) + tFData = UpdateFacet2Data( nProcId, tFData, nFacInd2, dFacElev2) + if tFData.nFacInd == -1 and tFData.nFacInd2 and tFData.nFacInd2 == true then + tFData.isOrthoFaces = true + end + end + return tFData +end + +--------------------------------------------------------------------- +local function SwapFacetsData( tFData) + if tFData then + tFData.nFacInd, tFData.nFacInd2 = tFData.nFacInd2, tFData.nFacInd + tFData.dFacElev, tFData.dFacElev2 = tFData.dFacElev2, tFData.dFacElev + tFData.ptC, tFData.ptC2 = tFData.ptC2, tFData.ptC + tFData.vtN, tFData.vtN2 = tFData.vtN2, tFData.vtN + tFData.rfFac, tFData.rfFac2 = tFData.rfFac2, tFData.rfFac + tFData.dH, tFData.dH2 = tFData.dH2, tFData.dH + tFData.dV, tFData.dV2 = tFData.dV2, tFData.dV + end + return tFData +end + +--------------------------------------------------------------------- +local function GetToolInfoForMachining( sMachiningName) + if EgtMdbSetCurrMachining( sMachiningName) then + local toolInfo = {} + 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( 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( 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, sMilling, 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 nLongFaceId = 0 + for i = 1, Proc.Fct do + if abs( vtN[i] * frSurfInt:getVersX()) < 0.5 then + nLongFaceId = i - 1 + break + end + end + return dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt +end + +--------------------------------------------------------------------- +local function GetFaceAdj( Proc, tFData) + -- Recupero le facce adiacenti alla principale (solo quelle esistenti) + local vAdj = GetValidFacetAdjacencies( Proc.Id, tFData.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 tFData.dH < tFData.dV then + tFData.dH, tFData.dV = tFData.dV, tFData.dH + end + -- Cerco una faccia adiacente alla principale sul lato lungo + local nFacAdj + for i = 1, #vAdj do + local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, tFData.nFacInd, vAdj[i], GDB_ID.ROOT) + local dLen = dist( ptP1, ptP2) + if dLen > 0.5 * tFData.dH then + nFacAdj = vAdj[i] + EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, tFData.dH, tFData.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 + local tFData = GetFacetsData( Proc.Id) + -- deve avere la normale principale diretta verso la testa + if tFData.vtN and tFData.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 + local tFData = GetFacetsData( Proc.Id) + -- deve avere la normale principale diretta verso la coda (oppure tunnel) + if tFData.vtN and tFData.vtN:getZ() < BD.NZ_MINA and tFData.nFacInd2 then + tFData = SwapFacetsData( tFData) + end + if not tFData.vtN or tFData.vtN:getX() > -0.001 or dEndDist + tFData.vtN:getX() * tFData.dFacElev > 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 + local tFData = GetFacetsData( Proc.Id) + if not tFData.nFacInd or tFData.nFacInd < 0 then + if tFData.nFacInd == -1 then + bClosedOrthoFaces = tFData.isOrthoFaces + 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 + tFData = GetFacetsData( nNewProc) + if not tFData.nFacInd or tFData.nFacInd < 0 then + if tFData.nFacInd == -1 then + bClosedOrthoFaces = tFData.isOrthoFaces + 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 + tFData = UpdateFacet1Data( Proc.Id, tFData, nDeletedFace) + -- rendo nulla la faccia opzionale perchè si tratta di una fessura + tFData = UpdateFacet2Data( Proc.Id, tFData, nil) + 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, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc) + EgtErase( nSurfInt) + -- verifico se può essere fatto con svuotatura + if VerifyPocket( dDimMin) then + return true, false + elseif VerifyChainSaw( dDimMin, dDimMax) then + return true, false + else + return false + end + else + -- se può essere fatto con utensile tipo lama + local bUseBHSideMill, _, _, dMaxMat = VerifyBHSideMill( Proc) +-- if bUseBHSideMill and ( dMaxMat <= tFData.dV + 15 * GEO.EPS_SMALL) then + if bUseBHSideMill and ( dMaxMat <= tFData.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, tFData.nFacInd, GDB_ID.ROOT) + -- cerco se c'è faccia adiacente sul lato più lungo + local nFaceAdj = GetFaceAdj( Proc, tFData) 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 tFData.nFacInd2 and tFData.dFacElev2 < 2 * tFData.dFacElev then + local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, tFData.nFacInd2, GDB_ID.ROOT) + bDown = ( vtN2:getZ() < BD.NZ_MINB) + elseif not tFData.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, sName, sMilling, offset, nFacInd, nFac2Ind, vtN) + -- inserisco la lavorazione di fresatura + 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, sName + -- se forzato uso fresa controllo se posso fare in una o più passate + if Q_USE_MILL and Q_USE_MILL == 1 then + sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_1' + bOk, sErr = DoMill( Proc, sName, sMilling, dTDiam / 2, nFacInd, nOthInd, vtN) + + if not bOk then return bOk, sErr end + end + sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) + bOk, sErr = DoMill( Proc, sName, 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, tFData, dCollSic, bSpecialApp, sMillMaster) + -- Cerco una faccia adiacente alla principale sul lato lungo + local nFacAdj, sErr = GetFaceAdj( Proc, tFData) + 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] == tFData.nFacInd then + -- Se non esiste faccia adiacente a lato precedente -> inizio aperto + local i = EgtIf( j > 1, j - 1, #vAdj2) + while vAdj2[i] == tFData.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] == tFData.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 < tFData.dFacElev + 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( tFData.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 tFData.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 == tFData.nFacInd2 then + if not bOpenStart then + EgtSetMachiningParam( MCH_MP.LOPERP, tFData.dFacElev2) + EgtSetMachiningParam( MCH_MP.LOTANG, 0) + end + if not bOpenEnd then + EgtSetMachiningParam( MCH_MP.LIPERP, tFData.dFacElev2) + EgtSetMachiningParam( MCH_MP.LITANG, 0) + end + end + end + -- applico elevazione + local sNotes = 'MaxElev=' .. EgtNumToString( tFData.dFacElev, 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, dDist, 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 DoClean( sName, sMilling, nIdPath, vtN, dMaxElev, dMachDepth, dExtraDepth, dNoLeadsAddLen, dLeadInPerp, + bLeftWorkside, bInvertTool, bInvertDir, bCheckToInvertPath, bSCCEvaluateOppositeVector, bEvaluateAddLeads) + local nMchId = EgtAddMachining( sName, sMilling) + local sMyWarn + if not nMchId then + sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling + return false, sMyWarn + end + -- aggiungo geometria + EgtSetMachiningGeometry( {{ nIdPath, -1}}) + -- imposto lato di lavoro sinistro + if bLeftWorkside then + EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) + end + -- imposto direzione utensile opposta + if bInvertTool then + EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) + end + -- imposto posizione braccio porta testa + local nSCC = MCH_SCC.NONE + if not BD.C_SIMM then + if EgtIf( bSCCEvaluateOppositeVector, AreSameOrOppositeVectorApprox( vtN, Z_AX()), AreSameVectorApprox( 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 = EgtIf( bInvertDir, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) + else + nSCC = EgtIf( bInvertDir, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) + end + end + EgtSetMachiningParam( MCH_MP.SCC, nSCC) + -- gestione attacco e uscita + if bEvaluateAddLeads and 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, dLeadInPerp) + 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, dNoLeadsAddLen) + EgtSetMachiningParam( MCH_MP.ENDADDLEN, dNoLeadsAddLen) + end + -- setto massimo affondamento possibile + EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth + dExtraDepth) + -- setto se devo invertire il percorso + if bCheckToInvertPath then + local bInvert = CheckToInvert( nIdPath, true) + EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertDir, not bInvert, bInvert)) + end + -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione + local sUserNotes = 'VMRS=0;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) + return false, sMyWarn + end + return true, sMyWarn +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 dDepth = 0 + if tFacAdj[i][3] > dTMaxDepth then + dDepth = dTMaxDepth - tFacAdj[i][3] + end + _, sMyWarn = DoClean( sName, sMilling, AuxId, vtN1, tFacAdj[i][3], dDepth, 0, 0, 0, true, false, false, true, true, false) + ::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 = '' + local bOk + for i = 1, nNumId do + local nIdPath = nFirstId + i - 1 + local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) + local bInvertMach + 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 + 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 + bInvertMach = true + end + end + local dMachDepth = 0 + if ( dMaxElev + dCollSic) > dTMaxDepth then + dMachDepth = dTMaxDepth - ( dMaxElev + dCollSic) + end + bOk, sMyWarn = DoClean( sName, sMilling, nIdPath, vtN1, dMaxElev, dMachDepth, dExtraDepth, 0.75 * dTDiam, 0.5 * dTDiam, true, bInvertMach, bInvertMach, true, true, true) + -- se devo applicare la contornatura anche sul lato opposto + if bOk and bDoubleSide then + if bMillDown then + sMilling = sMillingDn + dTDiam = dTDiamDn + dTMaxDepth = dTMaxDepthDn + end + sName = 'CleanOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) + bOk, sMyWarn = DoClean( sName, sMilling, nIdPath, vtN1, dMaxElev, dMachDepth, 0, 0.75 * dTDiam, 0, true, true, true, true, false, false) + end + end + if #sMyWarn > 0 then + EgtOutLog( sMyWarn) + end + + return true, sMyWarn +end + +--------------------------------------------------------------------- +local function MakeRoundCleanCornerOrContour( Proc, nFacInd, dDiam, bMillDown, bDoubleSide, + vtOrtho, nPathInt, nSurfInt, dDepth, bOneShot) + local nFunction = Q_CONTOUR_SMALL_TOOL + -- 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 i versori + 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 too small 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 bOk + bOk, sMyWarn = DoClean( sName, sMilling, AuxId, vtN1, dMaxDepth, 0, 0, 10, 0, false, false, true, false, false, false) + if not bOk then + return false, sMyWarn + 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 e massima elevazione (coincide con affondamento) + local sUserNotes = 'VMRS=0;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) + 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, vtOrtho, nSurfInt) + -- Se variabile globale indica che lo smusso è già stato fatto, esco + if _bMadeChamfer then + return 0 + end + _bMadeChamfer = true + local bIs3Faces = Proc.Fct == 3 + -- 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, tFData, 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 le facce adiacenti alla principale (solo quelle esistenti) + local vAdj = GetValidFacetAdjacencies( Proc.Id, tFData.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, tFData.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, tFData.dH, tFData.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 * tFData.rfFac:getVersX()) > abs( vtN * tFData.rfFac:getVersY()) then + tFData.dH, tFData.dV = tFData.dV, tFData.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] == tFData.nFacInd then + -- Se non esiste faccia adiacente a lato precedente -> inizio aperto + local i = EgtIf( j > 1, j - 1, #vAdj2) + while vAdj2[i] == tFData.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] == tFData.nFacInd do + k = EgtIf( k < #vAdj2, k + 1, 1) + end + bOpenEnd = ( vAdj2[k] < 0) + 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( tFData.rfFac:getVersZ()) + local dStartDist = -1 + local dEndDist = -1 + -- calcolo eventuali arretramenti lama + if not bOpenStart then + local dRadius = dSawDiam / 2 + local dCat1 = dRadius - tFData.dFacElev + 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 - tFData.dFacElev + dEndDist = sqrt( ( dRadius * dRadius) - ( dCat1 * dCat1)) + end + end + -- Eseguo i tagli + local nStep = ceil( ( tFData.dV - 10 * GEO.EPS_SMALL) / dSawThick) + local dStep = 0 + if nStep > 1 then + dStep = ( tFData.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) - tFData.dFacElev) * ( ( dSawDiam / 2) - tFData.dFacElev))) + -- 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 DoHeadChainSaw( Proc, sName, sSawing, tFData, nFaceUse, nFacAdj, vtN, vtNE, vtNS, dSawWidth, + dOffs, dDistToNextPiece, dMaxDepth, bOpenStart, bOpenEnd) + 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, tFData.rfFac:getVersZ())) + -- imposto offset radiale + EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) + -- se necessario, limito l'affondamento + if tFData.dFacElev > dMaxDepth + 10 * GEO.EPS_SMALL then + local sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( tFData.dFacElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' + local dDepth = dMaxDepth - tFData.dFacElev + EgtOutLog( sWarn) + EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH ' .. EgtNumToString( dDepth, 1)) + end + -- imposto elevazione + local sNotes = 'MaxElev=' .. EgtNumToString( tFData.dFacElev, 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, tFData.rfFac:getVersZ())) + if not EgtApplyMachining( true, false) then + local _, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nMchFId, false) + return false, sErr + end + end + if EgtIsMachiningEmpty() then + local _, sWarn = EgtGetMachMgrWarning( 0) + EgtSetOperationMode( nMchFId, false) + return false, sWarn + end + return true +end + +--------------------------------------------------------------------- +local function DoSideChainSaw( Proc, sName, sSawing, tFData, vtN, vtOrtho, nLongFaceId, + dOffs, dMaxMat, dSawCornerRad, bOpenStart, bOpenEnd) + 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, nLongFaceId}}) + -- imposto uso del lato faccia + local nFaceUse + -- se non è un tunnel a 4 facce + if Proc.Fct < 4 then + nFaceUse = BL.GetNearestParalOpposite( tFData.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 + 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 > dMaxMat then + local 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 dMaxMat > ( dDepth + dSawCornerRad + 1) then + EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth + dSawCornerRad + 1)) + -- se massimo affondamento supera altezza fessura, uso massimo affondamento + elseif dMaxMat > ( dDepth + 1) then + EgtSetMachiningParam( MCH_MP.DEPTH, ( dMaxMat - 1)) + -- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning + elseif dMaxMat < dDepth then + EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat) + local 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 + local _, sWarn = EgtGetMachMgrWarning( 0) + EgtSetOperationMode( nMchFId, false) + return false, sWarn + end + return true +end + +--------------------------------------------------------------------- +local function MakeByChainOrSaw( Proc, tFData, dDimMin, dDimMax, vtOrtho, nLongFaceId, + bOrthoFacesMaster, nBottomFace, nSurfInt) + local bIs3Faces = Proc.Fct == 3 + 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, dFacElev1, nFacInd2, dFacElev2 = 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, nLongFaceId, nSurfInt = GetTunnelDimension( Proc) + -- verifico la direzione + -- se devo inserire il chamfer + if _nChamfer > 0 then + local nOk, sErr = MakeChamfer( Proc, 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, tFData.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, tFData.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, tFData.dH, tFData.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 * tFData.rfFac:getVersX()) > abs( vtN * tFData.rfFac:getVersY()) then + tFData.dH, tFData.dV = tFData.dV, tFData.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] == tFData.nFacInd then + -- Se non esiste faccia adiacente a lato precedente -> inizio aperto + local i = EgtIf( j > 1, j - 1, #vAdj2) + while vAdj2[i] == tFData.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] == tFData.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( tFData.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 tFData.dFacElev < 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 > tFData.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( tFData.rfFac:getVersZ()) + -- Eseguo i tagli + local nStep = ceil( ( tFData.dV - 10 * GEO.EPS_SMALL) / dSawThick) + local dStep = 0 + if nStep > 1 then + dStep = ( tFData.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) - tFData.dFacElev) * ( ( dSawDiam / 2) - tFData.dFacElev))) + -- 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 > tFData.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 tFData.dFacElev > 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( tFData.rfFac:getVersZ()) + -- Calcolo normale faccia adiacente + local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT) + -- Verifico se necessarie più passate + local nStep = ceil( ( tFData.dV - 10 * GEO.EPS_SMALL) / dSawThick) + local dStep = 0 + if nStep > 1 then + dStep = ( tFData.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 dOffs = ( i - 1) * dStep + local bOk, sErr = DoHeadChainSaw( Proc, sName, sSawing, tFData, nFaceUse, nFacAdj, vtN, vtNE, vtNS, dSawWidth, dOffs, dDistToNextPiece, dMaxDepth, bOpenStart, bOpenEnd) + if not bOk then + return false, sErr + end + end + -- altrimenti segacatena di fianco + else + -- verifico se posso farlo con la sega-catena + local bMakeChainSaw, sSawing2, dMaxMat2, dSawCornerRad2, dSawThick2 = VerifyChainSaw( 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 dOffs = ( i - 1) * dStep + local bOk, sErr = DoSideChainSaw( Proc, sName, sSawing2, tFData, vtN, vtOrtho, nLongFaceId, dOffs, dMaxMat2, dSawCornerRad2, bOpenStart, bOpenEnd) + if not bOk then + return false, sErr + 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 DoPocketing( sName, sPocketing, sMchFind, vtN, nPathInt, nFaceIdx, nUseRoughTool, dMachDepth, dMaxElev, bInvertTool, bInvertPath, bFaceOrtho, bSCCEvaluateOppositeVector, bSCCYSpecialStrategy) + -- inserisco la lavorazione di svuotatura + 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( {{ nPathInt, nFaceIdx}}) + if bInvertTool then + EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) + end + if bFaceOrtho then + -- imposto uso faccia + EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) + end + -- imposto posizione braccio porta testa + local nSCC = MCH_SCC.NONE + if not BD.C_SIMM then + if EgtIf( bSCCEvaluateOppositeVector, AreSameOrOppositeVectorApprox( vtN, Z_AX()), AreSameVectorApprox( 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 bSCCYSpecialStrategy then + if vtN:getY() > 0.1 then + nSCC = MCH_SCC.ADIR_YP + else + nSCC = MCH_SCC.ADIR_YM + end + else + if vtN:getY() < GEO.EPS_SMALL then + nSCC = EgtIf( bInvertTool, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) + else + nSCC = EgtIf( bInvertTool, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) + end + end + end + EgtSetMachiningParam( MCH_MP.SCC, nSCC) + -- se tasca aperta, imposto opportuno attacco + if (sMchFind == 'OpenPocket' and nUseRoughTool == 0) or sMchFind == 'OpenPocket_H2' then + EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) + end + if bInvertPath then + -- inverto il percorso di lavorazione se necessario lavorare sinistro + EgtSetMachiningParam( MCH_MP.INVERT, bInvertPath) + end + if dMachDepth ~= 0 then + -- imposto affondamento + EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) + end + -- imposto elevazione e dichiaro non si generano sfridi per VMill + local sNotes = 'VMRS=0;' + if dMaxElev > 0 then + sNotes = sNotes .. 'MaxElev=' .. EgtNumToString( dMaxElev, 1) .. ';' + end + 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 bOk, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nMchFId, false) + return false, sErr + end + end + return true, '', nMchFId +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 dMachDepth = 0 + if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then + dMachDepth = dMaxDepth - dElev + dElev = dMaxDepth + sWarn = 'Warning : elevation bigger than max tool depth' + EgtOutLog( sWarn) + end + local bOk, sWarn, nMchFId = DoPocketing( sName, sPocketing, sMchFind, tvtN[2], Proc.Id, nFaceRef, nUseRoughTool, dMachDepth, dElev, false, false, true, false, true) + if not bOk then + return bOk, sWarn + end + return true, sWarn, sTuuidPk, dDiamTool +end + +--------------------------------------------------------------------- +local function DoHeadCut( Proc, sName, sMilling, nMchFId, dElev, nSideFace, tvtN) + 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) .. ';VMRS=0;' + EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) + if not EgtApplyMachining( true, false) then + local _, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nMchFId, false) + return false, sErr + end + return true +end + +--------------------------------------------------------------------- +local function MachineByMill( Proc, tvtN, nBaseFace, nSideFace, ptPs, tDimAndRef, + nDiffWidth, nUseRoughTool, dAng, sPocketing, sTuuidPk, dPrevFaceElev) + -- se angolo tra le facce maggiore di 90, inserisco la contornatura o svuotatura del lato più corto + if ( 180 + dAng) > 90.1 then + 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 + -- 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 + if sTuuidPk 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)) + bOk, sWarn = DoHeadCut( Proc, sName, sMilling, nMchFId, dElev, nSideFace, tvtN) + if not bOk then + return false, sWarn + end + 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, bOrthoFacesMaster, bMillDown) + local nFirstMachId + local bOrthoFaces + local sWarn + local sMchFind = 'Pocket' + local dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt + local bBadMach = false + local bIs3Faces = Proc.Fct == 3 + + 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, nLongFaceId, nSurfInt = GetTunnelDimension( Proc) + local nPathInt + -- se devo inserire il chamfer + if _nChamfer > 0 then + local nOk, sErr = MakeChamfer( Proc, 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( dDimMin, dDepth / 2, nil, sMchFind) + local bMakePocketDn, sPocketingDn, dMaxDepthDn + if bMillDown then + bMakePocketDn, sPocketingDn, dMaxDepthDn = VerifyPocket( 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 bToolInvert = false + -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) + if vtOrtho:getZ() < BD.NZ_MINA and abs( vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then + bToolInvert = 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 + bToolInvert = true + end + -- eseguo svuotatura + local bOk, sErr, nMchFId = DoPocketing( sName, sPocketing, sMchFind, vtOrtho, nPathInt, -1, 0, dMachDepth, dElev, bToolInvert, true, false, true) + if not bOk then + return -1, sErr + end + -- prendo l'id della prima lavorazione inserita + if not nFirstMachId then + nFirstMachId = nMchFId + 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)) + -- eseguo svuotatura in direzione invertita + local bOk, sErr, nMchFId = DoPocketing( sName, sPocketing, sMchFind, vtOrtho, nPathInt, -1, 0, dMachDepth, dElev, true, true, false, false) + if not bOk then + return -1, sErr + end + -- prendo l'id della prima lavorazione inserita + if not nFirstMachId then + nFirstMachId = nMchFId + 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) + -- calcolo affondamento + local dDepth = 0 + local dActMaxDepth = EgtIf( bFacPocketDn, dMaxDepthDn, dMaxDepth) + if dActMaxDepth < dFacElev + dFacCollSic then + dDepth = dActMaxDepth - dFacElev + dFacCollSic + end + -- inserisco la lavorazione di svuotatura + local sName = EgtIf( bDoubleSide, 'Pock3rd_', 'Pock2nd_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) + -- eseguo svuotatura + local bOk, sErr, nMchFId = DoPocketing( sName, sPocketing, sMchFind, vtN, Proc.Id, nFacInd, 0, dDepth, 0, false, true, false, true) + if not bOk then + return -1, sErr + end + -- prendo l'id della prima lavorazione inserita + if not nFirstMachId then + nFirstMachId = nMchFId + end + end + end + return 1, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId + end + end + end + + return 0, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, 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 ptC, 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 e massima elevazione + local sUserNotes = 'VMRS=0;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 iniziale + if tFacAdjMain[i][2] > nMaxLen then + ptIniPath = ptP1 + nMaxLen = tFacAdjMain[i][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 DoSideMill( Proc, sName, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir, bHalf, dV) + 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, tFData.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 tFData.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 tFData.vtN:getZ() > -0.5 then + EgtSetMachiningParam( MCH_MP.LITANG, 0) + EgtSetMachiningParam( MCH_MP.LIPERP, tFData.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, tFData.dFacElev + BD.COLL_SIC) + if bHalf then + EgtSetMachiningParam( MCH_MP.ENDADDLEN, - dH / 2) + end + end + -- tipo passate multiple + local nStepType = EgtIf( ( Proc.HeadDir and tFData.vtN:getY() < -0.5) or ( not Proc.HeadDir and tFData.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( ( tFData.vtN:getY() > 0.5 or ( bHeadDir and tFData.vtN:getZ() > 0.5 ) or ( not bHeadDir and tFData.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 MakeSideMill( Proc, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir) + local dH, dV + -- recupero la larghezza della faccia perpendicolarmente alle altre 2 + local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( tFData.nFacInd == 0, 1, 0), GDB_ID.ROOT) + local vtX = vtN2 ^ tFData.vtN + local frRef = Frame3d( tFData.ptC, tFData.ptC + 100 * vtX, tFData.ptC + 100 * vtN2) + local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, tFData.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 = ( tFData.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) + local bOk, sErr = DoSideMill( Proc, sName, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir, bHalf, dV) + return bOk, sErr +end + +--------------------------------------------------------------------- +local function MakeSpecialThreeFaces( Proc, tFData) + -- se orientata verso il basso, verifico l'alternativa + if tFData.vtN:getZ() < BD.NZ_MINA and tFData.vtN2:getZ() < BD.NZ_MINA then + local sErr = 'Error : special LapJoint from bottom impossible' + EgtOutLog( sErr) + return false, sErr + end + -- 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( tFData.dH, tFData.dV) + local dDiam2 = min( tFData.dH2, tFData.dV2) + local dCollSic = 2 * BD.COLL_SIC + local dCollSic2 = 2 * BD.COLL_SIC + if abs( tFData.vtN:getX()) > 0.7 or abs( tFData.vtN:getY()) > 0.7 or abs( tFData.vtN:getZ()) > 0.7 then dCollSic = 0 end + if abs( tFData.vtN2:getX()) > 0.7 or abs( tFData.vtN2:getY()) > 0.7 or abs( tFData.vtN2:getZ()) > 0.7 then dCollSic2 = 0 end + local sPocketing = ML.FindPocketing( sMchFind, dDiam2, tFData.dFacElev2 + dCollSic2) + local nPockFace = tFData.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 + tFData = SwapFacetsData( tFData) + + -- prendo a riferimento la seconda faccia per la svuotatura + sPocketing = ML.FindPocketing( sMchFind, dDiam2, tFData.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 bIsU, bIsL = TestUL( Proc) + if bIsL then + local bOk, sWarn + bOk, sWarn, _ = MakeByMill( Proc, tFData, dCollSic, true, sMilling) + 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 tFData.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( tFData.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, nLongFaceId) + -- verifico se posso farlo con la sega-catena + local bMakeChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick = VerifyChainSaw( 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, nLongFaceId}}) + -- 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, nLongFaceId, 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) + local 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 + local _, sWarn = EgtGetMachMgrWarning( 0) + EgtSetOperationMode( nMchFId, false) + return false, sWarn + end + end + end + + return true +end + +--------------------------------------------------------------------- +local function MakeSidePocketings( Proc, tFData, dCollSic, bSpecialMillOnSide, + nBottomFace, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide, + bSinglePart, bIsU, bIsL, dDiam, bMillDown, bMillUp, sMchFind, sMchFindBackUp) + local bTryWithBlades = true + local nOk, bOk, sWarn, sStat, sErr, dDimMin, dDimMax, dDepth, vtOrtho, bOrthoFaces, nSurfInt, sPocketing, nLongFaceId + if bSpecialMillOnSide then + -- eseguo + bOk, sWarn = MakeByMillAsSaw( Proc, tFData, 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 tFData.vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and tFData.nFacInd2 then + tFData = SwapFacetsData( tFData) + end + -- eseguo + bOk, sWarn, sStat = MakeByChainOrSaw( Proc, tFData, dDimMin, dDimMax, vtOrtho, nil, bOrthoFaces, nBottomFace, nSurfInt) + 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) + nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, _, _, _, _, _, _, _, _, bOrthoFaces = MakeByPockets( Proc, nil, bMillDown) + -- se lavorazione non idonea (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 dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc) + local nOk, sErr = MakeChamfer( Proc, 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, tFData.vtN, tFData.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 dDiamTool = 100 + local nPathInt, nSurfInt, bOneShot, nFirstMachId, bDoubleSide + nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, dDiamTool, + bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces = MakeByPockets( Proc, 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 bOk, sWarn2 = ManageAntiSplintByMill( Proc, tFData.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, tFData.nFacInd, dDiamTool, 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 tFData.vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and tFData.nFacInd2 then + tFData = SwapFacetsData( tFData) + end + -- eseguo + bOk, sWarn, sStat = MakeByChainOrSaw( Proc, tFData, dDimMin, dDimMax, vtOrtho, nLongFaceId, bOrthoFaces, nBottomFace, nSurfInt) + if not bOk and sStat == 'MNF' then + _, sPocketing = VerifyPocket( dDiam, tFData.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 = MakeRoundCleanCornerOrContour( Proc, tFData.nFacInd, 100, 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, tFData, bSinglePart) + -- 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 tFData.vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD and tFData.nFacInd2 then + tFData = SwapFacetsData( tFData) + bUseOtherFace = true + end + -- verifico non sia orientata verso il basso o ci sia una testa dal basso + local bFaceDown = ( tFData.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( tFData.vtN:getX()) > 0.866 and + ( Proc.Box:getMax():getX() < _b3Solid:getMax():getX() - 10 or tFData.vtN:getX() < 0) and + ( not Proc.Tail or tFData.vtN:getX() > 0) then + -- se non ho scambiato la faccia + if not bUseOtherFace then + if tFData.nFacInd2 then + tFData = SwapFacetsData( tFData) + -- altrimenti cerco la faccia secondaria per adiacenza alla principale + else + -- Cerco una faccia adiacente alla principale sul lato lungo + local nFacAdj, sErr = GetFaceAdj( Proc, tFData) + if nFacAdj < 0 then + EgtOutLog( sErr) + return false, sErr + end + tFData = UpdateFacet1Data( Proc.Id, tFData, nFacAdj) + 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( tFData.vtN) + -- abilitazione lavorazione da sotto + local bMillUp = ( BD.DOWN_HEAD and tFData.vtN:getZ() > -0.259) + local bMillDown = ( BD.DOWN_HEAD and tFData.vtN:getZ() < 0.342) + -- settaggio voluto da Alessandro/Fabio (per fare angoli con fresa piccola) + local sMchFind = 'Pocket' + local dDiam = min( tFData.dH, tFData.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, tFData.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( tFData.vtN) + end + -- ricerca lavorazione + local sPocketing + local _, sMyPocketing, dMyTMaxDepth, _ = VerifyPocket( dDiam, tFData.dFacElev + dCollSic, dMaxTotLen, sMchFind .. EgtIf( bMillDown, '_H2', '')) + if not sMyPocketing and bMillUp then + _, sMyPocketing, dMyTMaxDepth, _ = VerifyPocket( dDiam, tFData.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 > tFData.dFacElev + dCollSic - 10 * GEO.EPS_SMALL or ( dMyTMaxDepth > 0.8 * tFData.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 vtNi = EgtSurfTmFacetNormVersor( nTestId, nInt - 1, GDB_ID.ROOT) + -- se dimensione faccia sulla X + if b3Facet:getDimX() < 1 or abs( vtNi: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 tFData.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 tFData.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, tFData, 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, tFData, dCollSic, 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 dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc) + local nOk, sErr = MakeChamfer( Proc, 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 forma 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, tFData.vtN, tFData.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, tFData.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] = tFData.vtN + local bOk, sWarn2, sTuuidPk, dDiamTool + bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, tFData.ptC, tvtNx, tFData.nFacInd, sMchFind, nUseRoughTool, sPocketing, tFData.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, tFData.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] = tFData.vtN + tDimAndRef[1] = { tFData.dH, tFData.dV, tFData.rfFac} + for i = 1, #vAdj do + local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, tFData.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, tFData.nFacInd, vAdj[i], ptPs, tDimAndRef, + EgtIf( Proc.Fct == 3 and bIsU, 0, 2), nUseRoughTool, dAng, sPocketing, sTuuidPk, tFData.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 = MakeDrillOnCorner( Proc, tFData.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 = MakeSharpCleanCorner( Proc, tFData.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 = MakeRoundCleanCornerOrContour( Proc, tFData.nFacInd, dDiamTool, 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 tFData = GetFacetsData( Proc.Id) + if not tFData.nFacInd or tFData.nFacInd < 0 then + local sErr = 'Error : MakeTwoFaces could not find reference face' + EgtOutLog( sErr) + return false, sErr + end + + -- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia + local bMakeBySideMill, _, bHeadDir, sMilling, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill) + if bPrevBhSideMill == nil then + bPrevBhSideMill = bMakeBySideMill + end + if bMakeBySideMill and ( dMaxMat <= tFData.dH + 15 * GEO.EPS_SMALL) then + -- se smusso non è esclusivo + if _nChamfer < 2 then + local bOk, sErr = MakeSideMill( Proc, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir) + return bOk, sErr + end + -- altrimenti lavoro con svuotatura + else + local bOk, sErr = MakePocketingOrMilling( Proc, tFData, bSinglePart) + 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 tFData = GetFacetsData( Proc.Id) + if not tFData.nFacInd or tFData.nFacInd < 0 then + local sErr = 'Error : MakeThreeFaces could not find reference face' + EgtOutLog( sErr) + return false, sErr + end + + -- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia + local bMakeBySideMill, _, bHeadDir, sMilling, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bSinglePart, bPrevBhSideMill) + if bPrevBhSideMill == nil then + bPrevBhSideMill = bMakeBySideMill + end + --if bMakeBySideMill and ( dMaxMat <= tFData.dV + 15 * GEO.EPS_SMALL) then + if bMakeBySideMill and ( dMaxMat <= tFData.dH + 15 * GEO.EPS_SMALL) then + -- se smusso non è esclusivo + if _nChamfer < 2 then + local bOk, sErr = MakeSideMill( Proc, sMilling, tFData, dMaxMat, dToolDiam, bHeadDir) + return bOk, sErr + end + -- altrimenti lavoro con svuotatura + else + local bSpecial3faces = false + local bBoxF = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, tFData.rfFac) + + if tFData.dH * tFData.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 tFData.nFacInd2 then + -- se smusso non è esclusivo + if _nChamfer < 2 then + local bOk, sErr = MakeSpecialThreeFaces( Proc, tFData) + return bOk, sErr + end + -- altrimenti lavorazione di svuotatura o contornatura + else + local bOk, sErr = MakePocketingOrMilling( Proc, tFData, bSinglePart) + return bOk, sErr + end + end + + return true, '', bPrevBhSideMill +end + +--------------------------------------------------------------------- +local function MakeMoreFaces( Proc, bSinglePart, bPrevBhSideMill) + local bClosedOrthoFaces + -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa + local tFData = GetFacetsData( Proc.Id) + if not tFData.nFacInd or tFData.nFacInd < 0 then + if tFData.nFacInd == -1 then + bClosedOrthoFaces = tFData.isOrthoFaces + 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 + local nBottomFace + -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura + for i = 1, Proc.Fct do + local nNewProcId = EgtCopyGlob( Proc.Id, _nAddGrpId) or GDB_ID.NULL + -- elimino una faccia + nBottomFace = i - 1 + if EgtSurfTmRemoveFacet( nNewProcId, nBottomFace) then + -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa + tFData = GetFacetsData( nNewProcId) + if not tFData.nFacInd or tFData.nFacInd < 0 then + if tFData.nFacInd == -1 then + bClosedOrthoFaces = tFData.isOrthoFaces + EgtErase( nNewProcId) + break + else + EgtErase( nNewProcId) + local sErr = 'Error : MakeMoreFaces could not find reference face' + EgtOutLog( sErr) + return false, sErr + end + end + -- altrimenti esco + else + EgtErase( nNewProcId) + break + end + end + -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo + if bClosedOrthoFaces then + local dFacElev = BL.GetFaceElevation( Proc.Id, nBottomFace) + tFData = UpdateFacet1Data( Proc.Id, tFData, nBottomFace, dFacElev) + -- rendo nulla la faccia opzionale perchè si tratta di una fessura + tFData = UpdateFacet2Data( Proc.Id, tFData, nil) + -- non setto come tunnel + bClosedOrthoFaces = false + 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 nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId = MakeByPockets( Proc, 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, nLongFaceId) + if not bOk then + return false, sErr + end + end + -- altrimenti non è una fessura + else + local bOk, sErr = MakePocketingOrMilling( Proc, tFData, bSinglePart) + return bOk, sErr, bPrevBhSideMill + end + + return true, '', bPrevBhSideMill +end + +--------------------------------------------------------------------- +local function MakeLongFaces( Proc, Func) + -- divido in parti lungo 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 + +--------------------------------------------------------------------- +local function TestTwoFacesDownHead( Proc) + -- verifico ci siano due facce + if Proc.Fct ~= 2 then return false end + -- verifico se da lavorare con testa da sotto + local bDownHead = false + if BD.DOWN_HEAD then + 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) + local vtNm = ( vtN[1] + vtN[2]) ; vtNm:normalize() + bDownHead = ( vtNm:getZ() < -0.5) + end + return bDownHead +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 attiva 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 attiva 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 attiva 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.7 * _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 + -- verifico se da lavorare con testa da sotto + local bDownHead = TestTwoFacesDownHead( Proc) + -- 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' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead) + end + else + return LongCut.Make( Proc, _nPhase, _nRawId, _nPartId) + end + else + if bUseBlade then + return Fbs.MakeTwo( Proc, _nPhase, _nRawId, _nPartId, _dOvmHead, 'HeadSide' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead) + 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 = TestTwoFacesDownHead( Proc) + if BD.DOWN_HEAD then + 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) + 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 dDimMin, dDimMax, dDepth, vtOrtho, nLongFaceId, nSurfInt = GetTunnelDimension( Proc) + local nOk, sErr = MakeChamfer( Proc, 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 \ No newline at end of file