-- ProcessSawCut.lua by Egaltech s.r.l. 2022/12/19 -- Gestione calcolo taglio di lama per Travi -- 2022/06/10 Aggiunto il parametro dOvmTail per gestire sovramateriali in coda diversi da OVM_MID (sezioni alte e larghe). -- 2022/12/19 Aggiunta gestione testa da sotto. -- 2024/01/18 Implementata GetBlockedAxis che gestisce gli assi bloccati per tutti i tipi di utensile. -- Tabella per definizione modulo local ProcessSawCut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local DC = require( 'DiceCut') local Cut = require( 'ProcessCut') local LongCut = require( 'ProcessLongCut') EgtOutLog( ' ProcessSawCut started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessSawCut.Identify( Proc) return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 13) end --------------------------------------------------------------------- -- Classificazione della feature function ProcessSawCut.Classify( Proc, b3Raw) -- recupero i dati del versore direzione di accesso della lavorazione local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if not AuxId then return false end AuxId = AuxId + Proc.Id local vtDir = EgtSV( AuxId, GDB_ID.ROOT) return true, ( vtDir:getZ() <= - 0.5) end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessSawCut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead, dOvmTail) -- sovramateriale di coda dOvmTail = dOvmTail or BD.OVM_MID -- ingombro del grezzo local b3Raw = EgtGetRawPartBBox( nRawId) -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( nPartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error on process ' .. tostring( Proc.Id) .. ' part box not found' EgtOutLog( sErr) return false, sErr end -- recupero e verifico l'entità vettore local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.GEO_VECTOR then local sErr = 'Error on process ' .. tostring( Proc.Id) .. ' missing access direction' EgtOutLog( sErr) return false, sErr end local vtDir = EgtSV( AuxId, GDB_ID.ROOT) -- dati geometrici del taglio local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) local frFace = Frame3d( ptC, vtDir ^ vtN, vtDir, vtN) local b3Face = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFace) local dLen = b3Face:getDimX() local dWidth = b3Face:getDimY() -- se taglio di testa if Proc.Head then -- se coincide con il taglio di separazione precedente, non va fatto if AreSameVectorApprox( vtN, X_AX()) and abs( ptC:getX() - b3Raw:getMax():getX() + dOvmHead) < 10 * GEO.EPS_SMALL then return true end -- altrimenti taglio di coda else -- se coincide con taglio di separazione, non va fatto if AreSameVectorApprox( vtN, - X_AX()) and abs( ptC:getX() - b3Raw:getMin():getX()) < dOvmTail + 10 * GEO.EPS_SMALL then return true end end -- recupero flag per inizio e fine interni local bInside = (( EgtGetInfo( Proc.Id, 'Q01', 'i') or 0) ~= 0) -- abilitazione lavorazione da sotto local bDownHead = ( BD.DOWN_HEAD and vtDir:getZ() < -0.341) local bTopHead = ( BD.DOWN_HEAD and ( vtDir:getZ() > -0.342 or not bDownHead)) -- recupero la lavorazione local sCutting sCutting, bDownHead = ML.FindCutting( 'HeadSide', bTopHead, bDownHead) if not sCutting then local sErr = 'Error on process ' .. tostring( Proc.Id) .. ' cutting not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 2 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam dSawThick = EgtTdbGetCurrToolParam(MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end -- determino se lavorazione da davanti o da dietro e se da sotto local bFront = ( vtDir ^ vtN):getX() > 0 local bDownUp = ( not bDownHead and vtN:getZ() < -0.259) local bFillAreaPiece -- se non da sotto if not bDownUp then -- se poco inclinata ( inclinazione inferiore a 21.56 deg) if vtN:getZ() > 0.93 then -- verifico se la superfice è prevelentemente orizzontale con Z positiva e occupa tutta la trave o occupa sicuramente la faccia in Y -- e almeno 3/4 della lunghezza in X e sborda in X e non interessa la faccia inferiore, -- si possono far partire i tagli a cubetti dalla testa o lasciare il cordoncino centrale if ( ( abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL and abs( Proc.Box:getMax():getX() - b3Solid:getMax():getX()) < 10*GEO.EPS_SMALL) or ( ( abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL or abs( Proc.Box:getMax():getX() - b3Solid:getMax():getX()) < 10*GEO.EPS_SMALL) and ( Proc.Box:getDimX() > 0.75 * b3Solid:getDimX() or Proc.Box:getDimX() > 1500.000))) and abs( Proc.Box:getMin():getY() - b3Solid:getMin():getY()) < 10*GEO.EPS_SMALL and abs( Proc.Box:getMax():getY() - b3Solid:getMax():getY()) < 10*GEO.EPS_SMALL and b3Solid:getMin():getZ() < Proc.Box:getMin():getZ() - 100 * GEO.EPS_SMALL then bFillAreaPiece = true end -- se praticamente verticale di fianco ( inclinazione inferiore a 21.56deg) elseif abs( vtN:getY()) > 0.93 then -- se la faccia occupa tutta la trave in X e Z o occupa sicuramente la faccia in Z e almeno 3/4 della faccia in X e sborda in X, if ( ( abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL and abs( Proc.Box:getMax():getX() - b3Solid:getMax():getX()) < 10*GEO.EPS_SMALL) or ( ( abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL or abs( Proc.Box:getMax():getX() - b3Solid:getMax():getX()) < 10*GEO.EPS_SMALL) and ( Proc.Box:getDimX() > 0.75 * b3Solid:getDimX() or Proc.Box:getDimX() > 1500.000))) and abs( Proc.Box:getMin():getZ() - b3Solid:getMin():getZ()) < 10*GEO.EPS_SMALL and abs( Proc.Box:getMax():getZ() - b3Solid:getMax():getZ()) < 10*GEO.EPS_SMALL then local sErr = 'Error : Impossible to machine by orientation (on side)' EgtOutLog( sErr) return false, sErr end end end -- se ho il parametro Q04 = 1 e il taglio copre la lunghezza della trave allora lancio il processo dell'L10 local nAsLongCut = EgtGetInfo( Proc.Id, 'Q02', 'i') or 0 if nAsLongCut == 1 and bFillAreaPiece then return LongCut.Make( Proc, nPhase, nRawId, nPartId, true) -- se non ho taglio lungo passo al Cut per taglio a cubetti elseif bFillAreaPiece and abs(( vtDir ^ vtN):getY()) > 0.866 then local bOk, sErr = Cut.Make( Proc, nPhase, nRawId, nPartId, 0, false, true) -- se è andata a buon fine oppure ha fallito esco -- nel caso non ha fatto i tagli a cubetti (sErr vale -1) continuo if bOk or ( not bOk and type(sErr) ~= 'number') then return bOk, sErr end end -- determino affondamento e distanza interna da inizio e fine local dDepth = min( dWidth, dMaxDepth - BD.COLL_SIC) local dInsDist = 0 if bInside then dInsDist = sqrt( dSawDiam * dDepth - dDepth * dDepth) if 2 * dInsDist > dLen - 2 then dInsDist = ( dLen - 2) / 2 dDepth = dSawDiam / 2 - sqrt( dSawDiam * dSawDiam / 4 - dInsDist * dInsDist) end 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 / ( nC + 2) dStartAccDist = min( dC, dStartAccDist) dEndAccDist = min( dC, dEndAccDist) dC = ( dLen - dStartAccDist - dEndAccDist) / nC 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 -- determino l'utilizzo della faccia local nFaceUse = BL.GetNearestOrthoOpposite( vtDir) if bDownUp then nFaceUse = BL.GetOrtupOpposite( nFaceUse) end -- si percorrono i lati alto e basso della faccia for i = 1, nC do -- Posizione braccio portatesta local nSCC = EgtIf( ( BD.C_SIMM or i == 1 or i == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) if abs( vtDir:getY()) > 0.5 then nSCC = EgtIf( vtDir:getY() > 0, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) end -- ciclo sulle passate local dOffset = dWidth - dDepth ; local dLioTang = 0 local dLioPerp = dDepth + BD.CUT_SIC ; -- inserisco le parti di lavorazione local sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nC) 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, 0}}) -- limito opportunamente la lavorazione local dSal = EgtIf( i == 1, -dInsDist, -dStartAccDist - ( i - 2) * dC) local dEal = EgtIf( i == nC, -dInsDist, -dEndAccDist - ( nC - i - 1) * dC) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, dOffset) -- imposto offset longitudinale if Proc.Grp == 0 then EgtSetMachiningParam( MCH_MP.OFFSL, EgtIf( bDownUp, dSawThick / 2, -dSawThick / 2)) end -- imposto lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bFront ~= bDownUp, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) EgtSetMachiningParam( MCH_MP.INVERT, bFront) -- 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, nFaceUse) -- imposto angolo 3° asse rot local vtOut = EgtIf( vtN:getX() > 0, X_AX(), -X_AX()) EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sCutting, 'perpendicular', b3Raw, vtN, vtOut)) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true end --------------------------------------------------------------------- return ProcessSawCut