-- ProcessDtMortise.lua by Egaltech s.r.l. 2023/05/11 -- 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). -- 2022/06/01 Modifiche per evitare di entrare nel legno con mortase parziali. -- 2022/08/18 Migliorato calcolo dello step. -- 2022/09/29 Aggiunto riconoscimento della sola feature laterale. -- 2022/12/28 Aggiunta gestione lavorazione in doppio. -- 2023/03/06 Aggiunta forzatura ingresso fuori dal grezzo con pocket. -- 2023/03/28 Corretto calcolo larghezza mortasa quando più larga che lunga. -- 2023/05/11 Se lavorazione in doppio e precedente no oppure di tipo diverso, forzo risalita a Zmax. -- Tabella per definizione modulo local ProcessDtMortise = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Cut = require( 'ProcessCut') local Probe = require( 'ProcessProbing') 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 laterale function ProcessDtMortise.SideIdentify( Proc) return (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 55) end --------------------------------------------------------------------- -- Riconoscimento della sola feature frontale function ProcessDtMortise.FrontIdentify( Proc) return (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 56) end --------------------------------------------------------------------- -- Riconoscimento della feature profonda, non sulla faccia della trave function ProcessDtMortise.IsDeeper( Proc, b3Raw) -- 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) if ( AreSameVectorApprox( vtExtr, -Y_AX()) and Proc.Box:getMin():getY() > b3Raw:getMin():getY() + 100 * GEO.EPS_SMALL) or ( AreSameVectorApprox( vtExtr, Y_AX()) and Proc.Box:getMax():getY() < b3Raw:getMax():getY() - 100 * GEO.EPS_SMALL) or ( AreSameVectorApprox( vtExtr, -Z_AX()) and Proc.Box:getMin():getZ() > b3Raw:getMin():getZ() + 100 * GEO.EPS_SMALL) or ( AreSameVectorApprox( vtExtr, Z_AX()) and Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 100 * GEO.EPS_SMALL) then return true end return false 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) -- se PF con testa da sotto o TURN, ammessa qualunque orientazione if ( BD.C_SIMM and BD.DOWN_HEAD) or BD.TURN then return true end -- 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 CalcPathAtHeight( nProcId, AuxId, nAddGrpId, dHeight, dSideAng, b3Solid) -- copio la curva di base local NewAuxId = EgtCopyGlob( AuxId, nAddGrpId) if not NewAuxId then return end -- ne allungo gli estremi EgtAddCurveCompoLineTg( NewAuxId, 100, false) EgtAddCurveCompoLineTg( NewAuxId, 100, true) EgtMergeCurvesInCurveCompo( NewAuxId) local dOffset = dHeight * 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) -- per ogni curva creata, eseguo traslazione e offset per portarla sul top local vtMove = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) * ( dHeight - 10 * GEO.EPS_SMALL) for i = 1, nCount do EgtMove( NewAuxId + i - 1, vtMove, GDB_RT.GLOB) end -- 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 --------------------------------------------------------------------- local function GetVerticalSteps( dMachiningDepth, dStep ) local MachiningSteps = {} MachiningSteps.StepLength = 0 if dMachiningDepth <= 0 then MachiningSteps.Count = 0 return MachiningSteps end MachiningSteps.Count = ceil( (dMachiningDepth - 10 * GEO.EPS_SMALL) / dStep ) MachiningSteps.StepLength = dMachiningDepth / MachiningSteps.Count return MachiningSteps end --------------------------------------------------------------------- -- verifica che il box includa il punto in XY function EnclosesPoint( b3Box, ptP) if b3Box[2][1] < ptP[1] - GEO.EPS_SMALL or b3Box[1][1] > ptP[1] + GEO.EPS_SMALL then return false end if b3Box[2][2] < ptP[2] - GEO.EPS_SMALL or b3Box[1][2] > ptP[2] + GEO.EPS_SMALL then return false end if b3Box[2][3] < ptP[3] - GEO.EPS_SMALL or b3Box[1][3] > ptP[3] + GEO.EPS_SMALL then return false end return true end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessDtMortise.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) local sWarn bMakeAntiSplitPath = true -- 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.TURN and not BD.ANG_TRASM then local sErr = 'Machining from bottom impossible : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end -- ne determino l'asse local vtAx = EgtEV( AuxId, GDB_RT.GLOB) - EgtSV( AuxId, GDB_RT.GLOB) vtAx:normalize() -- determino l'altezza della mortasa (0=faccia di fondo) local rfDtMrt, dLenMrt, dWidthMrt = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 0, GDB_RT.GLOB) if abs( rfDtMrt:getVersY() * vtAx) > abs( rfDtMrt:getVersX() * vtAx) then rfDtMrt:rotate( rfDtMrt:getOrigin(), rfDtMrt:getVersZ(), 90) dLenMrt, dWidthMrt = dWidthMrt, dLenMrt end local b3DtMrt = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfDtMrt) local dAltMort = b3DtMrt:getDimZ() -- verifico se di tipo pocket o se antischeggia disabilitato local bPocket = ( EgtGetInfo( Proc.Id, 'P05', 'i') == 1) local bDisableAntiSplint = ( EgtGetInfo( Proc.Id, 'Q01', 'i') or 0) == 1 if bPocket or bDisableAntiSplint 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, PartId = Proc.PartId} CutProc.AffectedFaces = BL.GetProcessAffectedFaces( CutProc) 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 local bExcludeH2 = false if Proc.Double and Proc.Double > 0 then bMillUp = true bMillDown = false bExcludeH2 = true sMchExt = '' end -- recupero la lavorazione : prima ricerca per sola tipologia local sMilling = ML.FindMilling( sMillType..sMchExt, nil, nil, nil, nil, bMillUp, bMillDown, bExcludeH2) if not sMilling and bMillUp then sMilling = ML.FindMilling( sMillType, nil, nil, nil, nil, bMillUp, bMillDown, bExcludeH2) 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, nil, bMillUp, bMillDown, bExcludeH2) if not sMilling and bMillUp then sMilling = ML.FindMilling( sMillType, nil, nil, 2 * dMinRad, nil, bMillUp, bMillDown, bExcludeH2) 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 sHeadTool = 'H1' local bCW = true local bMillOnAggregate = sMchExt == '_AT' 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 sHeadTool = EgtTdbGetCurrToolParam( MCH_TP.HEAD) local dSpeed = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) or 0 bCW = ( dSpeed >= 0) end end local bMultipleZPasses = false -- se necessario, cerco un utensile più lungo if dAltMort > dMaxMat + 10 * GEO.EPS_SMALL then -- recupero la lavorazione : prima ricerca per sola tipologia sMilling = ML.FindMilling( sMillType..sMchExt, nil, nil, nil, nil, bMillUp, bMillDown, bExcludeH2, nil, 'Longest') if not sMilling and bMillUp then sMilling = ML.FindMilling( sMillType, nil, nil, nil, nil, bMillUp, bMillDown, bExcludeH2, nil, 'Longest') 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, nil, bMillUp, bMillDown, bExcludeH2, nil, 'Longest') if not sMilling and bMillUp then sMilling = ML.FindMilling( sMillType, nil, nil, 2 * dMinRad, nil, bMillUp, bMillDown, bExcludeH2, nil, 'Longest') sMchExt = '' end if not sMilling then local sErr = 'Radius too small : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end if not sMilling then local sErr = 'Error : DtMortise Depth bigger than Tool Cutting edge' EgtOutLog( sErr) return false, sErr end -- riassegno dati utensile dToolDiam = 100 dMaxMat = 30 dSideAng = 0 bCW = true bMillOnAggregate = sMchExt == '_AT' 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 bMultipleZPasses = true end -- tastatura se richiesta local Info = { vtProbe = vtExtr, ptProbe = ptBC, sType = 'DTMortise', sHead = sHeadTool} local bProbeExecuted, sErr = Probe.Make( Proc, nPartId, Info) -- se con tasca, la lavoro (mai in doppio) if bPocket then -- recupero il contorno della tasca (seconda curva ausiliaria) local vAuxId = EgtGetInfo( Proc.Id, 'AUXID', 'vi') local Aux2Id if vAuxId and #vAuxId >=2 then Aux2Id = vAuxId[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, nil, nil, bMillUp, bMillDown) if not sPocketing and bMillUp then sPocketing = ML.FindPocketing( 'Mortise', dToolDiam, nil, nil, bMillUp, bMillDown) end if not sPocketing then sPocketing = ML.FindPocketing( 'Pocket'..sMchExt, dToolDiam, nil, nil, bMillUp, bMillDown) if not sPocketing and bMillUp then sPocketing = ML.FindPocketing( 'Pocket', dToolDiam, nil, nil, bMillUp, bMillDown) 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 = EgtGetMachiningParam( MCH_MP.USERNOTES) or '' sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxMat - 0.1, 1)) sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0) EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- eventuale calcolo SCC local nSCC if BD.TURN then if not bPocket then if abs( vtAx:getY()) > abs( vtAx:getZ()) then nSCC = EgtIf( vtAx:getY() > 0, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( vtAx:getZ() > 0, MCH_SCC.ADIR_ZP, MCH_SCC.ADIR_ZM) end end -- se aggregato e rivolto verso Z-, si accede da lato aperto elseif bMillOnAggregate and AreSameVectorApprox( vtExtr, -Z_AX()) then if Proc.AffectedFaces.Back then nSCC = MCH_SCC.ADIR_YP elseif Proc.AffectedFaces.Front then nSCC = MCH_SCC.ADIR_YM end end -- flag di mirror precedente aggiornabile localmente local nMyPrevDouble = Proc.PrevDouble -- 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 : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- calcolo il percorso top mortise local nAuxId1 = CalcPathAtHeight( Proc.Id, AuxId, nAddGrpId, dAltMort, dSideAng, b3Solid) -- se esiste il percorso if nAuxId1 then if EgtCurveIsFlat( 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 ' 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) -- antischeggia sempre con una passata if bMultipleZPasses then EgtSetMachiningParam( MCH_MP.STEP, 0) end -- 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)) -- se necessario, imposto SCC if nSCC then EgtSetMachiningParam( MCH_MP.SCC, nSCC) end -- dichiaro non si generano sfridi per VMill local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or '' sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dAltMort, 1)) sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0) -- se lavorazione in doppio if Proc.Double and Proc.Double > 0 then sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) if Proc.Double ~= nMyPrevDouble then nMyPrevDouble = Proc.Double sUserNotes = EgtSetValInNotes( sUserNotes, 'StartZmax', 2) end end EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not ML.ApplyMachining( 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 sWarn = 'Warning : skipped DoveTail mortise antisplint' 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 vtOrtDiff = vtDiff - vtDiff * vtAx * vtAx local dDist = min( vtOrtDiff:len(), dWidthMrt) -- calcolo le passate local nPass = ceil( dDist / ( 1.9 * dToolDiam)) local dStep = 0 if nPass > 1 then dStep = max( ( dDist - 2 * dToolDiam) / ( 2 * nPass - 2), 0.25 * dToolDiam) end local dVerticalStep = 0 if bMultipleZPasses then local dToolVerticalStep = 0 if EgtMdbSetCurrMachining( sMilling) then dToolVerticalStep = EgtMdbGetCurrMachiningParam( MCH_MP.STEP) or 0 end if dToolVerticalStep < 10 * GEO.EPS_SMALL then dToolVerticalStep = dMaxMat / 3 else dToolVerticalStep = min( dToolVerticalStep, dMaxMat / 3) end local VerticalSteps = GetVerticalSteps( dAltMort, dToolVerticalStep) dVerticalStep = VerticalSteps.StepLength nPass = VerticalSteps.Count end 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 local GeomId = AuxId if ( i > 1) and bMultipleZPasses then local dCurrentHeight = dAltMort - ( ( nPass - i + 1) * dVerticalStep) -- 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 b3MortiseNoPocket = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD) GeomId = CalcPathAtHeight( Proc.Id, AuxId, nAddGrpId, dCurrentHeight, dSideAng, b3MortiseNoPocket) if not GeomId then local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.Id) EgtOutLog( sErr) return false, sErr end end EgtSetMachiningGeometry( {{ GeomId, -1}}) -- imposto offset local dOffs = ( i - 1) * dStep if bMultipleZPasses then if i > 1 then dOffs = 1 else dOffs = 0 end end EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- in caso di passate in Z già calcolate lo step deve essere nullo per garantire passate singole if bMultipleZPasses then EgtSetMachiningParam( MCH_MP.STEP, 0) end -- 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)) local ptS = EgtSP( AuxId, GDB_ID.ROOT) local ptE = EgtEP( AuxId, GDB_ID.ROOT) -- in presenza di pocket imposto dati ingresso e uscita if bPocket then -- recupero il contorno della tasca (seconda curva ausiliaria) local vAuxId = EgtGetInfo( Proc.Id, 'AUXID', 'vi') -- si prende il centro del percorso da svuotare ( non si controlla che sia presente perchè già verificata in precedenza) local ptPocketCenter = EgtGP( Proc.Id + vAuxId[2], GDB_ID.ROOT) -- calcolo componente tangente e lineare di ingresso local vtS = EgtSV( Proc.Id + vAuxId[1], GDB_ID.ROOT) -- vettore entrante percorso local vtOffS = EgtSV( Proc.Id + vAuxId[1], GDB_ID.ROOT) ; vtOffS:rotate( vtExtr, 90) -- vettore da punto iniziale a centro utensile local vtStartToCenter = ptPocketCenter - ( ptS + ( vtOffS * ( dToolDiam/2))) -- vettore da centro utensilenel punto iniziale e centro del percorso da svuotare local dLenStartToCenter = vtStartToCenter:len() -- distanza da centro utensile a centro del percorso da svuotare local dStartTangComp = abs( vtStartToCenter * vtS) -- prodotto scalare tra vettore entrante e vettore tra centro utensilee percordo da svuotare (componente tangente) local dStartPerpComp = sqrt( dLenStartToCenter^2 - dStartTangComp^2) -- pitagora tra componente tangente e la lunghezza tra i due centri -- calcolo componente tangente e lineare di uscita local vtE = EgtEV( Proc.Id + vAuxId[1], GDB_ID.ROOT) local vtOffE = EgtEV( Proc.Id + vAuxId[1], GDB_ID.ROOT) ; vtOffE:rotate( vtExtr, 90) local vtEndToCenter = ptPocketCenter - ( ptE + ( vtOffE * ( dToolDiam/2))) local dLenEndToCenter = vtEndToCenter:len() local dEndTangComp = abs( vtEndToCenter * vtE) local dEndPerpComp = sqrt( dLenEndToCenter^2 - dEndTangComp^2) EgtSetMachiningParam( MCH_MP.STARTPOS, 5) EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT) EgtSetMachiningParam( MCH_MP.LITANG, dStartTangComp) EgtSetMachiningParam( MCH_MP.LIPERP, dStartPerpComp) EgtSetMachiningParam( MCH_MP.LIELEV, 0) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.TANGENT) EgtSetMachiningParam( MCH_MP.LOTANG, dEndTangComp) EgtSetMachiningParam( MCH_MP.LOPERP, dEndPerpComp) EgtSetMachiningParam( MCH_MP.LOELEV, 0) EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) -- altrimenti verifico se sono bilanciati ingresso e uscita, per evitare inizio o fine nel legno else local dDistS = abs( ( ptS - rfDtMrt:getOrigin()) * rfDtMrt:getVersX()) local dDistE = abs( ( ptE - rfDtMrt:getOrigin()) * rfDtMrt:getVersX()) local dIni, dFin = EgtCurveDomain( AuxId) local nCrvCnt = dFin - dIni - 1 if abs( dDistS - dDistE) > 20 then local b3Test = BBox3d( b3Solid) b3Test:expand( -5) if dDistS < dDistE and EnclosesPoint( b3Test, ptS) and EgtCurveCompoAngCenter( AuxId, 0) == 0 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dDistE - dDistS) elseif dDistE < dDistS and EnclosesPoint( b3Test, ptE) and EgtCurveCompoAngCenter( AuxId, nCrvCnt) == 0 then EgtSetMachiningParam( MCH_MP.ENDADDLEN, dDistS - dDistE) end end end -- se necessario, imposto SCC if nSCC then EgtSetMachiningParam( MCH_MP.SCC, nSCC) end -- dichiaro massima elevazione e assenza sfridi per VMill local dMaxElev = dMaxMat if bMultipleZPasses then dMaxElev = dVerticalStep end local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or '' sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev - 0.1, 1)) sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0) -- in presenza di pocket dichiaro che non sto entrando e uscendo nel grezzo if bPocket then sUserNotes = EgtSetValInNotes( sUserNotes, 'OutRaw', 3) end -- se lavorazione in doppio if Proc.Double and Proc.Double > 0 then sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) if Proc.Double ~= nMyPrevDouble then nMyPrevDouble = Proc.Double sUserNotes = EgtSetValInNotes( sUserNotes, 'StartZmax', 2) end end -- se c'è stata tastatura, si disattiva sull'ultima lavorazione if bProbeExecuted and i == 1 then sUserNotes = EgtSetValInNotes( sUserNotes, 'END-PROBE', true) end EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true, sWarn end --------------------------------------------------------------------- return ProcessDtMortise