-- ProcessDoubleCut.lua by Egaltech s.r.l. 2021/11/25 -- Gestione calcolo doppi tagli di lama per Travi -- Tabella per definizione modulo local ProcessDoubleCut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Fbs = require( 'FacesBySaw') local DC = require( 'DiceCut') local Cut = require( 'ProcessCut') EgtOutLog( ' ProcessDoubleCut started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessDoubleCut.Identify( Proc) return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 11) end --------------------------------------------------------------------- -- Classificazione della feature function ProcessDoubleCut.Classify( Proc, b3Raw) --se una faccia, uso la classificazione dei tagli singoli if Proc.Fct == 1 then return Cut.Classify( Proc, b3Raw) end -- se PF con testa da sotto, ammessa qualunque orientazione if BD.C_SIMM and BD.DOWN_HEAD then return true end -- limite per facce da sotto local dNzLimDwnUp = BL.GetNzLimDownUp( b3Raw) -- verifico se convesso local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) local bConvex = ( not bAdj or ( dAng > 0)) if bConvex then -- recupero i dati di ogni singola faccia for i = 1, 2 do local nFac = i - 1 local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFac, GDB_ID.ROOT) if ( vtN:getZ() <= - 0.5 and abs( vtN:getY()) > 0.1) or ( vtN:getZ() <= - 0.174 and abs( vtN:getY()) > 0.866) then local _, DimH, DimV = BL.GetFaceHvRefDim( Proc.Id, nFac) if DimH > BD.MAX_DIM_DICE then return true, true end end local bDownCut = ( vtN:getZ() <= dNzLimDwnUp) if bDownCut then local _, DimH, DimV = BL.GetFaceHvRefDim( Proc.Id, nFac) -- confronto anche qua la distanza maggiore della faccia con la massima distanza del DiceCut -- e se il rapporto supera il 2 (implica che genera 3 tagli) dichiaro impossibile la lavorazione if DimH and BD.MAX_DIM_DICE and abs( BD.MAX_DIM_DICE) > 20 * GEO.EPS_SMALL and abs( DimH / BD.MAX_DIM_DICE) > 2 then return true, true end end end return true, false end -- altrimenti concavo, verifico le normali delle facce per tagli da sotto for i = 1, 2 do local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, i-1, GDB_ID.ROOT) local bDownCut = ( vtN:getZ() <= dNzLimDwnUp) if bDownCut then -- dimensione della faccia perpendicolare alla linea di intersezione tra le facce local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, 2-i, GDB_ID.ROOT) local vtX = vtN2 ^ vtN local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2) local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, i-1, GDB_BB.STANDARD, frRef) if b3Ref:getDimY() > BD.MAX_DIM_DICE then return true, true end 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, 'Q06', '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 then return true end if ( 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 o anche testa da sotto (non propago la segnalazione a TS3) local bVert = ( abs( vtExtr:getZ()) > 0.1) if bVert and not BD.DOWN_HEAD then local sWarn = 'Warning : skipped not horizontal chamfer' EgtOutLog( sWarn) return true end -- eseguo lo smusso solo se feature larga come la trave if ( not bVert and dWidth < b3Raw:getDimY() - 1) or ( bVert and dWidth < b3Raw:getDimZ() - 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 (Mark) not found in library' EgtOutLog( sErr) return false, sErr end local sMillingDw = ML.FindMilling( 'Mark_H2') if bVert and not sMillingDw then local sErr = 'Error : milling (Mark_H2) 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, EgtIf( not bVert or vtExtr:getZ() > 0.1, sMilling, sMillingDw)) 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 EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, 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, EgtIf( not bVert or vtExtr:getZ() < -0.1, sMilling, sMillingDw)) 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 EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end return true end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessDoubleCut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) -- se singola faccia, passo a quella lavorazione if Proc.Fct == 1 then return Cut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) end -- 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 : part box not found' EgtOutLog( sErr) return false, sErr end -- dati delle facce local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- normale media per capire se taglio di testa o di coda local vtNm = ( vtN[1] + vtN[2]) ; vtNm:normalize() local bHead = ( vtNm:getX() > 0) -- angolo diedro per stabilire se taglio convesso local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) local bConvex = true local bOnY = true local ptPs = ( ptC[1] + ptC[2]) / 2 if bAdj then local vtDir = ptP1 - ptP2 ; vtDir:normalize() bOnY = abs( vtDir:getZ()) > 0.5 and ( abs( vtDir:getZ()) + abs( vtDir:getX()) > abs( vtDir:getY())) ptPs = ( ptP1 + ptP2) / 2 bConvex = ( dAng > 0) end -- determino quale faccia è più grande local _, dB1, dH1 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 0) local _, dB2, dH2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 1) local nBigInd = EgtIf( dB1 * dH1 >= dB2 * dH2, 1, 2) local nSmaInd = 3 - nBigInd -- inserimento smussi local bOkc, sErrC = MakeChamfer( Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOkc then return bOkc, sErrC 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 convesso, lo tratto come due tagli singoli if bConvex then -- lavoro per prima la faccia più diretta in alto local vOrd = { 1, 2} if vtN[2]:getZ() > vtN[1]:getZ() then vOrd = { 2, 1} end -- creo piano di taglio coincidente con la prima faccia e lo lavoro local AddId = EgtSurfTmPlaneInBBox( nAddGrpId, ptC[vOrd[1]], vtN[vOrd[1]], b3Solid, GDB_RT.GLOB) if AddId then EgtSetName( AddId, 'AddCut_' .. tostring( Proc.Id)) EgtSetInfo( AddId, 'TASKID', Proc.TaskId) local b3Add = EgtGetBBoxGlob( AddId, GDB_BB.STANDARD) -- applico lavorazione local CutProc = { Id = AddId, Grp = Proc.Grp, Prc = 10, Box = b3Add, Fct = 1, Flg = Proc.Flg, Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId} local bOk, sErr = Cut.Make( CutProc, nPhase, nRawId, nPartId, dOvmHead) if not bOk then return bOk, sErr end end -- creo piano di taglio coincidente con la seconda faccia e lo lavoro AddId = EgtSurfTmPlaneInBBox( nAddGrpId, ptC[vOrd[2]], vtN[vOrd[2]], b3Solid, GDB_RT.GLOB) if AddId then EgtSetName( AddId, 'AddCut_' .. tostring( Proc.Id)) EgtSetInfo( AddId, 'TASKID', Proc.TaskId) local b3Add = EgtGetBBoxGlob( AddId, GDB_BB.STANDARD) -- applico lavorazione local CutProc = { Id = AddId, Grp = Proc.Grp, Prc = 10, Box = b3Add, Fct = 1, Flg = Proc.Flg, Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId} local bOk, sErr = Cut.Make( CutProc, nPhase, nRawId, nPartId, dOvmHead) if not bOk then return bOk, sErr end end -- altrimenti concavo else -- abilitazione lavorazione da sotto (testa da sotto e direzione normale sotto -30deg) local bTopHead = ( BD.DOWN_HEAD and vtNm:getZ() > -0.5) local bDownHead = ( BD.DOWN_HEAD and vtNm:getZ() < -0.5) -- recupero la lavorazione local sCutType = EgtIf( bHead, 'HeadSide', 'TailSide') local sCutting = ML.FindCutting( sCutType .. EgtIf( bDownHead, '_H2', '')) if not sCutting and bTopHead then sCutting = ML.FindCutting( sCutType) bDownHead = false end 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 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 dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end -- verifico se necessari tagli supplementari local vCuts = DC.GetDice( nAddGrpId, b3Solid, ptC[nBigInd], vtN[nBigInd], false, ptC[nSmaInd], vtN[nSmaInd]) --DC.PrintOrderCut( vCuts) if #vCuts > 0 then -- aggiorno nome e info 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 -- eseguo for i = 1, #vCuts do -- determino il modo di tagliare local vtOrthOpp = vtN[nBigInd] local vtNorm = vtN[nSmaInd] if ( i % 2) ~= 1 then vtOrthOpp, vtNorm = vtNorm, vtOrthOpp end -- lavoro la faccia for j = 1, #vCuts[i] do local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtOrthOpp, EgtIf( bDownHead, -2, nil), 0, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end end -- altrimenti, tagli diretti delle facce else local bOk, sErr = Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, sCutType .. EgtIf( bDownHead, '_H2', ''), false, bDownHead) if not bOk then return bOk, sErr end end -- segnalazione ingombro di testa o coda if Proc.Head then -- intersezioni con linee a metà altezza appena dentro dal davanti e dal dietro local ptRef = b3Raw:getCenter() - 0.5 * b3Raw:getDimX() * X_AX() local ptL1 = ptRef - ( 0.5 * b3Raw:getDimY() - 0.1) * Y_AX() local ptL2 = ptRef + ( 0.5 * b3Raw:getDimY() - 0.1) * Y_AX() local bInt1, IntTy1, IntPar1 = EgtLineSurfTmInters( ptL1, X_AX(), Proc.Id, GDB_ID.ROOT) local bInt2, IntTy2, IntPar2 = EgtLineSurfTmInters( ptL2, X_AX(), Proc.Id, GDB_ID.ROOT) local dMinPar = b3Raw:getDimX() if IntPar1 and #IntPar1 > 0 then dMinPar = min( dMinPar, IntPar1[1]) end if IntPar2 and #IntPar2 > 0 then dMinPar = min( dMinPar, IntPar2[1]) end local dOffs = b3Raw:getDimX() - dMinPar BL.UpdateHCING( nRawId, dOffs) elseif Proc.Tail then -- accetto approssimazione più grezza local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX() if vtNm:getZ() > 0.5 then dOffs = 0.4 * dOffs elseif abs( vtNm:getZ()) > 0.35 then dOffs = 0.75 * dOffs end BL.UpdateTCING( nRawId, dOffs) end end return true end --------------------------------------------------------------------- return ProcessDoubleCut