-- ProcessCut.lua by Egaltech s.r.l. 2023/08/01 -- Gestione calcolo singoli tagli di lama per Travi -- 2021/05/18 I due tagli con testa da sotto di un cubetto sono fatti di seguito. -- 2021/06/06 Correzioni per tagli con testa da sotto. -- 2021/07/14 Migliorie per tagli con testa da sotto. -- 2021/09/19 Tagli da sotto non sbiechi favorita posizione da sopra di testa. -- 2021/10/06 Piccola correzione a tagli di cubetti con testa da sotto. -- 2022/01/26 Taglio da sotto orizzontale deve avere direzione di riferimento ortogonale -Z. -- 2022/02/02 Modifiche per tagli di coda spostati prima come lavorazione su pezzi a caduta. -- 2022/02/06 Correzioni per tagli di coda spostati prima. -- 2022/05/31 Alcune modifiche per utilizzare la ProcessCut.Make in ProcessSplit e ProcessHeadCut, per le sezioni alte e larghe. -- 2022/06/10 Aggiunto il parametro dOvmTail per gestire sovramateriali in coda diversi da OVM_MID (sezioni alte e larghe). -- 2022/06/28 Modificata determinazione taglio bFromBottom in MakeFromTop. -- 2022/07/18 Se Q04=1, aggiunto LongCut anche dal lato per macchine tipo PF1250. -- 2022/08/12 I tagli di lama inclinati in coda ora partono dal centro e non dall'esterno. -- 2022/08/24 Disabilitato il dicing per i tagli meno spessi della lama. -- 2022/08/25 In caso di AdvTail con taglio lungo Y la profondità di lavorazione è opportunamente diminuita. -- 2022/08/30 Modificata la condizione che determina l'utilizzo della testa da sotto. Ora controlla se la trave è più grande del doppio della massima larghezza del cubetto. -- 2022/09/23 Corretta la condizione per cui è richiesto l'aggiornamento del grezzo. -- 2023/01/26 Migliorata la direzione di lavoro della lama in alcuni casi in cui il truciolo veniva scaricato dal lato errato. -- 2023/06/19 Aggiunti tagli speciali per evitare il rischio che il cubetto rimanga appoggiato al motore. -- 2023/08/01 Correzione su offset per taglio doppio di lato. -- 2023/08/01 In caso di pezzi alti su macchina tipo PF i tagli doppi di lato non vengono usati, si usa il metodo standard. -- 2023/09/12 In MakeFromTop abbassato a 590 mm il limite per convertire in LongCut. -- 2023/10/27 In MakeFromTop corretto massimo materiale in caso di lavorazione da sotto. -- 2023/12/07 Correzione in Classify in scelta ribaltamento trave quando si è in condizioni downUp. -- 2024/01/18 Gestita superficie limitante opzionale da passare a diceCut. -- 2024/05/10 In MakeFromTop ricalcolo direzione di lavorazione su facce a cubetti -- Tabella per definizione modulo local ProcessCut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Fbs = require( 'FacesBySaw') local DC = require( 'DiceCut') local LongCut = require( 'ProcessLongCut') EgtOutLog( ' ProcessCut started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessCut.Identify( Proc) -- se richiesto si forza fresatura Proc.bForceMill = ( ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10) and ( ( EgtGetInfo( Proc.Id, 'Q07', 'd') or 0) == 1)) if Proc.bForceMill then return false else return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10) end end --------------------------------------------------------------------- -- Classificazione della feature function ProcessCut.Classify( Proc, b3Raw) -- 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 del taglio local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- calcolo le massime estensioni lineari orizzontale e verticale della faccia local _, DimH, DimV = BL.GetFaceHvRefDim( Proc.Id, 0, b3Raw) if ( vtN:getZ() <= - 0.5 and abs( vtN:getY()) > 0.1) or ( vtN:getZ() <= - 0.174 and abs( vtN:getY()) > 0.866) or ( vtN:getZ() <= - 0.174 and abs( vtN:getZ()) * DimV > BD.MAX_DIM_DICE) then -- confronto queste estensioni con la massima dimensione del DiceCut (impossibile lavorare se entrambe maggiori) if DimH > BD.MAX_DIM_DICE + 100 * GEO.EPS_SMALL and DimV > BD.MAX_DIM_DICE + 100 * GEO.EPS_SMALL then return true, true end end -- se è un taglio da sotto, lo verifico local dNzLimDwnUp = BL.GetNzLimDownUp( b3Raw) local bDownCut = ( vtN:getZ() <= dNzLimDwnUp) if bDownCut then -- recupero i dati della lama local sCutType = EgtIf( Proc.Head, 'HeadSide', 'TailSide') local sCutting = ML.FindCutting( sCutType, true, false) local dMaxDepth = 0 local dMaxMat = 0 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat end end -- calcolo l'ingombro orizzontale della faccia _, DimH, DimV = BL.GetFaceHvRefDim( Proc.Id, 0) -- confronto questo ingombro con il doppio della massima dimensione del DiceCut (impossibile lavorare sotto da sopra se più di 2 tagli oppure se tipo PF, taglio inclinato in Y e non taglio singolo orizzontale) if DimH > 2 * BD.MAX_DIM_DICE or ( BD.C_SIMM and ( abs( vtN:getY()) > 0.1) and dMaxMat < DimH + BD.CUT_EXTRA) then return true, true end end return true, false end --------------------------------------------------------------------- -- Piano di taglio della feature function ProcessCut.GetCutPlane( Proc) if ProcessCut.Identify( Proc) then return EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) else return nil, nil end end --------------------------------------------------------------------- -- verifica curva per smusso (-1=errore curva, 0=estrusione non va bene, 1=ok) local function VerifyCurveForChamfer( AuxId) if not AuxId then return -2 end if ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then return -1 end local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- va bene solo se direzione estrusione orizzontale if abs( vtExtr:getZ()) > 0.1 then return 0 end return 1 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 le entità curva associate (max 2) local sVal = EgtGetInfo( Proc.Id, 'AUXID') local vsAuxId = EgtSplitString( sVal) local AuxId, Aux2Id if vsAuxId and #vsAuxId >=1 then AuxId = tonumber( vsAuxId[1]) end if vsAuxId and #vsAuxId >=2 then Aux2Id = tonumber( vsAuxId[2]) end if AuxId then AuxId = AuxId + Proc.Id end if Aux2Id then Aux2Id = Aux2Id + Proc.Id end local nRes = VerifyCurveForChamfer( AuxId) if nRes == 0 and Aux2Id then AuxId = Aux2Id nRes = VerifyCurveForChamfer( AuxId) end if nRes == -2 then return true end if nRes == -1 then local sErr = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end if nRes == 0 then local sWarn = 'Warning : skipped not horizontal chamfer' EgtOutLog( sWarn) return true 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 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, nil end --------------------------------------------------------------------- -- Aggiornamento ingombro local function UpdateEncumbrance( Proc, vtN, dOvmHead, nRawId, b3Solid, b3Raw) -- eventuale segnalazione ingombro di testa o coda (se non chiamata da altre feature) local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * b3Raw:getDimZ()) local dMinZ = max( BD.MIN_HEIGHT, 0.35 * b3Raw:getDimZ()) if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + dMinZ then if Proc.Head then local dOffs = b3Raw:getMax():getX() - dOvmHead - Proc.Box:getMin():getX() if vtN:getZ() > 0.5 then dOffs = dOffs - 0.6 * Proc.Box:getDimX() elseif vtN:getZ() < -0.5 then dOffs = dOffs - EgtIf( BD.PRESS_ROLLER, 0.4, 0.2) * Proc.Box:getDimX() elseif ( abs( vtN:getY()) > 0.9 and vtN:getZ() > 0.2) then dOffs = dOffs - 0.3 * Proc.Box:getDimX() end BL.UpdateHCING( nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX() if vtN:getZ() > 0.5 then dOffs = dOffs - 0.6 * Proc.Box:getDimX() elseif vtN:getZ() < -0.5 then dOffs = dOffs - EgtIf( BD.PRESS_ROLLER, 0.4, 0.2) * Proc.Box:getDimX() elseif ( abs( vtN:getY()) > 0.9 and vtN:getZ() > 0.2) then dOffs = dOffs - 0.3 * Proc.Box:getDimX() end BL.UpdateTCING( nRawId, dOffs) end end end --------------------------------------------------------------------- -- Applicazione della lavorazione con testa da sopra local function MakeFromTop( sCutting, Proc, nPhase, nRawId, nPartId, dOvmHead, bFromBottom, bCustDiceCut, bForced, b3Raw, sNotes, nLimitingSurf, sLeadInOutType) local sWarn -- ingombro del grezzo b3Raw = b3Raw or EgtGetRawPartBBox( nRawId) -- ingombro del pezzo local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- dati geometrici del taglio local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- limiti di taglio (se molto di lato e inclinati sono permessi fino a -45deg) local dNzLimDwnUp = BL.GetNzLimDownUp( b3Raw, vtN) local bDownCut = ( vtN:getZ() <= dNzLimDwnUp) if bFromBottom == nil then bFromBottom = ( vtN:getZ() > 0.25 and ( b3Solid:getDimX() < BD.LEN_SHORT_PART and BL.IsSplittedPartPhase( nPhase)) and not Proc.AdvTail and vtN:getX() < 0 and abs( vtN:getY()) < 0.259) end local dMinFeatureLengthForLongCut = EgtIf( BD.C_SIMM, 590, 400) -- verifico se da considerare taglio lungo ( non da sotto, inclinato non più di 30deg, largo come la trave e abbastanza lungo) local bLongCut = ( not bDownCut and vtN:getZ() > 0.865 and Proc.Box:getDimY() > b3Solid:getDimY() - 10 * GEO.EPS_SMALL and ( Proc.Box:getDimX() > 0.75 * b3Solid:getDimX() or Proc.Box:getDimX() > dMinFeatureLengthForLongCut)) -- verifico se da considerare taglio lungo dal lato, solo per macchine tipo PF1250, inclinato non più di 30deg local bLongCutFromSide = ( not bDownCut and ( BD.C_SIMM and BD.DOWN_HEAD and ( abs(vtN:getY()) > 0.865) and Proc.Box:getDimZ() > b3Solid:getDimZ() - 10 * GEO.EPS_SMALL) and ( Proc.Box:getDimX() > 0.75 * b3Solid:getDimX() or Proc.Box:getDimX() > dMinFeatureLengthForLongCut)) -- se taglio lungo e Q04 = 1 allora lancio il processo dell'L10 local bNoDicing = EgtGetInfo( Proc.Id, 'Q04', 'i') == 1 if bNoDicing then if bLongCut then local bOk, sErr = LongCut.Make( Proc, nPhase, nRawId, nPartId, true) return bOk, sErr, bNoDicing elseif bLongCutFromSide then local bOk, sErr = LongCut.Make( Proc, nPhase, nRawId, nPartId, false, 2) return bOk, sErr, bNoDicing end -- se non passa dal LongCut rimetto a false perchè ha fatto un taglio standard bNoDicing = false end -- se pezzo ancora attaccato alla trave, per non rovinare quello successivo local bFillAreaPiece local bFillTail if not BL.IsSplittedPartPhase( nPhase) then -- se non da sotto if not bDownCut then bFillAreaPiece = bCustDiceCut -- se true il controllo è già stato fatto dal modulo che ha chiamato il ProcessCut if not bFillAreaPiece then -- se poco inclinata ( inclinazione inferiore a 21.56 deg) if vtN:getZ() > 0.93 then -- si possono far partire i tagli a cubetti dalla testa bFillAreaPiece = bLongCut -- se praticamente verticale di fianco ( inclinazione inferiore a 21.56deg) elseif abs( vtN:getY()) > 0.93 then -- se la faccia occupa tutta la trave in X e Z o occupa sicuramente la faccia in Z e almeno 3/4 della faccia in X e sborda in X, if ( ( abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL and abs( Proc.Box:getMax():getX() - b3Solid:getMax():getX()) < 10*GEO.EPS_SMALL) or ( ( abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL or abs( Proc.Box:getMax():getX() - b3Solid:getMax():getX()) < 10*GEO.EPS_SMALL) and Proc.Box:getDimX() > 0.90 * b3Solid:getDimX())) and abs( Proc.Box:getMin():getZ() - b3Solid:getMin():getZ()) < 10*GEO.EPS_SMALL and abs( Proc.Box:getMax():getZ() - b3Solid:getMax():getZ()) < 10*GEO.EPS_SMALL then local sErr = 'Error : Impossible to machine by orientation (on side A)' EgtOutLog( sErr) return false, sErr end end end -- se quasi orizzontale ( inclinazione inferiore a 30) if vtN:getZ() > 0.866 then -- se la faccia termina davanti o dietro la trave e arriva in coda e non interessa la faccia inferiore, forzo il taglio a cubetti a partire dal davanti if ( abs( Proc.Box:getMin():getY() - b3Solid:getMin():getY()) < 10*GEO.EPS_SMALL or abs( Proc.Box:getMax():getY() - b3Solid:getMax():getY()) < 10*GEO.EPS_SMALL) and abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL and b3Solid:getMin():getZ() < Proc.Box:getMin():getZ() - 100 * GEO.EPS_SMALL then bFillTail = true end -- se verticale quasi completamente di fianco ( inclinazione inferiore a 30) elseif abs( vtN:getY()) > 0.866 then -- se la faccia termina davanti o dietro la trave e arriva in coda e non interessa la faccia inferiore, forzo il taglio a cubetti a partire dal davanti if ( abs( Proc.Box:getMin():getZ() - b3Solid:getMin():getZ()) < 10*GEO.EPS_SMALL or abs( Proc.Box:getMax():getZ() - b3Solid:getMax():getZ()) < 10*GEO.EPS_SMALL) and abs( Proc.Box:getMin():getX() - b3Solid:getMin():getX()) < 10*GEO.EPS_SMALL then local sErr = 'Error : Impossible to machine by orientation (on side B)' EgtOutLog( sErr) return false, sErr end end end end -- se vero taglio, eventuale inserimento smussi if ProcessCut.Identify( Proc) then local bOkc, sErrC = MakeChamfer( Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOkc then return bOkc, sErrC end end -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 2 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 dSawThick = EgtTdbGetCurrToolParam(MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end local dMaxVertDepth = dMaxDepth - ( BD.DECR_VERT_CUT or 0) -- determino la direzione di taglio preferenziale local frFac, dCutH, dCutV = BL.GetFaceHvRefDim( Proc.Id, 0, b3Raw) local bHorizCut = ( dCutV < dMaxVertDepth - BD.CUT_EXTRA and not bDownCut) or ( dCutV < 0.8 * dMaxVertDepth - BD.CUT_EXTRA and b3Solid:getDimZ() < 0.8 * dMaxVertDepth - BD.CUT_EXTRA) local bVertCutOk = ( dCutH < dMaxDepth - BD.CUT_EXTRA) -- 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 -- verifico se necessari tagli supplementari o se presente superficie limitante EgtOutLog( string.format( 'MaxDepth=%.1f MaxVertDepth=%.1f CutH=%.1f CutV=%.1f', dMaxDepth, dMaxVertDepth, dCutH, dCutV), 3) -- se lungo, una faccia e rivolto sul retro verso l'alto si forzano i cubetti per evitare di rovinare il pezzo successivo local bForceDicing = ( Proc.Fct == 1 and Proc.AffectedFaces.Left and bLongCut and vtN:getZ() > 10 * GEO.EPS_SMALL and vtN:getY() < 10 * GEO.EPS_SMALL) local vCuts = {} local dDicingOffsetP local dDicingOffsetO if ( ( not Proc.AdvTail) or bForceDicing) and ( dCutH - 100 * GEO.EPS_SMALL > dMaxDepth - BD.CUT_EXTRA - 3 * BD.COLL_SIC or dCutV - 100 * GEO.EPS_SMALL > dMaxVertDepth - BD.CUT_EXTRA - 3 * BD.COLL_SIC) then local ptExtra, vtExtra local bAutoCalcSurf = true if Proc.AdvTail then -- do avviso che la lama può sbordare nel pezzo successivo sWarn = 'Warning : Cut machining can damage next piece' EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')') end if bFillAreaPiece or bFillTail then local ptMiddle = ( b3Solid:getMin() + b3Solid:getMax()) / 2 ptExtra = Point3d( b3Solid:getMin():getX() + 5*GEO.EPS_SMALL, ptMiddle:getY(), ptMiddle:getZ()) vtExtra = X_AX() bAutoCalcSurf = false -- superficie limitante elseif nLimitingSurf then ptExtra, vtExtra = EgtSurfTmFacetCenter( nLimitingSurf, 0, GDB_ID.ROOT) end -- verifico elevazione max del materiale tagliato local dMaxElev if vtN:getX() > 0 then if bForced then dMaxElev = b3Raw:getMax():getX() - Proc.Box:getMin():getX() else dMaxElev = b3Solid:getMax():getX() - Proc.Box:getMin():getX() end else if bForced then dMaxElev = Proc.Box:getMax():getX() - b3Raw:getMin():getX() else dMaxElev = Proc.Box:getMax():getX() - b3Solid:getMin():getX() end end -- per macchina TURN (ma non OikosX) aggiusto massima dimensione cubetto local dNewDiceDim if BD.TURN and BD.TURN ~= 2 then local dDimRef = GEO.INFINITO if abs( vtN:getZ()) < 0.003 then dDimRef = b3Raw:getDimZ() elseif abs( vtN:getY()) < 0.003 then dDimRef = b3Raw:getDimY() end if dDimRef + BD.CUT_EXTRA < dMaxDepth then dNewDiceDim = - ( dMaxDepth - BD.CUT_EXTRA) end end -- se il taglio è più spesso della lama abilito il dicing, altrimenti no if ( dMaxElev > dSawThick) or bForceDicing then vCuts, dDicingOffsetP = DC.GetDice( nAddGrpId, EgtIf( bForced, b3Raw, b3Solid), ptC, vtN, bAutoCalcSurf, ptExtra, vtExtra, dMaxVertDepth - BD.CUT_EXTRA, dNewDiceDim) -- se taglio sborda in coda e non è stato inserito nessun taglio a cubetti, lo rilancio con le dimensioni customizzate if ( bFillTail or bCustDiceCut) and #vCuts == 0 then vCuts, dDicingOffsetP = DC.GetDice( nAddGrpId, b3Solid, ptC, vtN, bAutoCalcSurf, ptExtra, vtExtra, dMaxVertDepth - BD.CUT_EXTRA, Proc.Box:getDimY()) end end end -- se il ProcessCut viene lanciato dal ProcessSawCut e non ci sono tagli a cubetti, esco if bCustDiceCut and #vCuts == 0 then return false, -1 end -- per caso speciale in cui c'è il rischio che il cubetto rimanga appoggiato sul motore, faccio solo i tagli perpendicolari seguiti da due tagli verticali laterali local bDangerousReliefCut = false -- verifico che i tagli perpendicolari siano perpendicolari al lato più vicino a Z local nFirstPerpendicularCut = ( #vCuts > 0 and ( vCuts[1][1] or vCuts[3][1])) if nFirstPerpendicularCut then local frFace = BL.GetFaceHvRefDim( Proc.Id, 0) local vtTemp = EgtSurfTmFacetNormVersor( nFirstPerpendicularCut, 0, GDB_ID.ROOT) ^ frFace:getVersX() if not ( vtTemp:isSmall()) and not ( bDownCut or bFromBottom) and not bLongCut and ( not BD.C_SIMM or b3Raw:getDimZ() < BD.MIN_DIM_HBEAM + 10 * GEO.EPS_SMALL) then bDangerousReliefCut = true end end --DC.PrintOrderCut( vCuts) if #vCuts > 0 then -- sistemo posizione nel DB e nome local bOrthInv = false 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) if ( i % 2) == 1 then local vtO = EgtSurfTmFacetNormVersor( vCuts[i][j], 0, GDB_ID.ROOT) if ( vtN:getY() > 0.766 and vtO:getY() < -0.05) or ( vtN:getY() < -0.766 and vtO:getY() > 0.05) then EgtInvertSurf( vCuts[i][j]) bOrthInv = true end end end end -- eseguo for i = 1, #vCuts do -- determino il modo di tagliare local vtOrthoO local bNoPerpCuts = false if i % 2 == 1 then vtOrthoO = Vector3d( vtN) else local vtO if #vCuts[i-1] > 0 then vtO = EgtSurfTmFacetNormVersor( vCuts[i-1][1], 0, GDB_ID.ROOT) elseif vCuts[i+1] and #vCuts[i+1] > 0 then -- lunghezza faccia nell'eventuale direzione ortogonale local asseX = EgtSurfTmFacetNormVersor( vCuts[i+1][1], 0, GDB_ID.ROOT) local asseY = asseX ^ vtN local Frame = Frame3d( ptC, ptC + asseX, ptC + asseY) local b3Fac = EgtGetBBoxRef( vCuts[i][1], GDB_BB.STANDARD, Frame) -- se lunghezza inferiore al limite, accetto la direzione if b3Fac:getDimX() < dMaxDepth - BD.CUT_EXTRA then vtO = asseX else bNoPerpCuts = true end else bNoPerpCuts = true end if vtO then vtOrthoO = Vector3d( vtO) * EgtIf( bOrthInv, -1, 1) else -- ricalcolo tipo taglio perché "bHorizCut" è calcolato sulla feature, mentre il cubetto potrebbe essere lavorato in un altro modo local _, dLen, dWidth = BL.GetFaceHvRefDim( vCuts[i][1], 0, b3Raw) local bCutDirection = bHorizCut -- se bisogna tagliare di fianco ma la lunghezza faccia è più del massimo materiale, forzo lavorazione da sopra if not bHorizCut and dLen > dMaxDepth then bCutDirection = true end if bCutDirection then vtOrthoO = Z_AX() else if vtN:getZ() < dNzLimDwnUp then vtOrthoO = EgtIf( vtN:getY() > -0.02, -Y_AX(), Y_AX()) else vtOrthoO = EgtIf( vtN:getY() > 0.02, Y_AX(), -Y_AX()) end end end end local dDiceFaceMaxH = 0 local dDiceFaceMinH = GEO.INFINITO if ( i % 2) == 0 and bDangerousReliefCut then for j = 1, #vCuts[i] do local _, dDiceFaceH, dDiceFaceV = BL.GetFaceHvRefDim( vCuts[i][j], 0) dDiceFaceMaxH = max( dDiceFaceMaxH, dDiceFaceH) -- calcolo lato orizzontale minore ipotizzando sia un trapezio local dDiceFaceH2 = ( 2 * EgtSurfArea( vCuts[i][j]) ) / dDiceFaceV - dDiceFaceH dDiceFaceMinH = min( dDiceFaceMinH, dDiceFaceH2) end end -- caso speciale con rischio cubetto sul motore if ( i % 2) == 0 and bDangerousReliefCut and ( dMaxDepth > dDiceFaceMaxH - 0.5 * dDiceFaceMinH + BD.CUT_EXTRA_MIN) then local bDoubleCut = false local dCutExtra = BD.CUT_EXTRA if dMaxDepth < dDiceFaceMaxH + BD.CUT_EXTRA then bDoubleCut = true dCutExtra = - 0.5 * dDiceFaceMinH + BD.CUT_EXTRA_MIN end local nSurfToCut = EgtSurfTmBySewing( nAddGrpId, vCuts[i], false) local nFaceUseCut1, nFaceUseCut2 = MCH_MILL_FU.ORTHO_BACK, MCH_MILL_FU.ORTHO_FRONT if Proc.Tail then nFaceUseCut1, nFaceUseCut2 = nFaceUseCut2, nFaceUseCut1 end if bDoubleCut then local bOk, sErr = Fbs.MakeOne( nSurfToCut, 0, sCutting, dSawDiam, nFaceUseCut1, nil, dCutExtra, BD.CUT_SIC, 0, 0, 0, '', b3Raw, true) if not bOk then return false, sErr end end local bOk2, sErr2 = Fbs.MakeOne( nSurfToCut, 0, sCutting, dSawDiam, nFaceUseCut2, nil, dCutExtra, BD.CUT_SIC, 0, 0, 0, '', b3Raw) if not bOk2 then return false, sErr2 end -- caso standard else -- lavoro la faccia for j = 1, #vCuts[i] do -- se taglio dal basso if bDownCut then -- se strato pari composto da 1 o 2 elementi if ( i % 2) == 0 and #vCuts[i] <= 2 then -- il primo elemento prende la direzione prevista, il secondo quella opposta local vtNewOrthoO = Vector3d( vtOrthoO) local dVzLimDwnUp = dNzLimDwnUp if j ~= 1 then vtNewOrthoO = -vtOrthoO if BD.GetNzLimDownUp then dVzLimDwnUp = BD.GetNzLimDownUp( b3Raw, vtN, V_NULL(), true) elseif not BD.C_SIMM and not BD.TURN and abs( vtN:getY()) > 0.05 then dVzLimDwnUp = -0.708 end end local bSpecialTangentLeadInOut = ( i % 2 == 0) and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtNewOrthoO, dVzLimDwnUp, BD.CUT_EXTRA, BD.CUT_SIC, 0, 0, 0, nil, b3Raw, nil, nil, bSpecialTangentLeadInOut) if not bOk then return bOk, sErr end end -- tutti gli altri casi vengono saltati -- caso generale else -- in generale sta sollevato di pochissimo local dExtraCut = -0.1 -- se tagli paralleli if ( i % 2) == 0 then -- se non ci sono tagli ortogonali devo affondare if bNoPerpCuts then dExtraCut = BD.CUT_EXTRA -- se altrimenti tagli ortogonali invertiti, devo approfondire dello spessore lama elseif bOrthInv then dExtraCut = dSawThick -- se ultimo taglio, devo affondare elseif j == #vCuts[i] then dExtraCut = BD.CUT_EXTRA end end local dVzLimDwnUp = dNzLimDwnUp if BD.GetNzLimDownUp then dVzLimDwnUp = BD.GetNzLimDownUp( b3Raw, vtN, V_NULL(), true) elseif not BD.C_SIMM and not BD.TURN and vtN:getZ() > 0.707 then dVzLimDwnUp = -0.708 end local bSpecialTangentLeadInOut = ( i % 2 == 0) and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) local vtOrthoOAlternative if ( i % 2 == 0) and ( Proc.Fct == 1) and bNoPerpCuts then vtOrthoOAlternative = - vtOrthoO end local sLeadInOutTypeFbs = 'Calculated' if ( ( i % 2) ~= 0) then if ( sLeadInOutType == 'Tangent') then sLeadInOutTypeFbs = 'Tangent' elseif ( sLeadInOutType == 'Perpendicular') then sLeadInOutTypeFbs = 'Perpendicular' elseif ( sLeadInOutType == 'PerpendicularOutraw') then sLeadInOutTypeFbs = 'PerpendicularOutraw' end end local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtOrthoO, dVzLimDwnUp, dExtraCut, BD.CUT_SIC, 0, 0, 0, sNotes, b3Raw, nil, nil, bSpecialTangentLeadInOut, sLeadInOutTypeFbs, vtOrthoOAlternative, dDicingOffsetP) if not bOk then return bOk, sErr end end end end end -- altrimenti tagli diretti della faccia else -- impostazioni local dVzLimDwnUp = dNzLimDwnUp local dCutExtra = BD.CUT_EXTRA if Proc.AdvTail then if bHorizCut then dVzLimDwnUp = -0.01 end dCutExtra = -BD.ADVANCE_TAIL_OFFS end -- lavoro la faccia local vtOrthoO if bFromBottom and dCutV < dMaxDepth - BD.CUT_EXTRA and vtN:getZ() > 0 then vtOrthoO = -Z_AX() elseif ( bHorizCut and not bVertCutOk) and ( not bVertCutOk or b3Solid:getDimX() > BD.LEN_SHORT_PART or Proc.AdvTail or ( vtN:getX() > 0 and vtN:getZ() <= 0.708) or ( abs( vtN:getY()) < 0.1 and vtN:getZ() <= 0)) then vtOrthoO = Z_AX() elseif b3Solid:getDimX() < BD.LEN_SHORT_PART and not Proc.AdvTail and abs( vtN:getY()) > 0.259 and vtN:getZ() > -0.174 and abs( vtN:getY()) > abs( vtN:getZ()) and dCutH < dMaxDepth + 10 * GEO.EPS_SMALL then if Proc.Head then vtOrthoO = X_AX() else vtOrthoO = -X_AX() end elseif vtN:getZ() < dVzLimDwnUp and abs( vtN:getY()) > 0.259 and abs( vtN:getY()) > abs( vtN:getZ()) and dCutH < dMaxDepth + 10 * GEO.EPS_SMALL then if Proc.Head then vtOrthoO = X_AX() else vtOrthoO = -X_AX() end else if vtN:getZ() < dVzLimDwnUp or Proc.Tail or ( Proc.Head and abs( vtN:getY()) > 0.01) then vtOrthoO = EgtIf( vtN:getY() > -0.02, -Y_AX(), Y_AX()) elseif Proc.Head then vtOrthoO = EgtIf( vtN:getY() > -0.02, Y_AX(), -Y_AX()) else vtOrthoO = EgtIf( vtN:getY() > 0.02, Y_AX(), -Y_AX()) end -- se è una lavorazione da anticipare diminuisco la profondità del taglio per evitare collisioni con l'albero della lama if Proc.AdvTail then local _, dH = BL.GetFaceHvRefDim( Proc.Id, 0, b3Raw) dCutExtra = min( -BD.ADVANCE_TAIL_OFFS, -dH + dMaxDepth) end end -- taglio local bOk, sErr = Fbs.MakeOne( Proc.Id, 0, sCutting, dSawDiam, vtOrthoO, dVzLimDwnUp, dCutExtra, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end return true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione con testa da sotto local function MakeFromDown( sCutting, Proc, nPhase, nRawId, nPartId, dOvmHead) -- ingombro del grezzo local b3Raw = EgtGetRawPartBBox( nRawId) -- ingombro del pezzo local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- dati geometrici del taglio local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- se vero taglio, eventuale inserimento smussi if ProcessCut.Identify( Proc) then local bOkc, sErrC = MakeChamfer( Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOkc then return bOkc, sErrC end end -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 2 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 dSawThick = EgtTdbGetCurrToolParam(MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end local dMaxVertDepth = dMaxDepth -- determino la direzione di taglio preferenziale local frFac, dCutH, dCutV = BL.GetFaceHvRefDim( Proc.Id, 0, b3Raw) local bHorizCut = ( dCutV < dMaxVertDepth - BD.CUT_EXTRA) or Proc.AdvTail -- 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 -- verifico se necessari tagli supplementari EgtOutLog( string.format( 'MaxDepth=%.1f MaxVertDepth=%.1f CutH=%.1f CutV=%.1f', dMaxDepth, dMaxVertDepth, dCutH, dCutV), 3) local vCuts = {} if not Proc.AdvTail and ( dCutH > dMaxDepth - BD.CUT_EXTRA - 3 * BD.COLL_SIC or dCutV > dMaxVertDepth - BD.CUT_EXTRA - 3 * BD.COLL_SIC) then local ptExtra, vtExtra local bAutoCalcSurf = true if bFillAreaPiece or bFillTail then local ptMiddle = ( b3Solid:getMin() + b3Solid:getMax()) / 2 ptExtra = Point3d( b3Solid:getMin():getX() + 5 * GEO.EPS_SMALL, ptMiddle:getY(), ptMiddle:getZ()) vtExtra = X_AX() bAutoCalcSurf = false end vCuts = DC.GetDice( nAddGrpId, b3Solid, ptC, vtN, bAutoCalcSurf, ptExtra, vtExtra, dMaxVertDepth - BD.CUT_EXTRA, nil ,true) end --DC.PrintOrderCut( vCuts) if #vCuts > 0 then -- sistemo posizione nel DB e nome local bOrthInv = false 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) if ( i % 2) == 1 then local vtO = EgtSurfTmFacetNormVersor( vCuts[i][j], 0, GDB_ID.ROOT) if ( vtN:getY() > 0.707 and vtO:getY() < -0.05) or ( vtN:getY() < -0.707 and vtO:getY() > 0.05) then EgtInvertSurf( vCuts[i][j]) bOrthInv = true end end end end -- eseguo (facendo di seguito i due tagli di ogni singolo cubetto) for i = 1, #vCuts, 2 do -- determino il modo di tagliare dei perpendicolari local vtOrthoO_1 = Vector3d( vtN) -- determino il modo di tagliare dei paralleli local vtOrthoO_2 local bNoPerpCuts_2 = false local vtO if #vCuts[i] > 0 then vtO = EgtSurfTmFacetNormVersor( vCuts[i][1], 0, GDB_ID.ROOT) elseif vCuts[i+2] and #vCuts[i+2] > 0 then -- lunghezza faccia nell'eventuale direzione ortogonale local asseX = EgtSurfTmFacetNormVersor( vCuts[i+2][1], 0, GDB_ID.ROOT) local asseY = asseX ^ vtN local Frame = Frame3d( ptC, ptC + asseX, ptC + asseY) local b3Fac = EgtGetBBoxRef( vCuts[i+1][1], GDB_BB.STANDARD, Frame) -- se lunghezza inferiore al limite, accetto la direzione if b3Fac:getDimX() < dMaxDepth - BD.CUT_EXTRA then vtO = asseX else bNoPerpCuts_2 = true end else bNoPerpCuts_2 = true end if vtO then vtOrthoO_2 = Vector3d( vtO) * EgtIf( bOrthInv, -1, 1) else if bHorizCut then vtOrthoO_2 = -Z_AX() elseif vtN:getY() > -0.02 then if not Proc.Head then vtOrthoO_2 = -Y_AX() else vtOrthoO_2 = Y_AX() end else vtOrthoO_2 = -Y_AX() end end -- lavoro le coppie di facce del singolo cubetto for j = 1, max( #vCuts[i], #vCuts[i+1]) do -- extra taglio per perpendicolari local dExtraCut_1 = -0.1 -- extra taglio per paralleli local dExtraCut_2 = -0.1 -- se non ci sono tagli ortogonali devo affondare if bNoPerpCuts_2 then dExtraCut_2 = BD.CUT_EXTRA -- se altrimenti tagli ortogonali invertiti, devo approfondire dello spessore lama elseif bOrthInv then dExtraCut_2 = dSawThick -- se ultimo taglio, devo affondare elseif j == #vCuts[i+1] then dExtraCut_2 = BD.CUT_EXTRA end -- taglio perpendicolare (limite Vz Down Up messo a -2 per non farlo mai intervenire) if vCuts[i][j] then local bSpecialTangentLeadInOut = ( i % 2 == 0) and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) local bOk, sErr = Fbs.MakeOne( vCuts[i][j], 0, sCutting, dSawDiam, vtOrthoO_1, -2, dExtraCut_1, BD.CUT_SIC, 0, 0, 0, nil, b3Raw, nil, nil, bSpecialTangentLeadInOut) if not bOk then return bOk, sErr end end -- taglio parallelo (limite Vz Down Up messo a -2 per non farlo mai intervenire) if vCuts[i+1][j] then local bSpecialTangentLeadInOut = ( i % 2 == 0) and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) local bOk, sErr = Fbs.MakeOne( vCuts[i+1][j], 0, sCutting, dSawDiam, vtOrthoO_2, -2, dExtraCut_2, BD.CUT_SIC, 0, 0, 0, nil, b3Raw, nil, nil, bSpecialTangentLeadInOut) if not bOk then return bOk, sErr end end end end -- altrimenti tagli diretti della faccia else -- lavoro la faccia local vtOrthoO if bHorizCut and ( b3Solid:getDimX() > BD.LEN_SHORT_PART or Proc.AdvTail or vtN:getX() > 0) then vtOrthoO = -Z_AX() elseif b3Solid:getDimX() < BD.LEN_SHORT_PART and not Proc.AdvTail and abs( vtN:getY()) > 0.259 and vtN:getZ() > -0.174 and abs( vtN:getY()) > abs( vtN:getZ()) and dCutH < dMaxDepth + 10 * GEO.EPS_SMALL then if Proc.Head then vtOrthoO = X_AX() else vtOrthoO = -X_AX() end elseif abs( vtN:getY()) > 0.259 and abs( vtN:getY()) > abs( vtN:getZ()) and dCutH < dMaxDepth + 10 * GEO.EPS_SMALL then if Proc.Head then vtOrthoO = X_AX() else vtOrthoO = -X_AX() end elseif vtN:getY() > -0.02 then if Proc.Head then vtOrthoO = -Y_AX() else vtOrthoO = Y_AX() end else if Proc.Head then vtOrthoO = Y_AX() else vtOrthoO = -Y_AX() end end -- taglio (limite Vz Down Up messo a -2 per non farlo mai intervenire) local dCutExtra = BD.CUT_EXTRA if Proc.AdvTail then dCutExtra = min( -BD.ADVANCE_TAIL_OFFS, dMaxVertDepth - dCutV) end local bOk, sErr = Fbs.MakeOne( Proc.Id, 0, sCutting, dSawDiam, vtOrthoO, -2, dCutExtra, BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end return true end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessCut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead, bFromBottom, bCustDiceCut, bForced, b3Raw, sNotes, dOvmTail, bUpdateIng, nLimitingSurf, sLeadInOutType) -- sovramateriale di coda dOvmTail = dOvmTail or BD.OVM_MID -- ingombro del grezzo b3Raw = b3Raw or EgtGetRawPartBBox( nRawId) -- 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 -- dati geometrici del taglio local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- se taglio di testa if not bForced then if not BL.IsCutNeeded( Proc, b3Raw, dOvmHead, dOvmTail) then return true end end -- abilitazione lavorazione da sotto (testa da sotto e direzione normale sotto -20deg e sbandato oltre 1deg oppure sezione più larga di 2 cubetti o pezzo corto) local bDownHead = ( BD.DOWN_HEAD and vtN:getZ() < -0.341 and ( abs( vtN:getY()) > 0.017 or b3Raw:getDimY() > 2 * ( BD.MAX_DIM_DICE - BD.CUT_EXTRA_MIN) or b3Raw:getDimX() < BD.LEN_SHORT_PART)) local bDownTurn = ( BD.TURN and vtN:getZ() < -0.017) local bTopHead = ( BD.DOWN_HEAD and ( vtN:getZ() > -0.342 or not bDownHead)) -- recupero la lavorazione local sCutType = EgtIf( Proc.Head, 'HeadSide', 'TailSide') local sCutting local bH2 sCutting, bH2 = ML.FindCutting( sCutType, bTopHead, bDownHead) bDownHead = bH2 and bDownHead if not sCutting then local sErr = 'Error : cutting not found in library' EgtOutLog( sErr) return false, sErr end local bNoDicing = false local sWarn -- se taglio con testa da sopra if not bDownHead and not bDownTurn then local bOk, sErr, bNoDicing2 = MakeFromTop( sCutting, Proc, nPhase, nRawId, nPartId, dOvmHead, bFromBottom, bCustDiceCut, bForced, b3Raw, sNotes, nLimitingSurf, sLeadInOutType) bNoDicing = bNoDicing2 if not bOk then return false, sErr else sWarn = sErr end -- altrimenti taglio con testa da sotto else local bOk, sErr = MakeFromDown( sCutting, Proc, nPhase, nRawId, nPartId, dOvmHead) if not bOk then return false, sErr else sWarn = sErr end end -- Aggiornamento ingombro (se vero taglio o richiesto) -- Se lascio il cordolo (bNoDicing) non aggiorno il grezzo perchè lo scarto rimane attaccato if ( ProcessCut.Identify( Proc) or bUpdateIng) and not bNoDicing then UpdateEncumbrance( Proc, vtN, dOvmHead, nRawId, b3Solid, b3Raw) end return true, sWarn end --------------------------------------------------------------------- return ProcessCut