-- ProcessDrill.lua by Egaltech s.r.l. 2021/10/29 -- Gestione calcolo forature per Travi -- 2021/04/14 DS Corretta gestione Invert con testa da sotto. Migliorato calcolo ingombro portautensile. -- 2021/05/03 DS Su macchina con testa da sotto aggiunta possibilità di fare fori verticali metà sopra e l'altra sotto. -- 2021/09/19 DS Si premia il più possibile ricerca punta con adeguato affondamento. -- 2021/10/29 DS MaxElev anche su fori con svuotatura. -- Tabella per definizione modulo local ProcessDrill = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') EgtOutLog( ' ProcessDrill started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessDrill.Identify( Proc) return ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 40) end --------------------------------------------------------------------- -- Classificazione della feature function ProcessDrill.IsHeadFeature( Proc, b3Raw, dCurrOvmH) -- verifico se è in testa if Proc.Box:getMax():getX() < b3Raw:getMax():getX() - dCurrOvmH - BD.MAX_DIST_HTFEA then return false end -- recupero e verifico l'entità foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then return false end local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- se entrata principale if Proc.Flg > 0 then local nFcs = EgtGetInfo( Proc.Id, 'FCS', 'i') or 0 return ( ( nFcs == 5 or nFcs == 6) and vtExtr:getX() > 0.5) -- altrimenti entrata opposta else local nFce = EgtGetInfo( Proc.Id, 'FCE', 'i') or 0 return ( ( nFce == 5 or nFce == 6) and vtExtr:getX() < -0.5) end end --------------------------------------------------------------------- -- Verifica se feature di coda function ProcessDrill.IsTailFeature( Proc, b3Raw) -- verifico se è in coda if Proc.Box:getMin():getX() > b3Raw:getMin():getX() + BD.OVM_MID + BD.MAX_DIST_HTFEA then return false end -- recupero e verifico l'entità foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then return false end local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- se entrata principale if Proc.Flg == 2 or ( Proc.Flg == 1 and vtExtr:getZ() >= BD.DRILL_VZ_MIN) then local nFcs = EgtGetInfo( Proc.Id, 'FCS', 'i') or 0 return ( ( nFcs == 5 or nFcs == 6) and vtExtr:getX() < -0.5) -- altrimenti entrata opposta else local nFce = EgtGetInfo( Proc.Id, 'FCE', 'i') or 0 return ( ( nFce == 5 or nFce == 6) and vtExtr:getX() > 0.5) end end --------------------------------------------------------------------- -- Recupero dati foro e adattamento se speciale function ProcessDrill.GetData( Proc, b3Raw) -- verifico se foro da adattare if EgtExistsInfo( Proc.Id, 'DiamUser') then local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id end if AuxId and EgtGetType( AuxId) == GDB_TY.CRV_ARC and BD.USER_HOLE_DIAM and BD.USER_HOLE_DIAM > 1 then EgtModifyArcRadius( AuxId, BD.USER_HOLE_DIAM / 2) end end -- recupero diametro local dDiam = EgtGetInfo( Proc.Id, 'P12', 'd') or 0 -- recupero faccia di entrata e uscita local nFcs = EgtGetInfo( Proc.Id, 'FCS', 'i') or 0 local nFce = EgtGetInfo( Proc.Id, 'FCE', 'i') or 0 return dDiam, nFcs, nFce end --------------------------------------------------------------------- -- Verifica se da lavorare in due metà function ProcessDrill.Split( Proc, b3Raw) -- recupero e verifico l'entità foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then return false end -- recupero i dati del foro local dDiam = 2 * EgtArcRadius( AuxId) local dLen = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local bOpen = ( Proc.Fce ~= 0) -- recupero flag abilitazione split (0=auto,1=no) local bTrySplit = ( EgtGetInfo( Proc.Id, 'Q02', 'i') ~= 1) if not bTrySplit then return false end -- restituisco se va fatto in doppio (solo fori orizzontali) local bHoriz = ( abs( vtExtr:getZ()) < abs( BD.DRILL_VZ_MIN) and ( abs( vtExtr:getY()) * b3Raw:getDimZ() > abs( vtExtr:getZ()) * b3Raw:getDimY() or Proc.Fce == 5 or Proc.Fce == 6)) local bSlant = ( abs( vtExtr:getX()) > BD.DRILL_VX_MAX) return ( bOpen and ( bHoriz or BD.ROT90 or BD.DOWN_HEAD) and not bSlant) end --------------------------------------------------------------------- -- Classificazione della feature function ProcessDrill.Classify( Proc, b3Raw) -- recupero e verifico l'entità foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then return false end -- recupero i dati del foro local dDiam = 2 * EgtArcRadius( AuxId) local dLen = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local ptCen = EgtCP( AuxId, GDB_RT.GLOB) -- se lavorato in doppio, devo considerare il lato più sfavorevole if Proc.Flg == -2 or (( BD.ROT90 or BD.DOWN_HEAD) and Proc.Flg == 2) then if vtExtr:getZ() > 0 then vtExtr = - vtExtr ptCen = ptCen + vtExtr * dLen end end -- verifico se troppo inclinato e quindi non lavorabile if not ( Proc.Fcs == 5 or Proc.Fcs == 6 or Proc.Fce == 5 or Proc.Fce == 6) and abs( vtExtr:getX()) > BD.DRILL_VX_MAX then return false, false, false end local bOpen = ( Proc.Fce ~= 0) local bFaceDown = ( ptCen:getZ() < b3Raw:getMin():getZ() + 2 and (( not Proc.Head and not Proc.Tail) or (( BD.ROT90 or BD.DOWN_HEAD) and ( Proc.Flg == 2 or Proc.Flg == -2)))) -- verifico se il foro è sotto e quindi va spostato o sopra o sul fianco if (( vtExtr:getZ() < BD.DRILL_VZ_MIN or bFaceDown) and ( not bOpen or Proc.Flg ~= 1)) then if not bOpen then return true, true, false else return true, not ( BD.ROT90 or BD.DOWN_HEAD), ( BD.ROT90 or BD.DOWN_HEAD) end else return true, false, false end end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessDrill.Make( Proc, nPhase, nRawId, nPartId) -- 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à foro local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then local sErr = 'Error : missing drill geometry' EgtOutLog( sErr) return false, sErr end -- recupero i dati del foro local dDiam = 2 * EgtArcRadius( AuxId) local dLen = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) if Proc.Flg == -2 then vtExtr = - vtExtr end local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0) -- verifico che il foro non sia fattibile solo da sotto local bToInvert = ( vtExtr:getZ() < BD.DRILL_VZ_MIN) and not BD.DOWN_HEAD if bToInvert and ( not bOpen or Proc.Flg ~= 1) then local sErr = 'Error : drilling from bottom impossible' EgtOutLog( sErr) return false, sErr end -- se il foro è cieco all'inizio, lo inverto if Proc.Fcs == 0 then bToInvert = true end if bToInvert then vtExtr = - vtExtr end -- se foro è splittato ed è la parte opposta, inverto if Proc.Flg == -2 then bToInvert = true end -- profondità geometrica del foro local dDepth = dLen local dDepth2 = dLen if Proc.Flg == 2 or Proc.Flg == -2 then dDepth = dLen / 2 + BD.DRILL_OVERLAP end local dCheckDepth = dDepth local dCheckDepth2 = dDepth2 local nErrorCode = 0 -- abilitazione foratura da sotto local bDrillDown = ( BD.DOWN_HEAD and ( Proc.Down or vtExtr:getZ() < -0.1 or vtExtr:getZ() < 0.259)) local bDrillUp = ( BD.DOWN_HEAD and vtExtr:getZ() > -0.259) -- primo gruppo di controlli con lunghezza utensile pari a metà foro se passante -- recupero la lavorazione local sDrilling, sType, dMaxDepth, dMaxToolLength, dToolDiam, dDiamTh, dToolFreeLen = ML.FindDrilling( dDiam, dCheckDepth, bDrillDown) if not sDrilling and bDrillUp then sDrilling, sType, dMaxDepth, dMaxToolLength, dToolDiam, dDiamTh, dToolFreeLen = ML.FindDrilling( dDiam, dCheckDepth) end if not sDrilling and dCheckDepth then sDrilling, sType, dMaxDepth, dMaxToolLength, dToolDiam, dDiamTh, dToolFreeLen = ML.FindDrilling( dDiam, 0, bDrillDown) if sDrilling then dCheckDepth = nil end end if not sDrilling and bDrillUp and dCheckDepth then sDrilling, sType, dMaxDepth, dMaxToolLength, dToolDiam, dDiamTh, dToolFreeLen = ML.FindDrilling( dDiam, 0) if sDrilling then dCheckDepth = nil end end if not sDrilling then nErrorCode = 1 end -- se trovata la lavorazione e la lunghezza massima utensile supera il valore limite del BeamData e inclinato più di 10 gradi da Z -- allora ricerco un utensile senza imporre minima capacità di taglio if nErrorCode == 0 and dMaxToolLength > ( BD.MAX_TOOL_LEN_FOR_HOR_MACH or 300) and abs( vtExtr:getZ()) < ( BD.DRILL_VZ_MIN_LONG_TOOL or cos(10)) then -- se non ho passato altezza di taglio utensile allora la lunghezza utensile non è idonea per il taglio if not dCheckDepth then nErrorCode = 2 -- rifaccio ricerca lavorazione senza specificare la profondità (dovrebbe trovare l'utensile più corto) else sDrilling, sType, dMaxDepth, dMaxToolLength, dToolDiam, dDiamTh, dToolFreeLen = ML.FindDrilling( dDiam, 0, bDrillDown) if not sDrilling and bDrillUp then sDrilling, sType, dMaxDepth, dMaxToolLength, dToolDiam, dDiamTh, dToolFreeLen = ML.FindDrilling( dDiam, 0) end if not sDrilling then nErrorCode = 1 elseif dMaxToolLength > ( BD.MAX_TOOL_LEN_FOR_HOR_MACH or 300) and abs( vtExtr:getZ()) < ( BD.DRILL_VZ_MIN_LONG_TOOL or cos(10)) then nErrorCode = 2 end end end -- secondo gruppo di controlli con lunghezza richiesta pari all'intero foro -- recupero la lavorazione local sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 if dDepth2 > dDepth + BD.DRILL_OVERLAP then sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 = ML.FindDrilling( dDiam, dCheckDepth2, bDrillDown) if not sDrilling2 and bDrillUp then sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 = ML.FindDrilling( dDiam, dCheckDepth2) end if not sDrilling2 and dCheckDepth2 then sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 = ML.FindDrilling( dDiam, 0, bDrillDown) if sDrilling2 then dCheckDepth2 = nil end end if not sDrilling2 and bDrillUp and dCheckDepth2 then sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 = ML.FindDrilling( dDiam, 0) if sDrilling2 then dCheckDepth2 = nil end end if not sDrilling2 then nErrorCode = 1 end -- se trovata la lavorazione e la lunghezza massima utensile supera il valore limite del BeamData e inclinato più di 10 gradi da Z -- allora ricerco un utensile senza imporre minima capacità di taglio if nErrorCode == 0 and dMaxToolLength2 > ( BD.MAX_TOOL_LEN_FOR_HOR_MACH or 300) and abs( vtExtr:getZ()) < ( BD.DRILL_VZ_MIN_LONG_TOOL or cos(10)) then -- se non ho passato altezza di taglio utensile allora la lunghezza utensile non è idonea per il taglio if not dCheckDepth2 then nErrorCode = 2 -- rifaccio ricerca lavorazione senza specificare la profondità (dovrebbe trovare l'utensile più corto) else sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 = ML.FindDrilling( dDiam, 0, bDrillDown) if not sDrilling2 and bDrillUp then sDrilling2, sType2, dMaxDepth2, dMaxToolLength2, dToolDiam2, dDiamTh2, dToolFreeLen2 = ML.FindDrilling( dDiam, 0) end if not sDrilling2 then nErrorCode = 1 elseif dMaxToolLength2 > ( BD.MAX_TOOL_LEN_FOR_HOR_MACH or 300) and abs( vtExtr:getZ()) < ( BD.DRILL_VZ_MIN_LONG_TOOL or cos(10)) then nErrorCode = 2 end end end end -- se esiste il parametro massima lunghezza per fori da dietro e il foro è passante e non è ancora stato invertito -- ed è orizzontale ed è orientato principalmente verso Y+ e non è la parte splittata e l'utensile supera una certa lunghezza -- lo inverto per premiare l'entrata davanti local bCommonCompare = BD.MAX_TOOL_LEN_BACK_HOR_MACH and bOpen and abs(vtExtr:getX()) < 0.5 and abs(vtExtr:getZ()) < 0.5 if nErrorCode == 0 and not bToInvert and bCommonCompare and vtExtr:getY() > 0.866 and Proc.Flg == 1 and dMaxToolLength > BD.MAX_TOOL_LEN_BACK_HOR_MACH then bToInvert = true vtExtr = - vtExtr --------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------- -- 14/12/2020 richiesta di Fabio Squaratti: con foro orizzontale passante e parametro Q02 = 0 (settato per fare in due parti), -- se punta più lunga del parametro BD.MAX_TOOL_LEN_BACK_HOR_MACH alloro ignoro la doppia foratura contrapposta e faccio foratura solo dal davanti -- Questo implica che il valore del parametro Q02 = 0 non è vincolante perchè basta che l'utensile supera il parametro allora la foratura si comporta -- come se il parametro Q02 sia = 1 --------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------- elseif nErrorCode == 0 and not bToInvert and bCommonCompare and abs(vtExtr:getY()) > 0.866 and Proc.Flg == 2 and dMaxToolLength2 > BD.MAX_TOOL_LEN_BACK_HOR_MACH then sDrilling = sDrilling2 sType = sType2 dMaxDepth = dMaxDepth2 dToolDiam = dToolDiam2 dDiamTh = dDiamTh2 dToolFreeLen = dToolFreeLen2 dDepth = dDepth2 if vtExtr:getY() > 0 then bToInvert = true vtExtr = - vtExtr end -- se sono al secondo mezzo foro con utensile che supera la lunghezza di riferimento non lo eseguo elseif nErrorCode == 0 and bCommonCompare and abs(vtExtr:getY()) > 0.866 and Proc.Flg == -2 and dMaxToolLength2 > BD.MAX_TOOL_LEN_BACK_HOR_MACH then return true, '' end if nErrorCode == 1 then local sErr = 'Error : drilling not found in library' EgtOutLog( sErr) return false, sErr elseif nErrorCode == 2 then local sErr = 'Error : tool too long to machine with big angle from vertical' EgtOutLog( sErr) return false, sErr end local dSubL1 = 0 local dSubL2 = 0 local dSubL3 = 0 local dDeltaRad = ( Proc.Diam - dToolDiam) / 2 -- se foro non su testa o coda e inclinato, limito il massimo affondamento local bInMid = false local bInvertFcse = ( bToInvert and Proc.Flg ~= -2) if ( not bInvertFcse and Proc.Fcs ~= 5 and Proc.Fcs ~= 6) or ( bInvertFcse and Proc.Fce ~= 5 and Proc.Fce ~= 6) then bInMid = true local CosB = abs( vtExtr:getX()) if CosB < BD.DRILL_VX_MAX then local TgA = CosB / sqrt( 1 - CosB * CosB) dSubL1 = ( dDiamTh / 2 + dDeltaRad + 2) * TgA else dMaxDepth = 0 end end -- se foro davanti o dietro e inclinato, limito il massimo affondamento if dMaxDepth > 0 and abs( vtExtr:getY()) > abs( vtExtr:getZ()) then local CosB = abs( vtExtr:getZ()) if bInMid then CosB = sqrt( vtExtr:getZ() * vtExtr:getZ() + vtExtr:getX() * vtExtr:getX()) end if CosB < BD.DRILL_VX_MAX then local TgA = CosB / sqrt( 1 - CosB * CosB) dSubL2 = ( dDiamTh / 2 + dDeltaRad + 2) * TgA else dMaxDepth = 0 end end -- se foro sopra o sotto e inclinato, limito il massimo affondamento if dMaxDepth > 0 and abs( vtExtr:getZ()) > abs( vtExtr:getY()) then local CosB = abs( vtExtr:getY()) if bInMid then CosB = sqrt( vtExtr:getY() * vtExtr:getY() + vtExtr:getX() * vtExtr:getX()) end if CosB < BD.DRILL_VX_MAX then local TgA = CosB / sqrt( 1 - CosB * CosB) dSubL3 = ( dDiamTh / 2 + dDeltaRad + 2) * TgA else dMaxDepth = 0 end end local dSubL = max( dSubL1, dSubL2, dSubL3) if dMaxDepth > 0 then dMaxDepth = min( dMaxDepth, dToolFreeLen - dSubL) 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}}) -- eventuale inversione if sType == 'Drill' or sType == 'Drill_H2' then EgtSetMachiningParam( MCH_MP.INVERT, bToInvert) else EgtSetMachiningParam( MCH_MP.TOOLINVERT, bToInvert) end -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = MCH_SCC.ADIR_YM if AreSameVectorApprox( vtExtr, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtExtr:getX()) < 0.1 then local bNearTail = ( Proc.Box:getCenter():getX() < b3Solid:getCenter():getX() and Proc.Box:getCenter():getX() - b3Solid:getMin():getX() < 1000) local bVeryShortPart = ( BD.LEN_VERY_SHORT_PART and b3Solid:getDimX() < BD.LEN_VERY_SHORT_PART) nSCC = EgtIf( BL.IsPartFinalPhase( nPhase) or ( bNearTail and not bVeryShortPart), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtExtr:getY() > 0.1 then nSCC = MCH_SCC.ADIR_YP end else nSCC = MCH_SCC.NONE end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- aggiusto l'affondamento local sMyWarn 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 EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill local sUserNotes = 'VMRS=0;' -- aggiungo alle note massima elevazione (coincide con affondamento) sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dDepth, 1) .. ';' -- se foro passante, aggiungo questa qualifica alle note if ( sType == 'Drill' or sType == 'Drill_H2') and bOpen then sUserNotes = sUserNotes .. 'Open=1;' end -- se lavorazione in doppio if EgtExistsInfo( Proc.Id, 'MAIN') then sUserNotes = sUserNotes .. 'Double;' elseif EgtExistsInfo( Proc.Id, 'DOU') then sUserNotes = sUserNotes .. 'Main;' end EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo local bOk = EgtApplyMachining( true, false) if not bOk and BD.DOWN_HEAD then if sType == 'Drill' or sType == 'Drill_H2' then EgtSetMachiningParam( MCH_MP.INVERT, true) else EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) end bOk = EgtApplyMachining( true, false) end if not bOk 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 return true, sMyWarn end --------------------------------------------------------------------- return ProcessDrill