-- ProcessLongDoubleCut.lua by Egaltech s.r.l. 2021/05/18 -- Gestione calcolo doppio taglio longitudinale per Travi -- 2021/05/18 Possibile taglio con lama anche di fianco su macchina con testa da sotto. -- Tabella per definizione modulo local ProcessLong2Cut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') EgtOutLog( ' ProcessLongDoubleCut started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') local dLimMinPiece = BD.LEN_SHORT_PART or 1000 --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessLong2Cut.Identify( Proc) return ( Proc.Grp == 0 and Proc.Prc == 12) end --------------------------------------------------------------------- -- Identificazione delle facce della feature. -- Ritorna quattro valori : -- flag delle facce limitanti (0= no, 1= a destra, 2= a sinistra, 3= entrambe) -- vettore indici facce longitudinali -- vettore dei centri delle facce longitudinali -- vettore dei centri delle normali local function IdentifyFaces( Proc) local nFaceLimit = 0 local tFaceLong = {} local tptC = {} local tvtN = {} -- verifico le normali delle facce local nFacetCnt = EgtSurfTmFacetCount( Proc.Id) for i = 1, nFacetCnt do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) -- se è una faccia limite a sinistra if vtN:getX() > GEO.EPS_SMALL then nFaceLimit = nFaceLimit | 2 -- se è una faccia limite a destra elseif vtN:getX() < -GEO.EPS_SMALL then nFaceLimit = nFaceLimit | 1 -- altrimenti è una faccia longitudinale else local nInd = #tFaceLong + 1 tFaceLong[nInd] = i-1 tptC[nInd], tvtN[nInd] = EgtSurfTmFacetCenter( Proc.Id, ( i-1), GDB_ID.ROOT) end end return nFaceLimit, tFaceLong, tptC, tvtN end --------------------------------------------------------------------- -- Classificazione della feature function ProcessLong2Cut.Classify( Proc) local nUseMillOnSide = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0 -- se richiesto utensile di fianco if nUseMillOnSide > 0 then -- carico i dati delle face già inserite nelle opportune tabelle local nFaceLimit, tFaceLong, _, vtN = IdentifyFaces( Proc) -- verifico posizione (+1=sopra, -1=sotto, 0=sui lati) local nSide = 0 if vtN[1]:getZ() > -10 * GEO.EPS_SMALL and vtN[2]:getZ() > -10 * GEO.EPS_SMALL then nSide = 1 elseif vtN[1]:getZ() < -10 * GEO.EPS_SMALL and vtN[2]:getZ() < -10 * GEO.EPS_SMALL then nSide = -1 end -- angolo diedro per stabilire se taglio convesso local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, tFaceLong[1], tFaceLong[2], GDB_ID.ROOT) local bConvex if bAdj then bConvex = ( dAng >= 0) else bConvex = true end -- se feature di fianco e facce concave per lavorazione impossibile if nSide == 0 and not bConvex then -- do errore perchè su un lato entra nel pezzo (entra nel lato sopra) Proc.ErrMsg = 'Error : impossible to machinine with tool on side' return false, false end end return true, false end --------------------------------------------------------------------- function ProcessLong2Cut.GetLongFacesCount( Proc) local nLongFaces = 0 local nFacetCnt = EgtSurfTmFacetCount( Proc.Id) for i = 1, nFacetCnt do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) if abs( vtN:getX()) < GEO.EPS_SMALL then nLongFaces = nLongFaces + 1 end end return nLongFaces end --------------------------------------------------------------------- local function MakeSideFace( nId, nFac, nSide, sMilling, dToolDiam, nL2CSide) -- inserisco la lavorazione local sNameF = 'L2C_' .. ( EgtGetName( nId) or tostring( nId)) .. '_' .. tostring( nFac) local nMchFId = EgtAddMachining( sNameF, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ nId, nFac}}) -- lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- uso della faccia local nFaceUse = EgtIf( nSide == 1, MCH_MILL_FU.ORTHO_RIGHT, MCH_MILL_FU.ORTHO_LEFT) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- annullo offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, 0) -- attacco e uscita EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + 30) EgtSetMachiningParam( MCH_MP.LOPERP, 0) EgtSetMachiningParam( MCH_MP.LOTANG, dToolDiam / 2 + 30) -- se faccia di fianco e testa da sotto, aumento la sicurezza if nL2CSide == 0 and BD.DOWN_HEAD then EgtSetMachiningParam( MCH_MP.STARTPOS, 80) end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end --------------------------------------------------------------------- -- Applicazione della lavorazione local function MakeByPocketing( Proc, nPhase, nRawId, nPartId, nSide, nFacInd, dFacElev) -- cerco la svuotatura opportuna local sPockType = EgtIf( nSide ~=1 and BD.DOWN_HEAD, 'OpenPocket_H2', 'OpenPocket') local sPocketing = ML.FindPocketing( sPockType, Proc.Box:getDimX()) if not sPocketing then local sErr = 'Error : OpenPocket not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dMaxDepth = 0 if EgtMdbSetCurrMachining( sPocketing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMaxDepth = ( EgtTdbGetCurrToolMaxDepth() or dMaxDepth) end end -- inserisco la lavorazione 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, nFacInd}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) -- imposto attacco per tasca aperta EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local sWarn if dFacElev > dMaxDepth + 10 * GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxDepth - dFacElev) dFacElev = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dFacElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessLong2Cut.Make( Proc, nPhase, nRawId, nPartId, bForcedBladeMaster, nUseSideToolMaster) local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- carico i dati delle face già inserite nelle opportune tabelle local nFaceLimit, tFaceLong, ptC, vtN = IdentifyFaces( Proc) local dLen = Proc.Box:getDimX() -- verifico posizione (+1=sopra, -1=sotto, 0=sui lati) local nSide = 0 if vtN[1]:getZ() > -10 * GEO.EPS_SMALL and vtN[2]:getZ() > -10 * GEO.EPS_SMALL then nSide = 1 elseif vtN[1]:getZ() < -10 * GEO.EPS_SMALL and vtN[2]:getZ() < -10 * GEO.EPS_SMALL then nSide = -1 end -- angolo diedro per stabilire se taglio convesso local bInt, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, tFaceLong[1], tFaceLong[2], GDB_ID.ROOT) local bConvex local bOrtho local ptM if bInt then bConvex = ( dAng >= 0) bOrtho = ( abs( dAng + 90) < 1) ptM = ( ptP1 + ptP2) / 2 else bConvex = true bOrtho = false ptM = ( ptC[1] + ptC[2]) / 2 end local ptRef = ( ptC[1] + ptC[2]) / 2 -- analisi del taglio local vOrd = {} local vFaceUse = {} if nSide == 1 or ( nSide == -1 and BD.DOWN_HEAD) then vOrd = EgtIf( ptC[1]:getY() < ptRef:getY(), { 1, 2}, { 2, 1}) vFaceUse = { BL.GetNearestOrthoOpposite( ptC[1] - ptM), BL.GetNearestOrthoOpposite( ptC[2] - ptM)} elseif nSide == -1 then vOrd = EgtIf( ptC[1]:getY() < ptM:getY(), { 1, 2}, { 2, 1}) vFaceUse = { BL.GetNearestParalOpposite( ptC[1] - ptM), BL.GetNearestParalOpposite( ptC[2] - ptM)} else local bFront = ( vtN[1]:getY() < 0) if bFront then vOrd = EgtIf( ptC[1]:getZ() < ptM:getZ(), { 1, 2}, { 2, 1}) vFaceUse = { BL.GetNearestOrthoOpposite( ptC[1] - ptM), BL.GetNearestOrthoOpposite( ptC[2] - ptM)} else vOrd = EgtIf( ptC[1]:getZ() < ptM:getZ(), { 2, 1}, { 1, 2}) vFaceUse = { BL.GetNearestOrthoOpposite( ptC[1] - ptM), BL.GetNearestOrthoOpposite( ptC[2] - ptM)} end end local vWidth = {} _, _, vWidth[1] = BL.GetFaceHvRefDim( Proc.Id, tFaceLong[1]) _, _, vWidth[2] = BL.GetFaceHvRefDim( Proc.Id, tFaceLong[2]) -- ottengo la distanza tra la fine del pezzo e il pezzo successivo local dDistToNextPiece = EgtGetInfo( nRawId, 'BDST', 'd') or 5.4 local bForcedLim local sWarn ---------------------------------------------------------------------------------------------------------------------------------------- -- 2020/09/17 Fabio Squaratti: se sono attivi entrambe i Q01 (lavorare con lama) e Q03 (lavorare con fresa di fianco anche da sopra) -- allora vince il Q3, cioè si utilizza la fresa di fianco ( per i tagli da sopra) -- 2020/09/17 Fabio Squaratti: se lavorazione con fresa di fianco e se ci sono delle facce laterali, l'utensile deve arrivare -- fino al punto più vicino della faccia laterale (prima l'arretramento era sempre del raggio utensile). -- Questo viene fatto se Q03=1 o fresa da sotto ---------------------------------------------------------------------------------------------------------------------------------------- local bUseBlade local nUseMillOnSide -- se presenti utilizzo i parametri dell'eventuale lua "padre" if bForcedBladeMaster ~= nil then bUseBlade = bForcedBladeMaster else bUseBlade = EgtGetInfo( Proc.Id, 'Q01', 'i') == 1 end if nUseSideToolMaster ~= nil then nUseMillOnSide = nUseSideToolMaster else nUseMillOnSide = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0 end -- se entrambe i Q sono attivi, disabilito lama if nUseMillOnSide > 0 then bUseBlade = false end -- Se senza facce limitanti, da sopra e richiesto con doppio taglio di lama if nFaceLimit == 0 and ( nSide == 1 or ( nSide == 0 and BD.DOWN_HEAD)) and bUseBlade and b3Solid:getDimX() > dLimMinPiece - 1 then -- recupero la lavorazione local sCutting = ML.FindCutting( 'HeadSide') if not sCutting then local sErr = 'Error : HeadSide not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dToolDiam = 0 local dMaxDepth = 0 local dToolThick = 0 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth dToolThick = EgtTdbGetCurrToolParam(MCH_TP.THICK) or dToolThick end end -- se la distanza dal pezzo successivo è inferiore della metà lama, do un warning if dDistToNextPiece < dToolDiam/2 then sWarn = 'Warning : Cut machining can damage next piece' EgtOutLog( sWarn) end -- determino numero di parti local dStartAccDist = BD.LONGCUT_ENDLEN local dEndAccDist = BD.LONGCUT_ENDLEN local nC = ceil( ( dLen - dStartAccDist - dEndAccDist) / BD.LONGCUT_MAXLEN) local dC = 0 if nC > 0 then dC = ( dLen - dStartAccDist - dEndAccDist) / nC if dC < min( dStartAccDist, dEndAccDist) then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end nC = nC + 2 else if dLen > min( dStartAccDist, dEndAccDist) then nC = 2 dStartAccDist = dLen / 2 dEndAccDist = dStartAccDist else nC = 1 dStartAccDist = 0 dEndAccDist = 0 end end local dDimStrip = EgtIf( nSide ~= 0, BD.DIM_STRIP_SMALL, BD.DIM_STRIP) local nM = 0 -- se convesso lavoro ogni faccia in due metà lasciando attaccata la parte centrale if bConvex then -- si percorrono i lati alto e basso della faccia for i = 1, nC do -- Posizione braccio portatesta local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = EgtIf( ( i == 1 or i == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) end -- ciclo sulle due facce for j = 1, #vOrd do -- determino se lavorazione da davanti o da dietro local bFront = ( vtN[vOrd[j]]:getY() < 0) -- determino l'utilizzo della faccia local nFaceUse = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_TOP, EgtIf( bFront, MCH_MILL_FU.ORTHO_BACK, MCH_MILL_FU.ORTHO_FRONT)) local nFaceUse2 = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_DOWN, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) -- ciclo sulle passate local dOffset = ( vWidth[vOrd[j]] + dDimStrip) / 2 ; local dLioTang = 0 local dLioPerp = ( vWidth[vOrd[j]] - dDimStrip) / 2 + BD.CUT_SIC ; for k = 1, 2 do -- inserisco le parti di lavorazione nM = nM + 1 local sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) .. '_' .. tostring(j) local nMchFId = EgtAddMachining( sNameF, sCutting) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sCutting EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vOrd[j]-1}}) -- limito opportunamente la lavorazione local dSal = EgtIf( i == nC, 0, - dEndAccDist - ( nC - i - 1) * dC) local dEal = EgtIf( i == 1, 0, - dStartAccDist - ( i - 2) * dC) if ( not bFront and k == 1) or ( bFront and k == 2) then dSal, dEal = dEal, dSal end EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, dOffset) -- imposto attacco/uscita EgtSetMachiningParam( MCH_MP.LITANG, dLioTang) EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOTANG, dLioTang) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto uso della faccia EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( k == 1, nFaceUse, nFaceUse2)) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end end -- altrimenti concavo else -- si percorrono i lati alto e basso della faccia for i = 1, nC do -- Posizione braccio portatesta local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = EgtIf( ( i == 1 or i == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) end -- ciclo sulle due facce for j = 1, #vOrd do -- determino se lavorazione da davanti o da dietro local bFront = ( vtN[vOrd[j]]:getY() < 0) -- determino l'utilizzo della faccia local nFaceUse = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_TOP, EgtIf( bFront, MCH_MILL_FU.ORTHO_BACK, MCH_MILL_FU.ORTHO_FRONT)) local nFaceUse2 = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_DOWN, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) -- ciclo sulle passate local dOffset local dLioPerp if j == 1 then -- il primo taglio lo faccio completo se angolo interno maggiore di 90 -- se angolo interno inferiore di 90° calcolo l'arretramento della lama + un piccolo delta di 0.3 if dAng < - ( 90 + 10 * GEO.EPS_SMALL) then dOffset = 0.3 + ((dToolThick* vtN[vOrd[1]]) * vtN[vOrd[2]] * vtN[vOrd[2]]):len() else dOffset = 0 end dLioPerp = vWidth[vOrd[j]] + BD.CUT_SIC else -- il secondo ridotto della distanza minima e della componente spessore della lama dOffset = dDimStrip + ((dToolThick* vtN[vOrd[1]]) - (dToolThick* vtN[vOrd[1]]) * vtN[vOrd[2]] * vtN[vOrd[2]]):len() dLioPerp = vWidth[vOrd[j]] - dOffset + BD.CUT_SIC end local dLioTang = 0 local sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) local nMchFId = EgtAddMachining( sNameF, sCutting) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sCutting EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vOrd[j]-1}}) -- limito opportunamente la lavorazione local dSal = EgtIf( i == nC, 0, - dEndAccDist - ( nC - i - 1) * dC) local dEal = EgtIf( i == 1, 0, - dStartAccDist - ( i - 2) * dC) if ( bFront) then dSal, dEal = dEal, dSal end EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, dOffset) -- imposto attacco/uscita EgtSetMachiningParam( MCH_MP.LITANG, dLioTang) EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOTANG, dLioTang) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto uso della faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse2) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end end -- se non è sotto e non uso fresa di fianco: lavorazione Long2Cut elseif ( nSide ~= - 1 or BD.DOWN_HEAD) and nUseMillOnSide == 0 then -- determino la massima elevazione local dElev = 0 local dFacElev1 = BL.GetFaceElevation( Proc.Id, tFaceLong[1], nPartId) local dFacElev2 = BL.GetFaceElevation( Proc.Id, tFaceLong[2], nPartId) -- 03/12/2020 -- se facce concave e a 90 gradi, prendo l'elevazione minima if bOrtho then dElev = min( dFacElev1, dFacElev2) else dElev = max( dFacElev1, dFacElev2) end -- recupero la lavorazione local sMilling = ML.FindMilling( 'Long2Cut', dElev) if not sMilling then local sErr = 'Error : Long2Cut not found in library' EgtOutLog( sErr) return false, sErr end -- se angolo compreso è inferiore ai 90 gradi do errore if dAng and dAng < - ( 90 + 10 * GEO.EPS_ANG_SMALL) then local sErr = 'Error : Impossible use a mill with angle less than 90' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dToolDiam = 0 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end -- se la fine (a sinistra) non è limitata e ho un pezzo successivo più distante da metà raggio. setto la fine come limitata if dDistToNextPiece < dToolDiam/2 and nFaceLimit < 2 then bForcedLim = true nFaceLimit = nFaceLimit + 2 end -- se chiuso e corto, applico svuotatura con fresa opportuna if nFaceLimit == 3 and Proc.Box:getDimX() < 2 * dToolDiam then -- svuotatura della prima faccia longitudinale local bOk, sErr = MakeByPocketing( Proc, nPhase, nRawId, nPartId, nSide, tFaceLong[1], dFacElev1) -- svuotatura della seconda faccia longitudinale if not bOk then return bOk, sErr end return MakeByPocketing( Proc, nPhase, nRawId, nPartId, nSide, tFaceLong[2], dFacElev2) end -- determino gli estremi local dStartDist = 0 local dStartAccDist = BD.LONGCUT_ENDLEN local bStartFixed = true -- se ho faccia limite a destra if nFaceLimit == 1 or nFaceLimit == 3 then dStartDist = dToolDiam / 2 dStartAccDist = BD.LONGCUT_MAXLEN bStartFixed = false end local dEndDist = 0 local dEndAccDist = BD.LONGCUT_ENDLEN local bEndFixed = true -- se ho faccia limite a sinistra if nFaceLimit >= 2 then dEndDist = dToolDiam / 2 dEndAccDist = BD.LONGCUT_MAXLEN bEndFixed = false end -- determino il numero di parti in cui dividere la lavorazione local nC = ceil( ( dLen - dStartAccDist - dEndAccDist) / BD.LONGCUT_MAXLEN) local dC = 0 if nC > 0 then local nIncStep = 2 if bStartFixed and bEndFixed then dC = ( dLen - dStartAccDist - dEndAccDist) / nC -- se distanza rimanente è < della metà del minimo della distanza estremi allora aggiungo un passo in più local dMinDist = EgtIf( min( dStartAccDist, dEndAccDist) / 2 > 300 , 300, min( dStartAccDist, dEndAccDist) / 2) if dC < dMinDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC nIncStep = 1 elseif dC < min( dStartAccDist, dEndAccDist) then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end elseif bStartFixed then dC = ( dLen - dStartAccDist) / ( nC + 1) dEndAccDist = dC if dC < dStartAccDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end elseif bEndFixed then dC = ( dLen - dEndAccDist) / ( nC + 1) dStartAccDist = dC if dC < dEndAccDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end else dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end nC = nC + nIncStep else if dLen > min( dStartAccDist, dEndAccDist) then nC = 2 if bStartFixed and not bEndFixed then dStartAccDist = min( dStartAccDist, dLen/2) dEndAccDist = dLen - dStartAccDist elseif not bStartFixed and bEndFixed then dEndAccDist = min( dEndAccDist, dLen/2) dStartAccDist = dLen - dEndAccDist else dStartAccDist = dLen/2 dEndAccDist = dStartAccDist end else nC = 1 dStartAccDist = 0 dEndAccDist = 0 end end local nIni, nFin = 1, 2 local dLimitAngle = -0.5 - 20 * GEO.EPS_SMALL -- se facce ortogonali (concave), mantengo la lavorazione di testa sulla faccia più grande purchè non superi di 30 gradi il sottosquadra if bOrtho then if vtN[vOrd[1]]:getZ() > 0.001 and vtN[vOrd[2]]:getZ() > 0.001 then if vtN[vOrd[1]]:getZ() >= vtN[vOrd[2]]:getZ() then nFin = 1 else nIni = 2 end else if vtN[vOrd[1]]:getZ() < dLimitAngle then nIni = 2 elseif vtN[vOrd[2]]:getZ() < dLimitAngle then nFin = 1 else if vtN[vOrd[1]]:getZ() >= vtN[vOrd[2]]:getZ() then if vtN[vOrd[2]]:getZ() < dLimitAngle then nFin = 1 else nIni = 2 end else if vtN[vOrd[1]]:getZ() < dLimitAngle then nIni = 2 else nFin = 1 end end end end end -- ciclo sulle parti local nM = 0 for j = 1, nC do -- su entrambe le facce for i = nIni, nFin do -- Limitazioni della lavorazione local nPos = EgtIf( i == 1, j, nC - j + 1) local dSal = EgtIf( nPos == 1, - EgtIf( i == nIni, dStartDist, dEndDist), - EgtIf( i == nIni, dStartAccDist, dEndAccDist) - ( nPos - 2) * dC) local dEal = EgtIf( nPos == nC, - EgtIf( i == nIni, dEndDist, dStartDist), - EgtIf( i == nIni, dEndAccDist, dStartAccDist) - ( nC - nPos - 1) * dC) -- Posizione braccio portatesta local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = EgtIf( ( j == 1 or j == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) end -- Verifico se da fare di fianco perchè normale troppo verso il basso (minore di -30deg) local bSide = ( vtN[vOrd[i]]:getZ() < dLimitAngle and not BD.DOWN_HEAD) -- ciclo sulle passate local nO = 1 local dStep = 0 local dAgg = EgtIf( bConvex, 2 * BD.CUT_EXTRA, BD.CUT_EXTRA) local dLargh = vWidth[vOrd[i]] if not bSide and dLargh > 0.8 * dToolDiam then nO = ceil( dLargh / ( 0.6 * dToolDiam)) if nO > 1 then dStep = dLargh / nO end end for k = 1, nO do -- inserisco le parti di lavorazione nM = nM + 1 local sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) local nMchFId = EgtAddMachining( sNameF, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, tFaceLong[vOrd[i]]}}) -- limito opportunamente la lavorazione EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto uso faccia EgtOutLog( 'FaceUse='..tostring( vFaceUse[vOrd[i]])) --EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bSide, BL.GetParallelOpposite( vFaceUse[vOrd[i]]), vFaceUse[vOrd[i]])) EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bSide, MCH_MILL_FU.PARAL_DOWN, vFaceUse[vOrd[i]])) -- imposto lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bSide, true, false)) -- imposto offset radiale (nullo se concavo o di lato) local dOffsR = EgtIf( k < nO, ( nO - k) * dStep, EgtIf( bConvex, - BD.CUT_EXTRA, 0)) if bSide then dOffsR = 0 end EgtSetMachiningParam( MCH_MP.OFFSR, dOffsR) -- se di lato, imposto offset longitudinale if bSide then EgtSetMachiningParam( MCH_MP.OFFSL, - BD.CUT_EXTRA) end -- attacco e uscita local dLioPerp = EgtIf( bSide, dToolDiam, dLargh - dOffsR + BD.CUT_SIC) EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) -- se faccia di fianco e testa da sotto, aumento la sicurezza if nSide == 0 and BD.DOWN_HEAD then EgtSetMachiningParam( MCH_MP.STARTPOS, 80) end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- se facce principali convesse, eventuale lavorazione della faccia limitante l'inizio (a destra) if bConvex and j == 1 and not bStartFixed then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], 1, sMilling, dToolDiam, nSide) end -- se facce principali convesse, eventuale lavorazione della faccia limitante la fine (a sinistra) if bConvex and j == nC and not bEndFixed then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], -1, sMilling, dToolDiam, nSide) end end end -- altrimenti è sotto : lavorazione Long2CutDown else -- da Analisi con Fabio Squaratti 15/09/2020 -- variabile che indica se ripassare sul raggio rimasto dalla lavorazione di fianco local bRemoveToolRadius -- se nExtendMach = 0 la lavorazione rimane arretrata dalla fine della faccia del raggio utensile -- se nExtendMach = 1 la lavorazione arriva fino alla fine faccia (se non ha facce limite) ignorando il pezzo successivo -- se nExtendMach = 2 la lavorazione viene estesa ma arretra per non segnare il pezzo successivo (se non ha facce limite) local nExtendMach -- recupero la lavorazione local sMilling local sPrefix if nSide ~= - 1 then sMilling = ML.FindMilling( 'Long2CutSide') sPrefix = 'L2CS_' nExtendMach = nUseMillOnSide if nUseMillOnSide == 2 then bRemoveToolRadius = true -- nExtendMach = 0 -- arretro la lavorazione del raggio utensile (se non ha facce limite) end -- lavorazione da sotto else sMilling = ML.FindMilling( 'Long2CutDown') sPrefix = 'L2CD_' nExtendMach = 1 if nUseMillOnSide ~= 1 then nExtendMach = 2 -- arretro il minimo indispensabile per non segnare il pezzo successivo (se non ha facce limite) end end if not sMilling then local sErr = 'Error : Long2CutSide or Long2CutDown not found in library' EgtOutLog( sErr) return false, sErr end -- se angolo compreso è inferiore ai 90 gradi do errore if dAng < - ( 90 + 10 * GEO.EPS_SMALL) then local sErr = 'Error : Impossible use a mill with angle less than 90' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dToolDiam = 0 local dMaxDepth = 0 local dThDiam = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam end end local dDistToEnd = dToolDiam / 2 -- se fresa di fianco o da sotto calcolo quanto l'utensile può andare vicino al limite se l'elevazione della faccia è minore del raggio utensile if nUseMillOnSide <= 1 or nSide == -1 then -- calcolo l'elevazione della faccia principale local dFacElev1 = BL.GetFaceElevation( Proc.Id, tFaceLong[vOrd[1]], nPartId) local dFacElev2 = BL.GetFaceElevation( Proc.Id, tFaceLong[vOrd[2]], nPartId) local dFacElev = max( dFacElev1, dFacElev2) if dFacElev < dDistToEnd then dDistToEnd = sqrt( ( ( dToolDiam / 2) * ( dToolDiam / 2)) - ( ( dToolDiam / 2 - dFacElev) * (dToolDiam / 2 - dFacElev))) end end -- se la fine è già limitata allora setto per arretrare del raggio utensile if nFaceLimit >= 2 then nExtendMach = 0 -- se la fine non è limitata e ho un pezzo successivo distante meno di metà raggio. setto la fine come limitata elseif dDistToNextPiece < dDistToEnd and nExtendMach ~= 1 then nFaceLimit = nFaceLimit + 2 end -- aggiuntivo sull'affondamento local dAgg = EgtIf( bConvex, BD.CUT_EXTRA, 0) -- determino gli estremi local dStartDist = 0 local dStartAccDist = BD.LONGCUT_ENDLEN local bStartFixed = true -- se ho facce limite a destra if nFaceLimit == 1 or nFaceLimit == 3 then dStartDist = dDistToEnd dStartAccDist = BD.LONGCUT_MAXLEN bStartFixed = false end local dEndDist = 0 local dEndAccDist = BD.LONGCUT_ENDLEN local bEndFixed = true -- se ho facce limite a sinistra if nFaceLimit >= 2 then dEndDist = EgtIf( nExtendMach == 2, dDistToEnd - dDistToNextPiece + 0.5, dDistToEnd) dEndAccDist = BD.LONGCUT_MAXLEN bEndFixed = false end -- determino il numero di parti in cui dividere la lavorazione local nC = ceil( ( dLen - dStartAccDist - dEndAccDist) / BD.LONGCUT_MAXLEN) local dC = 0 if nC > 0 then if bStartFixed and bEndFixed then dC = ( dLen - dStartAccDist - dEndAccDist) / nC elseif bStartFixed then dC = ( dLen - dStartAccDist) / ( nC + 1) dEndAccDist = dC elseif bEndFixed then dC = ( dLen - dEndAccDist) / ( nC + 1) dStartAccDist = dC else dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end nC = nC + 2 else if dLen > min( dStartAccDist, dEndAccDist) then nC = 2 if bStartFixed and not bEndFixed then dStartAccDist = min( dStartAccDist, dLen/2) dEndAccDist = dLen - dStartAccDist elseif not bStartFixed and bEndFixed then dEndAccDist = min( dEndAccDist, dLen/2) dStartAccDist = dLen - dEndAccDist else dStartAccDist = dLen/2 dEndAccDist = dStartAccDist end else nC = 1 dStartAccDist = 0 dEndAccDist = 0 end end -- ciclo sulle parti local nM = 0 for j = 1, nC do local nIni, nFin = 1, 2 local nDir = 1 -- se facce ortogonali (concave) controllo se con la lavorazione della prima faccia il diametro copre la seconda (e non la eseguo) if bOrtho then -- se da sotto scelgo la faccia (lavorta col fianco utensile) con direzione più sottosquadra if nSide == -1 and vtN[vOrd[1]]:getZ() < -0.001 and vtN[vOrd[2]]:getZ() < -0.001 then -- se gli angoli delle due facce sono uguali ( sotto il grado di differenza) sgelgo la faccia più vicina a un fianco if abs(vtN[vOrd[1]]:getZ() - vtN[vOrd[2]]:getZ()) < 0.017 then -- se punto medio più vicino al lato dietro if b3Solid:getMax():getY() - ptM:getY() < ptM:getY() - b3Solid:getMin():getY() then -- se prima faccia più vicina alla faccia dietro eseguo prima questa if ptC[vOrd[1]]:getY() > ptC[vOrd[2]]:getY() then if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end -- se è più lontana inverto la direzione di lavoro else -- inverto la direzione di lavorazione delle facce nDir = -1 nIni, nFin = 2, 1 if dToolDiam > vWidth[vOrd[1]] then nFin = 2 end end -- altrimenti punto medio più vicino al lato davanti else -- se prima faccia più vicina alla faccia dietro inverto la direzione di lavorazione if ptC[vOrd[1]]:getY() > ptC[vOrd[2]]:getY() then -- inverto la direzione di lavorazione delle facce nDir = -1 nIni, nFin = 2, 1 if dToolDiam > vWidth[vOrd[1]] then nFin = 2 end else if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end end end elseif vtN[vOrd[2]]:getZ() < vtN[vOrd[1]]:getZ() then -- inverto la direzione di lavorazione delle facce nDir = -1 nIni, nFin = 2, 1 if dToolDiam > vWidth[vOrd[1]] then nFin = 2 end else if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end end -- in tutti gli altri casi else if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end end end -- su entrambe le facce for i = nIni, nFin, nDir do -- Limitazioni della lavorazione local nPos = EgtIf( i == 1, j, nC - j + 1) local dSal = EgtIf( nPos == 1, - EgtIf( i == nIni, dStartDist, dEndDist), - EgtIf( i == nIni, dStartAccDist, dEndAccDist) - ( nPos - 2) * dC) local dEal = EgtIf( nPos == nC, - EgtIf( i == nIni, dEndDist, dStartDist), - EgtIf( i == nIni, dEndAccDist, dStartAccDist) - ( nC - nPos - 1) * dC) -- Posizione braccio portatesta local nSCC = EgtIf( BD.C_SIMM, MCH_SCC.NONE, MCH_SCC.ADIR_XP) -- inserisco le parti di lavorazione nM = nM + 1 local sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) local nMchFId = EgtAddMachining( sNameF, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, tFaceLong[vOrd[i]]}}) -- limito opportunamente la lavorazione EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto uso faccia if nUseMillOnSide > 0 and nSide ~= -1 then if nSide == 1 then if bConvex then if vtN[vOrd[i]]:getZ() > 0.866 then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_TOP) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) else EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) end -- se concavo else local vFaceUse2 = BL.GetNearestParalOpposite( vtN[EgtIf(vOrd[i] == 1, 2, 1)]) EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse2) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) end else if bConvex then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) if vtN[vOrd[i]]:getZ() >= 0 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) end else -- lascio lo stesso le lavorazioni anche se viene intercettato l'errore local vFaceUse2 = BL.GetNearestParalOpposite( vtN[EgtIf(vOrd[i] == 1, 2, 1)]) EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse2) if vtN[vOrd[i]]:getZ() < 0 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) end end end else EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse[vOrd[i]]) end -- imposto lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) EgtSetMachiningParam( MCH_MP.INVERT, true) local dNz = vtN[vOrd[i]]:getZ() -- nel caso concavo, devo impostare la lunghezza di attacco ortogonale if not bConvex then -- local dLioPerp = vWidth[vOrd[i]] * EgtIf( abs(dNz) < GEO.EPS_SMALL, 1, sqrt( 1 - dNz * dNz) / abs( dNz)) + BD.COLL_SIC local dLioPerp = vWidth[ EgtIf( vOrd[i] == 1, 2,1)] + BD.COLL_SIC EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) end -- verifico massimo affondamento (tengo conto dell'inclinazione utensile e della pinza con estremità conica) -- 08/09/2020 tolti i 3mm ( per la ghiera smussata) perchè nella verifica collisione vine creato un cilindro non smussato che rileva la collisione -- local dCollSic = max( BD.COLL_SIC, ( dThDiam - dToolDiam) / 2 * abs( vtN[vOrd[i]]:getY() / vtN[vOrd[i]]:getZ()) - 3) local dCollSic = max( BD.COLL_SIC, ( dThDiam - dToolDiam) / 2 * EgtIf( abs(dNz) < GEO.EPS_SMALL, 1, abs( vtN[vOrd[i]]:getY() / dNz))) if vWidth[vOrd[i]] + dAgg > dMaxDepth - dCollSic then sWarn = 'Warning in LongDoubleCut : depth (' .. EgtNumToString( vWidth[vOrd[i]] + dAgg, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth - dCollSic, 1) .. ')' end local dDepth = min( dMaxDepth - dCollSic, vWidth[vOrd[i]] + dAgg) EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- se facce principali convesse, eventuale lavorazione della faccia limitante l'inizio (a destra) if bConvex and j == 1 and not bStartFixed and bRemoveToolRadius then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], 1, sMilling, dToolDiam) end -- se facce principali convesse, eventuale lavorazione della faccia limitante la fine (a sinistra) if bConvex and j == nC and not bEndFixed and bRemoveToolRadius then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], -1, sMilling, dToolDiam) end end end end return true, sWarn end --------------------------------------------------------------------- return ProcessLong2Cut