-- ProcessDtMortise.lua by Egaltech s.r.l. 2022/03/23 -- Gestione calcolo mortase a coda di rondine per Travi -- 2021/04/08 Aggiunto controllo massimo materiale lavorabile dalla fresa. -- 2021/04/08 Miglioria scelta lavorazione in presenza di testa da sotto. -- 2021/06/28 Aggiunta gestione attacco e uscita con pocket. -- 2021/07/20 Aggiunta gestione rinvio angolare su FAST. -- 2021/12/01 Se frontale aggiungo taglio con Grp e Proc di vero taglio (per aggiornare ingombro di testa /coda). -- Tabella per definizione modulo local ProcessDtMortise = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Cut = require( 'ProcessCut') EgtOutLog( ' ProcessDtMortise started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') -- settaggi interni ( poi andrà utilizzato parametro ACTIVE_AS proveniente da parametri utente di TechnoEssetre) local bMakeAntiSplitPath = true local bMakeAsByArc = true --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessDtMortise.Identify( Proc) return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 55) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 56)) end --------------------------------------------------------------------- -- Riconoscimento della sola feature frontale function ProcessDtMortise.FrontIdentify( Proc) return (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 56) end --------------------------------------------------------------------- -- Verifica se feature di coda function ProcessDtMortise.IsTailFeature( Proc, b3Raw) -- la mortasa di fronte è già stata classificata nel chiamante -- controllo la mortasa standard if Proc.Box:getMin():getX() < b3Raw:getMin():getX() + BD.MAX_DIST_HTFEA then -- recupero la curva di profilo local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if not AuxId then return false end AuxId = AuxId + Proc.Id local vtStart = EgtSV( AuxId, GDB_ID.ROOT) local vtEnd = EgtEV( AuxId, GDB_ID.ROOT) local vtDir = -vtStart + vtEnd ; vtDir:normalize() -- se l'asse della mortasa è inclinato indietro più di 8 deg è considerata di coda return ( vtDir:getX() < -0.15) end return false end --------------------------------------------------------------------- -- Classificazione della feature function ProcessDtMortise.Classify( Proc) -- recupero i dati della curva di contorno della faccia di fondo local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if not AuxId then return false end AuxId = AuxId + Proc.Id local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- verifico se la mortasa è lavorabile solo da sotto local bDown = ( vtExtr:getZ() < -0.1) -- se da sotto e presente rinvio angolare verifico se c'è opportuna lavorazione if bDown and BD.ANG_TRASM then if ML.FindMilling( 'DtMortise_AT') then bDown = false end end return true, bDown end --------------------------------------------------------------------- -- Piano di taglio della feature function ProcessDtMortise.GetCutPlane( Proc) if ProcessDtMortise.FrontIdentify( Proc) then return EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) else return nil, nil end end --------------------------------------------------------------------- local function CalcTopPath( nProcId, AuxId, nAddGrpId, dAltMort, dSideAng, b3Solid) -- copio la curva di base local NewAuxId = EgtCopyGlob( AuxId, nAddGrpId) if not NewAuxId then return end -- ne allungo gli estremi --EgtExtendCurveStartByLen( NewAuxId, 100) --EgtExtendCurveEndByLen( NewAuxId, 100) EgtAddCurveCompoLineTg( NewAuxId, 100, false) EgtAddCurveCompoLineTg( NewAuxId, 100, true) EgtMergeCurvesInCurveCompo( NewAuxId) -- eseguo traslazione e offset per portarla sul top local vtMove = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) * ( dAltMort - 10 * GEO.EPS_SMALL) EgtMove( NewAuxId, vtMove, GDB_RT.GLOB) local dOffset = dAltMort * tan( dSideAng) if not EgtOffsetCurve( NewAuxId, dOffset) then return end -- la limito entro la trave local refBox = Frame3d( b3Solid:getMin()) local vtBoxDiag = b3Solid:getMax() - b3Solid:getMin() local nCount NewAuxId, nCount = EgtTrimFlatCurveWithBox( NewAuxId, refBox, vtBoxDiag, true, true, GDB_RT.GLOB) -- se divisa in più parti, le unisco congiungendole con segmenti if nCount > 1 then if EgtGetType( NewAuxId) ~= GDB_TY.CRV_COMPO then NewAuxId = EgtCurveCompo( nAddGrpId, NewAuxId) end for i = 2, nCount do local CrvId = NewAuxId + i - 1 local ptStart = EgtSP( CrvId) EgtAddCurveCompoLine( NewAuxId, ptStart) EgtAddCurveCompoCurve( NewAuxId, CrvId) end end return NewAuxId end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessDtMortise.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- ingombro del pezzo local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- recupero e verifico l'entità curva local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then local sErr = 'Missing profile geometry : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end -- recupero i dati della curva local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local ptBC = EgtGP( AuxId, GDB_RT.GLOB) -- verifico che la mortasa non sia orientata verso il basso (-5 deg) o che ci sia una testa da sotto o un rinvio angolare local bFaceDown = ( vtExtr:getZ() < -0.1) if bFaceDown and not BD.DOWN_HEAD and not BD.ANG_TRASM then local sErr = 'Machining from bottom impossible : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end -- determino l'altezza della mortasa (0=faccia di fondo) local rfDtMrt = Frame3d( ptBC, vtExtr) local b3DtMrt = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfDtMrt) local dAltMort = b3DtMrt:getDimZ() -- verifico se di tipo pocket local bPocket = ( EgtGetInfo( Proc.Id, 'P05', 'i') == 1) if bPocket then bMakeAntiSplitPath = false end -- verifico se frontale local bFront = ( Proc.Prc == 56) -- se mortasa di fronte, eseguo il taglio della faccia if bFront then -- verifico esista la faccia di taglio local ptCutC, vtCutN = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) if ptCutC and vtCutN and AreSameVectorApprox( vtExtr, vtCutN) then -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end local AddId = EgtSurfTmPlaneInBBox( nAddGrpId, ptCutC, vtCutN, b3Solid, GDB_RT.GLOB) local b3Cut = EgtGetBBoxGlob( AddId or GDB_ID.NULL, GDB_BB.STANDARD) local CutProc = { Id = AddId, Grp = Proc.Grp - 2, Prc = 10, Box = b3Cut, Fct = 1, Flg = Proc.Flg, Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId} local bFromBottom = ( b3Solid:getDimX() < BD.LEN_SHORT_PART and vtExtr:getZ() > 0.25) local bOk, sErr = Cut.Make( CutProc, nPhase, nRawId, nPartId, dCurrOvmH, bFromBottom) if not bOk then return bOk, sErr end end end -- recupero il raggio minimo della mortasa local dMinRad = 1000 local nSt, nEnd = EgtCurveDomain( AuxId) for i = nSt, nEnd - 1 do local dRad = EgtCurveCompoRadius( AuxId, i) if dRad > 0 and dRad < dMinRad then dMinRad = dRad end end -- abilitazione lavorazione da sotto local bMillUp = ( BD.DOWN_HEAD and vtExtr:getZ() > -0.259) local bMillDown = ( BD.DOWN_HEAD and vtExtr:getZ() < 0.174) if BD.DH_MAX_TOP and Proc.Box:getMax():getZ() - b3Solid:getMin():getZ() > BD.DH_MAX_TOP then bMillDown = false end local bMillAngTrasm = ( BD.ANG_TRASM and vtExtr:getZ() < -0.1) -- recupero la lavorazione local sMillType = 'DtMortise' local sMchExt = '' if bMillDown then sMchExt = '_H2' elseif bMillAngTrasm then sMchExt = '_AT' end -- recupero la lavorazione : prima ricerca per sola tipologia local sMilling = ML.FindMilling( sMillType..sMchExt) if not sMilling and bMillUp then sMilling = ML.FindMilling( sMillType) end if not sMilling then local sErr = 'Milling not found in library : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end -- recupero la lavorazione : seconda ricerca con tipologia e diametro massimo sMilling = ML.FindMilling( sMillType..sMchExt, nil, nil, 2 * dMinRad) if not sMilling and bMillUp then sMilling = ML.FindMilling( sMillType, nil, nil, 2 * dMinRad) sMchExt = '' end if not sMilling then local sErr = 'Radius too small : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end -- recupero il diametro dell'utensile e l'angolo di spoglia local dToolDiam = 100 local dMaxMat = 30 local dSideAng = 0 local bCW = true if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dToolDiam = max( dToolDiam, 10) dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or dSideAng local dSpeed = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) or 0 bCW = ( dSpeed >= 0) end end -- verifico che la profondità non superi il massimo materiale dell'utensile if dAltMort > dMaxMat + 10 * GEO.EPS_SMALL then local sErr = 'Error : DtMortise Depth bigger than Tool Cutting edge' EgtOutLog( sErr) return false, sErr end -- se con tasca, la lavoro if bPocket then -- recupero il contorno della tasca (seconda curva ausiliaria) local sVal = EgtGetInfo( Proc.Id, 'AUXID') local vsAuxId = EgtSplitString( sVal) local Aux2Id if vsAuxId and #vsAuxId >=2 then Aux2Id = tonumber( vsAuxId[2]) end if Aux2Id then Aux2Id = Aux2Id + Proc.Id end if not Aux2Id or ( EgtGetType( Aux2Id) & GDB_FY.GEO_CURVE) == 0 then local sErr = 'Missing pocket geometry : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end -- recupero la lavorazione local sPocketing sPocketing = ML.FindPocketing( 'Mortise'..sMchExt, dToolDiam) if not sPocketing and bMillUp then sPocketing = ML.FindPocketing( 'Mortise', dToolDiam) end if not sPocketing then sPocketing = ML.FindPocketing( 'Pocket'..sMchExt, dToolDiam) if not sPocketing and bMillUp then sPocketing = ML.FindPocketing( 'Pocket', dToolDiam) end end if not sPocketing then local sErr = 'Error : Mortise or Pocket not found in library' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di svuotatura local sName = 'DtMtPck_' .. ( 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( {{ Aux2Id, -1}}) -- dichiaro non si generano sfridi per VMill local sUserNotes = 'MaxElev='.. EgtNumToString( dMaxMat - 0.1, 1) .. '; VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- se parametro interno abilitato e il percorso non è chiuso, aggiungo percorso e lavorazione antischeggia if bMakeAntiSplitPath and not EgtCurveIsClosed( AuxId) then -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error on process ' .. tostring( Proc.Id) .. ' missing AddGroup' EgtOutLog( sErr) return false, sErr end -- calcolo il percorso top mortise local nAuxId1 = CalcTopPath( Proc.Id, AuxId, nAddGrpId, dAltMort, dSideAng, b3Solid) -- se esiste il percorso if nAuxId1 then -- creo percorso sulla parte alta della mortasa local dToolRadDelta = dAltMort * tan( dSideAng) local dTopDiam = dToolDiam + 2 * dToolRadDelta -- recupero punto iniziale e finale del percorso local ptStart = EgtSP( nAuxId1, GDB_RT.GLOB) local ptEnd = EgtEP( nAuxId1, GDB_RT.GLOB) if ptStart and ptEnd then local nId1 -- se richiesti due segmenti di linea if not bMakeAsByArc then -- determino il punto comune dei due segmenti local vtDelta = ( ptEnd - ptStart) / 4 vtDelta:rotate( vtExtr, -90) local ptMid = ( ptStart + ptEnd) / 2 + vtDelta -- creo la spezzata formata dai due segmenti nId1 = EgtCurveCompoFromPoints( nAddGrpId, { ptStart, ptMid, ptEnd}, GDB_RT.GLOB) -- altrimenti richiesto arco else -- direzione del segmento local vtDir = ptEnd - ptStart ; local dLen = vtDir:len() vtDir:normalize() -- direzioni tangenti iniziale e finale local vtStart = EgtSV( nAuxId1, GDB_RT.GLOB) local vtEnd = EgtEV( nAuxId1, GDB_RT.GLOB) -- angoli local dAngStart = acos( vtStart * vtDir) local dAngEnd = acos( vtEnd * vtDir) local dMaxAng = min( 30, dAngStart, dAngEnd) if dLen < dTopDiam then dMaxAng = min( dMaxAng, asin( dLen / dTopDiam)) end local vtTg = vtDir ; vtTg:rotate( vtExtr, -dMaxAng) -- creo l'arco nId1 = EgtArc2PV( nAddGrpId, ptStart, ptEnd, vtTg, GDB_RT.GLOB) end if not nId1 then local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end EgtModifyCurveExtrusion( nId1, vtExtr, GDB_RT.GLOB) -- inserisco la lavorazione di contornatura anti splint local sNameF = 'DtMtAS_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) 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( {{ nId1, -1}}) -- setto affondamento pari all'altezza della mortsasa EgtSetMachiningParam( MCH_MP.DEPTH, dAltMort) -- setto offset radiale con aggiunto un ulteriore allargamento di 1mm EgtSetMachiningParam( MCH_MP.OFFSR, dToolRadDelta - 1) -- sistemo il lato e la direzione di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bCW, false, true)) -- dichiaro non si generano sfridi per VMill local sUserNotes = 'MaxElev='.. EgtNumToString( dAltMort, 1) .. '; VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end else local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end else local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end end -- verifico se necessarie più passate (distanza all'imbocco ortogonale all'asse) local vtDiff = EgtEP( AuxId, GDB_RT.GLOB) - EgtSP( AuxId, GDB_RT.GLOB) local vtAx = EgtEV( AuxId, GDB_RT.GLOB) - EgtSV( AuxId, GDB_RT.GLOB) vtAx:normalize() local vtOrtDiff = vtDiff - vtDiff * vtAx * vtAx local dDist = vtOrtDiff:len() -- calcolo le passate local nPass = ceil( dDist / ( 1.9 * dToolDiam)) local dStep = ( dDist - 0.95 * dToolDiam) / ( 2 * nPass) for i = nPass, 1, -1 do -- inserisco la lavorazione di contornatura local sNameF = 'DtMt_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nPass) 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( {{ AuxId, -1}}) -- imposto offset local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- sistemo il lato e la direzione di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bCW, false, true)) -- in presenza di pocket imposto dati ingresso e uscita if bPocket then EgtSetMachiningParam( MCH_MP.STARTPOS, 5) EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) EgtSetMachiningParam( MCH_MP.STARTADDLEN, 5) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2) EgtSetMachiningParam( MCH_MP.LIPERP, 5) EgtSetMachiningParam( MCH_MP.LIELEV, 0) end -- dichiaro non si generano sfridi per VMill local sUserNotes = 'MaxElev='.. EgtNumToString( dMaxMat - 0.1, 1) .. '; VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true end --------------------------------------------------------------------- return ProcessDtMortise