-- ProcessSimpleScarf.lua by Egaltech s.r.l. 2020/06/04 -- Gestione calcolo giunto Gerber per Travi -- 2022/06/10 Aggiunto il parametro dOvmTail per gestire sovramateriali in coda diversi da OVM_MID (sezioni alte e larghe) -- 2022/08/09 Ora se la feature ha meno di due facce viene richiamata la normale Cut. -- 2022/11/09 Aggiunta gestione parametro Q04 per forzare utilizzo fresa di lato e lavorare come FreeContour. -- 2023/02/14 Gestite le rotazioni di 90 deg nell'aggiornamento del grezzo. -- 2024/08/05 Se assimilabile ad un taglio (1 faccia) si considerare area non pinzabile testa/coda -- Tabella per definizione modulo local ProcessSimpleScarf = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Fbs = require( 'FacesBySaw') local DC = require( 'DiceCut') local Cut = require( 'ProcessCut') local FreeContour = require( 'ProcessFreeContour') EgtOutLog( ' ProcessSimpleScarf started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessSimpleScarf.Identify( Proc) return (( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 70) end --------------------------------------------------------------------- -- Classificazione della feature function ProcessSimpleScarf.Classify( Proc) -- se forzato utilizzo fresa non ruoto la trave local bForceSideMill = ( EgtGetInfo( Proc.Id, 'Q04', 'd') or 0) > 0 -- 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) if vtN:getZ() < - 0.5 and Proc.Box:getDimX() / abs( vtN:getZ()) > BD.MAX_DIM_DICE and not bForceSideMill then return true, true end end return true, false end --------------------------------------------------------------------- -- lavorazione smussi local function MakeChamfer( Proc, nPhase, nRawId, nPartId, dOvmHead) -- verifico che lo smusso sia richiesto local dDepth = EgtGetInfo( Proc.Id, 'Q01', 'd') or 0 if dDepth < 0.1 then return true end -- ingombro del grezzo local b3Raw = EgtGetRawPartBBox( nRawId) -- recupero e verifico l'entità curva associata 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 = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end -- recupero i dati della curva e del profilo local dWidth = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- eseguo lo smusso solo se direzione orizzontale (non propago la segnalazione a TS3) if abs( vtExtr:getZ()) > 0.1 then local sWarn = 'Warning : skipped not horizontal chamfer' EgtOutLog( sWarn) return true end -- eseguo lo smusso solo se feature larga come la trave if dWidth < b3Raw:getDimY() - 1 then local sWarn = 'Warning : skipped chamfer (feature smaller than beam)' EgtOutLog( sWarn) return true, sWarn end local dExtra = 2 -- recupero la lavorazione local sMilling = ML.FindMilling( 'Mark') if not sMilling then local sErr = 'Error : milling not found in library' EgtOutLog( sErr) return false, sErr end -- Inserisco la lavorazione del lato standard local sName1 = 'SJN_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMch1Id = EgtAddMachining( sName1, sMilling) if not nMch1Id then local sErr = 'Error adding machining ' .. sName1 .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- assegno affondamento e offset radiale EgtSetMachiningParam( MCH_MP.DEPTH, dDepth + dExtra) EgtSetMachiningParam( MCH_MP.OFFSR, dExtra) -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMch1Id, false) return false, sErr end -- Inserisco la lavorazione del lato opposto local sName2 = 'SJN_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMch2Id = EgtAddMachining( sName2, sMilling) if not nMch2Id then local sErr = 'Error adding machining ' .. sName2 .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- inverto direzione utensile EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) -- assegno affondamento e offset radiale EgtSetMachiningParam( MCH_MP.DEPTH, dDepth + dExtra) EgtSetMachiningParam( MCH_MP.OFFSR, dExtra) -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMch2Id, false) return false, sErr end return true end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessSimpleScarf.Make( Proc, nPhase, nRawId, nPartId, dOvmHead, dOvmTail) -- sovramateriale di coda dOvmTail = dOvmTail or BD.OVM_MID -- recupero l'ingombro del grezzo di appartenenza 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 : part box not found' EgtOutLog( sErr) return false, sErr end -- se ci sono meno di due facce si riduce a una normale Cut local nFacetCnt = EgtSurfTmFacetCount( Proc.Id) if nFacetCnt < 2 then local bOk, sErr = Cut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead, nil, nil, nil, nil, nil, dOvmTail, true) return bOk, sErr end -- dati delle facce local ptC = {} local vtN = {} for i = 1, nFacetCnt do ptC[i], vtN[i] = EgtSurfTmFacetCenter( Proc.Id, i-1, GDB_ID.ROOT) end -- ordino le facce (1=esterna, 2=interna, 3=intermedia) local vFaceOrd = { 0, 0, 0} for i = 1, nFacetCnt do if abs( vtN[i]:getY()) > 0.1 or abs( vtN[i]:getZ()) > 0.1 then vFaceOrd[3] = i break end end if vFaceOrd[3] == 0 then local sErr = 'Error : missing intermediate face' EgtOutLog( sErr) return false, sErr end for i = 1, nFacetCnt do if i ~= vFaceOrd[3] then local bTouch, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, i - 1, vFaceOrd[3] - 1, GDB_ID.ROOT) if bTouch and dAng > 0 then vFaceOrd[1] = i elseif bTouch and dAng < 0 then vFaceOrd[2] = i end end end -- determino se di testa o di coda local bHead if vtN[vFaceOrd[2]] then bHead = ( vtN[vFaceOrd[2]]:getX() > 0) else bHead = ( vtN[vFaceOrd[1]]:getX() > 0) end -- vettore di riferimento per le facce ortogonali all'asse trave local vtRef = Vector3d( 0, vtN[vFaceOrd[3]]:getY(), vtN[vFaceOrd[3]]:getZ()) vtRef:normalize() -- inserimento smussi local bOkc, sErrC = MakeChamfer( Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOkc then return bOkc, sErrC end -- se forzato utilizzo fresa richiamo la freecontour local bForceSideMill = EgtGetInfo( Proc.Id, 'Q04', 'd') == 1 or ( EgtGetInfo( Proc.Id, 'Q04', 'd') == 2 and abs( vtN[vFaceOrd[3]]:getY()) < 0.1) or ( EgtGetInfo( Proc.Id, 'Q04', 'd') == 3 and abs( vtN[vFaceOrd[3]]:getY()) < 0.1 and vtN[vFaceOrd[3]]:getZ() < 0.1) if bForceSideMill then bOk, sErr = FreeContour.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOk then return bOk, sErr end else -- recupero la lavorazione local sCutting = ML.FindCutting( 'HeadSide') if not sCutting then local sErr = 'Error : cutting not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dSawDiam = 400 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam end end -- taglio sulla faccia esterna if vFaceOrd[1] ~= 0 then -- in generale va fatto local bCut = true -- se di testa e coincide con inizio grezzo, non va fatto if bHead and AreSameVectorApprox( vtN[vFaceOrd[1]], X_AX()) and abs( ptC[vFaceOrd[1]]:getX() - b3Raw:getMax():getX() + dOvmHead) < 10 * GEO.EPS_SMALL then bCut = false end -- se di coda e coincide con taglio di separazione, non va fatto if not bHead and AreSameVectorApprox( vtN[vFaceOrd[1]], - X_AX()) and abs( ptC[vFaceOrd[1]]:getX() - b3Raw:getMin():getX()) < dOvmTail + 10 * GEO.EPS_SMALL then bCut = false end -- se va fatto, inserisco la lavorazione if bCut then local vtOrthoO = Vector3d( vtRef) local bOk, sNameOrErr = Fbs.MakeOne( Proc.Id, vFaceOrd[1] - 1, sCutting, dSawDiam, vtOrthoO, nil, BD.CUT_EXTRA, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sNameOrErr end end end -- 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 -- se esistono faccia interna ed intermedia, verifico se richiedono taglio a cubetti local vCuts = {} if vFaceOrd[2] ~= 0 and vFaceOrd[3] ~= 0 then vCuts = DC.GetDice( nAddGrpId, b3Solid, ptC[vFaceOrd[3]], vtN[vFaceOrd[3]], false, ptC[vFaceOrd[2]], vtN[vFaceOrd[2]]) elseif vFaceOrd[3] ~= 0 then vCuts = DC.GetDice( nAddGrpId, b3Solid, ptC[vFaceOrd[3]], vtN[vFaceOrd[3]], true) end if #vCuts > 0 then -- sistemo posizione nel DB e nome for i = 1, #vCuts do for j = 1, #vCuts[i] do EgtSetName( vCuts[i][j], 'AddCut_' .. tostring( Proc.Id)) EgtSetInfo( vCuts[i][j], 'TASKID', Proc.TaskId) end end -- calcolo secondo riferimento per testa o coda local vtRef2 = EgtIf( bHead, X_AX(), -X_AX()) -- eseguo for i = 1, #vCuts do local vtOrthoO if i % 2 == 1 then vtOrthoO = Vector3d( vtRef) else if #vCuts[i-1] > 0 then vtOrthoO = Vector3d( EgtIf( vtRef2, vtRef2, vtRef)) else local vtO for j = 1, #vCuts[i-1] do _, vtO = EgtSurfTmFacetCenter( vCuts[i-1][j], 0, GDB_ID.ROOT) break end if vtO then vtOrthoO = Vector3d( vtO) else vtOrthoO = Y_AX() end end end -- lavoro la faccia for j = 1, #vCuts[i] do local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtOrthoO, nil, 0, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end end else -- taglio sulla faccia interna local bIntCut = false if vFaceOrd[2] ~= 0 then -- inserisco la lavorazione local nOrthoOpposite = BL.GetNearestOrthoOpposite( vtRef) local bOk, sNameOrErr = Fbs.MakeOne( Proc.Id, vFaceOrd[2] - 1, sCutting, dSawDiam, nOrthoOpposite, nil, 0, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sNameOrErr end if #sNameOrErr > 0 then bIntCut = true end end -- taglio sulla faccia intermedia if vFaceOrd[3] ~= 0 then -- calcolo secondo testa o coda local vtRef2 = EgtIf( bHead, X_AX(), -X_AX()) -- se non ho il taglio sulla faccia interna if not bIntCut then local frHV, DimH, DimV = BL.GetFaceHvRefDim( Proc.Id, vFaceOrd[3] - 1) if DimV > DimH then vtRef2 = Vector3d( frHV:getVersX()) end end -- inserisco la lavorazione local bOk, sErr = Fbs.MakeOne( Proc.Id, vFaceOrd[3] - 1, sCutting, dSawDiam, vtRef2, nil, 0, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end end end -- aggiornamento ingombro di testa o coda if Proc.Head then local dHCI = 0 if abs( vtRef:getZ()) > 0.1 and not BD.ROT90 then local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, vFaceOrd[1] - 1, GDB_BB.STANDARD) if b3Fac1 then dHCI = b3Raw:getMax():getX() - dOvmHead - b3Fac1:getMin():getX() end else dHCI = b3Raw:getMax():getX() - dOvmHead - Proc.Box:getMin():getX() end BL.UpdateHCING( nRawId, dHCI) elseif Proc.Tail then local dTCI = 0 if abs( vtRef:getZ()) > 0.1 and not BD.ROT90 then local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, vFaceOrd[1] - 1, GDB_BB.STANDARD) if b3Fac1 then dTCI = b3Fac1:getMax():getX() - b3Solid:getMin():getX() end else dTCI = Proc.Box:getMax():getX() - b3Solid:getMin():getX() end BL.UpdateTCING( nRawId, dTCI) end return true, sErrC end --------------------------------------------------------------------- return ProcessSimpleScarf