-- BeamExec.lua by Egaltech s.r.l. 2023/12/26 -- Libreria esecuzione lavorazioni per Travi -- 2019/07/11 Aggiunta gestione stato rotazione di feature per TS3. -- 2019/09/04 Corretto controllo feature di testa e coda con sovramateriale di testa elevato. -- 2019/09/25 Aggiunta gestione StepJoint e StepJointNotch. -- 2020/01/21 Aggiunta gestione ScarfJoint. -- 2020/02/10 Aggiunta gestione FrenchRidgeLap. -- 2020/02/11 Aggiunta gestione BlockHausFront. -- 2020/04/02 Fori di testa dal basso non danno errore e fanno ribaltare la trave. -- 2020/04/07 Aggiunta gestione TyroleanDovetail. -- 2020/04/14 Aggiunta gestione Dovetail. -- 2020/05/16 Migliorie ordinamento fori. -- 2020/05/16 Gestione rotazione di 90deg. -- 2020/05/21 Correzione rotazione di 90deg (caso DY > DZ). -- 2020/05/25 Correzione rotazione di 90deg dopo scarico su carico. -- 2020/06/02 Per dati foro si chiama funzione GetData di ProcessDrill (per gestire variazioni di diametro da UserParams). -- 2020/07/25 Ricalcolati flag head e tail della prima parte del foro dopo lo split. -- 2020/07/27 Modifica a ordinamento fori. -- 2020/10/07 Aggiunta distanza libera dietro il pezzo (BDST) scritta nel suo grezzo. -- 2020/10/15 Per foro sdoppiato ricalcolo anche flag Head oltre a Tail . -- 2020/10/23 Corretto spostamento foro per tenone quando tenone nullo. -- 2020/12/29 Aggiunta gestione fori in doppio. -- 2021/02/25 Aggiunta gestione eventuale ricalcolo per macchine tipo PF. -- 2021/07/13 Aggiunta gestione posizionamento pezzo TR/BR per macchine con carico a destra e scarico a sinistra. -- 2021/11/27 House mortise sempre prima di (dt)mortise, house tenon sempre dopo (dt)tenon. -- 2021/12/15 Corretta CompareFeature (risultato deve essere simmetrico scambiando le feature). -- 2021/12/20 Ulteriore correzione a CompareFeature (caso con entrambe senza geometria). -- 2022/05/04 Nell'ordinamento quando si confrontano i box delle feature aggiunta verifica preliminare della loro validità. -- 2022/05/31 Aggiunta gestione sovramateriale per sezioni alte e larghe e informazione di eventuale creazione nuova fase dalla AddFeatureMachining. -- 2022/06/10 Per sezioni alte e larghe modificata la gestione del sovramateriale per considerare la presenza di feature preesistenti ed -- eventuale parametro Q05, che determinano la presenza o meno della finitura. -- Create le funzioni AnalyzeHeadFeatures e AnalyzeTailFeatures. Spostate più in alto le funzioni CollectFeatures, isHeadFeature e isTailFeature. -- 2022/07/01 Aggiunta la gestione delle forature migliorate in presenza di feature testa/coda ad 1 faccia che tagliano tutta la sezione, -- controllata tramite il parametro IMPROVE_HEAD_TAIL_DRILLINGS da BeamData. Attivata di default. -- 2022/08/01 Tolleranza su sezione portata a 0.1 mm (100 * GEO.EPS_SMALL). -- 2022/08/08 Modifica per macchine senza BD.MAX_WIDTH2 e BD.MAX_HEIGHT2. -- 2022/08/18 Aggiunta gestione macchine con testa da sotto con lama da sotto disabilitata. -- 2022/09/28 I fori vengono sempre fatti prima delle tacche. -- 2022/09/29 Aggiunta la ricerca di feature specchiate, al momento solo per DtMortise, con le relative funzioni. -- 2022/12/23 Corrette rotazioni 90 deg per macchine con carico da destra. -- 2022/12/28 Implementata gestione forature e code di rondine in doppio. -- 2023/01/31 Implementata gestione mortase in doppio. -- 2023/01/31 Nelle lavorazioni in doppio aggiunta la minima distanza tra le feature. -- 2023/02/17 Ora le forature che intersecano le mortase sono sempre fatte prima della mortasa stessa. -- 2023/02/17 Nelle tasche in doppio, la distanza minima ammessa tra le feature è stata portata a 50. -- 2023/02/20 Ora le mortase a coda di rondine laterali sono sempre fatte prima dei tagli longitudinali. -- 2023/03/31 Corretto ordinamento per fori di coda da lasciare in coda. -- 2023/07/31 Corretto errore nelle mortase in doppio. -- 2023/09/13 Aggiunta ClassifyTopology per la classificazione topologica delle feature. In CollectFeatures aggiunta la raccolta preliminare di alcune informazioni. -- 2023/09/26 Funzione IsFeatureCuttingEntireSection spostata in BeamLib -- 2023/09/26 In ClassifyTopology aggiunto passaggio del parametro nRawId -- 2023/10/24 Aggiunta scrittura parametro BARLEN nelle info del mach group -- 2023/11/08 Aggiunta gestione processi Variant. -- 2023/11/30 Migliorato il calcolo elevazione con l'utilizzo della nuova funzione EgtSurfTmFacetElevationInBBox. -- 2023/12/26 Modifiche per centrare i pezzi in Y sulla tavola. -- 2024/02/26 Migliorata 'CompareFeatures' per ordine lavorazioni -- Migliorata 'CompareFeatures' per ordine forature -- 2024/02/19 In Collect aggiunta la scrittura nella Proc di Width e Height delle facce. -- 2024/02/29 Migliorata 'CompareFeatures' per ordine forature -- 2024/03/04 Creata funzione calcolo dipendenze tra feature con calcolo topologia. -- 2024/03/07 Implementate le lavorazioni in doppio per fori specchiati non passanti e DrillPocket. -- 2024/03/11 In CollectFeatures si scrive ora Width e Height della faccia sia trimmate con il grezzo che intere. -- 2024/03/13 In CollectFeatures si scrive lunghezza foro su Proc e si controla se serve Predrill -- In OrderFeature, preforo sempre prima del foro -- 2024/04/11 In CollectFeatures aggiunta lettura info PRID, scritta in Proc.FeatureId -- 2024/09/04 Gestione dipendenza foro-tasca in caso di fase con pezzo ribaltato -- Tabella per definizione modulo local BeamExec = {} -- Include require( 'EgtBase') -- Carico i dati globali e libero tutti gli altri _G.package.loaded.BeamData = nil _G.package.loaded.CutData = nil _G.package.loaded.MillingData = nil _G.package.loaded.PocketingData = nil _G.package.loaded.DrillData = nil _G.package.loaded.SawingData = nil local BD = require( 'BeamData') -- Carico le librerie _G.package.loaded.MachiningLib = nil _G.package.loaded.BeamLib = nil _G.package.loaded.DiceCut = nil _G.package.loaded.FacesBySaw = nil _G.package.loaded.ProcessHeadCut = nil _G.package.loaded.ProcessSplit = nil _G.package.loaded.ProcessCut = nil _G.package.loaded.ProcessDoubleCut = nil _G.package.loaded.ProcessLongCut = nil _G.package.loaded.ProcessLongDoubleCut = nil _G.package.loaded.ProcessSawCut = nil _G.package.loaded.ProcessRidgeLap = nil _G.package.loaded.ProcessLapJoint = nil _G.package.loaded.ProcessChamfer = nil _G.package.loaded.ProcessDrill = nil _G.package.loaded.ProcessFrenchRidgeLap = nil _G.package.loaded.ProcessBlockHausFront = nil _G.package.loaded.ProcessTenon = nil _G.package.loaded.ProcessMortise = nil _G.package.loaded.ProcessDtTenon = nil _G.package.loaded.ProcessDtMortise = nil _G.package.loaded.ProcessMark = nil _G.package.loaded.ProcessText = nil _G.package.loaded.ProcessScarfJoint = nil _G.package.loaded.ProcessSimpleScarf = nil _G.package.loaded.ProcessStepJoint = nil _G.package.loaded.ProcessStepJointNotch = nil _G.package.loaded.ProcessProbing = nil _G.package.loaded.ProcessProfFront = nil _G.package.loaded.ProcessProfConcave = nil _G.package.loaded.ProcessProfConvex = nil _G.package.loaded.ProcessProfCamb = nil _G.package.loaded.ProcessProfHead = nil _G.package.loaded.ProcessRoundArch = nil _G.package.loaded.ProcessTyroleanDovetail = nil _G.package.loaded.ProcessDovetail = nil _G.package.loaded.ProcessFreeContour = nil _G.package.loaded.ProcessDecor = nil _G.package.loaded.ProcessVariant = nil local ML = require( 'MachiningLib') local BL = require( 'BeamLib') local Topology = require( 'FeatureTopology') local DC = require( 'DiceCut') local Fbs = require( 'FacesBySaw') local Hcut= require( 'ProcessHeadCut') local Split = require( 'ProcessSplit') local Cut = require( 'ProcessCut') local DoubleCut = require( 'ProcessDoubleCut') local LongCut = require( 'ProcessLongCut') local Long2Cut = require( 'ProcessLongDoubleCut') local SawCut = require( 'ProcessSawCut') local RidgeLap = require( 'ProcessRidgeLap') local LapJoint = require( 'ProcessLapJoint') local Chamfer = require( 'ProcessChamfer') local Drill = require( 'ProcessDrill') local FrenchRidgeLap = require( 'ProcessFrenchRidgeLap') local BlockHausFront = require( 'ProcessBlockHausFront') local Tenon = require( 'ProcessTenon') local Mortise = require( 'ProcessMortise') local DtTenon = require( 'ProcessDtTenon') local DtMortise = require( 'ProcessDtMortise') local Mark = require( 'ProcessMark') local Text = require( 'ProcessText') local ScarfJoint = require( 'ProcessScarfJoint') local Scarf = require( 'ProcessSimpleScarf') local StepJoint = require( 'ProcessStepJoint') local StJoNotch = require( 'ProcessStepJointNotch') local ProfFront = require( 'ProcessProfFront') local ProfConcave = require( 'ProcessProfConcave') local ProfConvex = require( 'ProcessProfConvex') local ProfCamb = require( 'ProcessProfCamb') local ProfHead = require( 'ProcessProfHead') local RoundArch = require( 'ProcessRoundArch') local TyroleanDovetail = require( 'ProcessTyroleanDovetail') local Dovetail = require( 'ProcessDovetail') local FreeContour = require( 'ProcessFreeContour') local Decor = require( 'ProcessDecor') local Variant = require( 'ProcessVariant') EgtOutLog( ' BeamExec started', 1) EgtMdbSetGeneralParam( MCH_GP.MAXDEPTHSAFE, BD.COLL_SIC) EgtMdbSave() ------------------------------------------------------------------------------------------------------------- local function IsHeadFeature( Proc, b3Raw, dCurrOvmH) -- feature sempre di testa o coda per il gruppo if Proc.Grp == 1 or Proc.Grp == 2 then return ( Proc.Box:getCenter():getX() > b3Raw:getCenter():getX() - 0.5 * dCurrOvmH) end -- feature sempre di testa o coda nonostante il gruppo if ( Proc.Grp == 3 or Proc.Grp == 4) and ( Proc.Prc == 38 or Proc.Prc == 51 or Proc.Prc == 56 or Proc.Prc == 100 or Proc.Prc == 101 or Proc.Prc == 102 or Proc.Prc == 103 or Proc.Prc == 106) then return ( Proc.Box:getCenter():getX() > b3Raw:getCenter():getX() - 0.5 * dCurrOvmH) end -- gestioni speciali if LapJoint.Identify( Proc) then return LapJoint.IsHeadFeature( Proc, b3Raw, dCurrOvmH) end if Drill.Identify( Proc) then return Drill.IsHeadFeature( Proc, b3Raw, dCurrOvmH) end if StJoNotch.Identify( Proc) then return StJoNotch.IsHeadFeature( Proc, b3Raw, dCurrOvmH) end if RoundArch.Identify( Proc) then return RoundArch.IsHeadFeature( Proc, b3Raw, dCurrOvmH) end if Dovetail.Identify( Proc) then return Dovetail.IsHeadFeature( Proc, b3Raw, dCurrOvmH) end if FreeContour.Identify( Proc) then return FreeContour.IsHeadFeature( Proc, b3Raw, dCurrOvmH) end -- non è di testa return false end ------------------------------------------------------------------------------------------------------------- local function IsTailFeature( Proc, b3Raw, dCurrOvmH, dCurrOvmT) -- lunghezza di riferimento per spostare le feature di coda appena prima local dAdvTailLen = BD.LEN_VERY_SHORT_PART or BD.LEN_SHORT_PART -- feature sempre di testa o coda per il gruppo (se non troppo lunga) if Proc.Grp == 1 or Proc.Grp == 2 then -- se abilitato avanzamento lavorazione feature di coda e pezzo corto (quindi a caduta) e feature in coda if BD.ADVANCE_TAIL_CUT and b3Raw:getDimX() < dAdvTailLen and Proc.Box:getCenter():getX() < b3Raw:getCenter():getX() - 0.5 * dCurrOvmH then -- se taglio, lo avanzo if Proc.Prc == 10 then return false, true end end -- standard return ( Proc.Box:getCenter():getX() < b3Raw:getCenter():getX() - 0.5 * dCurrOvmH and Proc.Box:getDimX() < BD.MAX_LEN_HTFEA) end -- feature sempre di testa o coda nonostante il gruppo if ( Proc.Grp == 3 or Proc.Grp == 4) and ( Proc.Prc == 38 or Proc.Prc == 51 or Proc.Prc == 56 or Proc.Prc == 100 or Proc.Prc == 101 or Proc.Prc == 102 or Proc.Prc == 103 or Proc.Prc == 106) then -- se abilitato avanzamento lavorazione feature di coda e pezzo corto (quindi a caduta) e feature in coda if BD.ADVANCE_TAIL_CUT and b3Raw:getDimX() < dAdvTailLen and Proc.Box:getCenter():getX() < b3Raw:getCenter():getX() - 0.5 * dCurrOvmH then -- se profilo front solo con smusso, lo avanzo if Proc.Prc == 100 and ProfFront.OnlyChamfer( Proc) then return false, true end -- se profilo concavo solo con smusso, lo avanzo if Proc.Prc == 101 and ProfConcave.OnlyChamfer( Proc) then return false, true end -- se profilo convesso solo con smusso, lo avanzo if Proc.Prc == 102 and ProfConvex.OnlyChamfer( Proc) then return false, true end -- se profilo caudato solo con smusso, lo avanzo if Proc.Prc == 103 and ProfCamb.OnlyChamfer( Proc) then return false, true end -- se profilo head solo con smusso, lo avanzo if Proc.Prc == 106 and ProfHead.OnlyChamfer( Proc) then return false, true end end -- standard return ( Proc.Box:getCenter():getX() < b3Raw:getCenter():getX() - 0.5 * dCurrOvmH) end -- gestioni speciali if LapJoint.Identify( Proc) then return LapJoint.IsTailFeature( Proc, b3Raw) end if Drill.Identify( Proc) then return Drill.IsTailFeature( Proc, b3Raw, dCurrOvmT) end if StJoNotch.Identify( Proc) then return StJoNotch.IsTailFeature( Proc, b3Raw) end if DtMortise.Identify( Proc) then return DtMortise.IsTailFeature( Proc, b3Raw) end if RoundArch.Identify( Proc) then return RoundArch.IsTailFeature( Proc, b3Raw) end if Dovetail.Identify( Proc) then return Dovetail.IsTailFeature( Proc, b3Raw) end if FreeContour.Identify( Proc) then return FreeContour.IsTailFeature( Proc, b3Raw) end -- non è di coda return false end ------------------------------------------------------------------------------------------------------------- local function NeedTopologyFeature( Proc) -- richiedono calcolo topologia if Cut.Identify( Proc) then return true end if DoubleCut.Identify( Proc) then return true end if LongCut.Identify( Proc) then return true end if Long2Cut.Identify( Proc) then return true end if SawCut.Identify( Proc) then return true end if RidgeLap.Identify( Proc) then return true end if LapJoint.Identify( Proc) then return true end if FrenchRidgeLap.Identify( Proc) then return true end if Chamfer.Identify( Proc) then return true end -- tutte le altre non richiedono calcolo topologia return false end ------------------------------------------------------------------------------------------------------------- local function CollectFeatures( PartId, b3Raw, dCurrOvmH, dCurrOvmT) local dRawW = b3Raw:getDimY() local dRawH = b3Raw:getDimZ() -- recupero le feature local vProc = {} local LayerId = {} LayerId[1] = BL.GetAddGroup( PartId) LayerId[2] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Processings') for nInd = 1, 2 do local ProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL) while ProcId do local nEntType = EgtGetType( ProcId) if nEntType == GDB_TY.SRF_MESH or nEntType == GDB_TY.EXT_TEXT or nEntType == GDB_TY.CRV_LINE or nEntType == GDB_TY.CRV_ARC or nEntType == GDB_TY.CRV_BEZ or nEntType == GDB_TY.CRV_COMPO then local nGrp = EgtGetInfo( ProcId, 'GRP', 'i') local nPrc = EgtGetInfo( ProcId, 'PRC', 'i') local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1 local nCutId = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0 local nTaskId = EgtGetInfo( ProcId, 'TASKID', 'i') or 0 -- leggo se ci sono feature collegate local nAddAdjId = EgtGetInfo( ProcId, 'ADJID', 'i') local nAddMainId = EgtGetInfo( ProcId, 'MAINID', 'i') local nFeatureId = EgtGetInfo( ProcId, 'PRID', 'i') if nGrp and nPrc and nDo == 1 then local Proc = {} Proc.PartId = PartId Proc.Id = ProcId Proc.Grp = nGrp Proc.Prc = nPrc Proc.Flg = 1 Proc.Fct = EgtSurfTmFacetCount( ProcId) or 0 Proc.Diam = 0 Proc.Fcs = 0 Proc.Fce = 0 Proc.CutId = nCutId Proc.TaskId = nTaskId Proc.FeatureId = nFeatureId or Proc.TaskId -- se ci sono feature collegate ne scrivo il riferimento nella Proc if nAddAdjId then Proc.AdjId = Proc.Id + nAddAdjId elseif nAddMainId then Proc.MainId = Proc.Id + nAddMainId end Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) if b3Raw then -- recupero l'elenco delle facce della parte interessate dalla feature Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) -- recupero informazioni sulle facce della feature if not Proc.Face then Proc.Face = BL.GetFacetsInfo( Proc, b3Raw) end end if Proc.Box and not Proc.Box:isEmpty() then Proc.Head = IsHeadFeature( Proc, b3Raw, dCurrOvmH) Proc.Tail, Proc.AdvTail = IsTailFeature( Proc, b3Raw, dCurrOvmH, dCurrOvmT) table.insert( vProc, Proc) -- se foro if Drill.Identify( Proc) then -- assegno diametro e facce di ingresso e uscita (dati tabelle sempre per riferimento) Proc.Diam, Proc.Len, Proc.Fcs, Proc.Fce = Drill.GetData( Proc, b3Raw) -- verifico se devo inserire i prefori if Drill.IsPredrillNeeded( Proc) then local bAddProc, PredrillProc= Drill.AddPredrillFromDrillProc( Proc) if bAddProc then table.insert( vProc, PredrillProc) end end -- verifico se necessaria seconda lavorazione da parte opposta per foro più lungo della punta if Drill.Split( Proc, b3Raw) then -- aggiorno flags prima parte foro (dati tabelle sempre per riferimento) Proc.Flg = 2 Proc.Head = Drill.IsHeadFeature( Proc, b3Raw, dCurrOvmH) Proc.Tail = Drill.IsTailFeature( Proc, b3Raw, dCurrOvmH, dCurrOvmT) -- definisco dati seconda parte local Proc2 = {} Proc2.PartId = PartId Proc2.Id = ProcId Proc2.Grp = nGrp Proc2.Prc = nPrc Proc2.Flg = -2 Proc2.Box = BBox3d( Proc.Box) Proc2.Fct = Proc.Fct Proc2.Diam = Proc.Diam Proc2.Len = Proc.Len Proc2.Head = Drill.IsHeadFeature( Proc2, b3Raw, dCurrOvmH) Proc2.Tail = Drill.IsTailFeature( Proc2, b3Raw, dCurrOvmH) Proc2.Fcs = Proc.Fce Proc2.Fce = Proc.Fcs Proc2.CutId = Proc.CutId Proc2.TaskId = Proc.TaskId Proc2.AdjId = Proc.AdjId Proc2.MainId = Proc.MainId -- recupero l'elenco delle facce della parte interessate dalla feature Proc2.AffectedFaces = BL.GetProcessAffectedFaces( Proc2) table.insert( vProc, Proc2) -- verifico se devo inserire i prefori if Drill.IsPredrillNeeded( Proc2) then local bAddProc, PredrillProc= Drill.AddPredrillFromDrillProc( Proc2) if bAddProc then table.insert( vProc, PredrillProc) end end end -- se BlockHaus HalfLap elseif Proc.Prc == 37 then local nFacInd = BL.GetFaceWithMostAdj( Proc, PartId) if nFacInd then local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) if vtN then Proc.vtN = Vector3d( vtN) end end end else Proc.Head = false Proc.Tail = false Proc.Flg = 0 table.insert( vProc, Proc) EgtOutLog( ' Feature ' .. tostring( Proc.Id) .. ' is empty (no geometry)') end end end ProcId = EgtGetNext( ProcId) end end return vProc end ------------------------------------------------------------------------------------------------------------- local function CalcHeadTailMachBeforeIntersDrillings( vProc, b3Raw) local nHeadId local dHeadX = GEO.INFINITO local nTailId local dTailX = -GEO.INFINITO local b3HeadBox local b3TailBox for i = 1, #vProc do local Proc = vProc[i] if Proc.Box and not Proc.Box:isEmpty() then if Proc.Fct == 1 and BL.IsFeatureCuttingEntireSection( Proc.Box, b3Raw:getDimY(), b3Raw:getDimZ()) and ( Proc.Head or Proc.Tail) and Proc.Prc ~= 340 and Proc.Prc ~= 350 then if Proc.Head and Proc.Box:getCenter():getX() < dHeadX then dHeadX = Proc.Box:getCenter():getX() nHeadId = Proc.Id b3HeadBox = Proc.Box elseif Proc.Tail and Proc.Box:getCenter():getX() > dTailX then dTailX = Proc.Box:getCenter():getX() nTailId = Proc.Id b3TailBox = Proc.Box end end end end local vMachBeforeIntersDrillings = { Head = { Id = nHeadId, Box = b3HeadBox}, Tail = { Id = nTailId, Box = b3TailBox} } return vMachBeforeIntersDrillings end ------------------------------------------------------------------------------------------------------------- local function AnalyzeHeadFeatures( b3Solid, vProc, dRawW, dRawH) local nReplacedFeatureId = nil local bHeadFinishingNeeded = true local nCuttingFeatureId = nil for i = 1, #vProc do local Proc = vProc[i] -- controllo se esiste già una feature taglio di testa if not nReplacedFeatureId then if ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10 then local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) if ptC and vtN and AreSameVectorApprox( vtN, X_AX()) and abs( ptC:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL then nReplacedFeatureId = Proc.Id end end end if Proc.Head and Proc.Id ~= nReplacedFeatureId and Proc.Prc ~= 340 then -- controllo se la feature taglia l'intera sezione; in caso positivo la finitura non è necessaria bHeadFinishingNeeded = not BL.IsFeatureCuttingEntireSection( Proc.Box, dRawW, dRawH) if not bHeadFinishingNeeded and ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10) and ( Proc.Flg > 0) then nCuttingFeatureId = Proc.Id end end end return bHeadFinishingNeeded, nReplacedFeatureId, nCuttingFeatureId end ------------------------------------------------------------------------------------------------------------- local function AnalyzeTailFeatures( b3Solid, vProc, dRawW, dRawH) local nReplacedFeatureId = nil local bTailFinishingNeeded = true local nCuttingFeatureId = nil for i = 1, #vProc do local Proc = vProc[i] -- controllo se esistè già una feature taglio di coda if not nReplacedFeatureId then if ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10 then local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) if ptC and vtN and AreSameVectorApprox( vtN, -X_AX()) and abs( ptC:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL then nReplacedFeatureId = Proc.Id end end end if Proc.Tail and Proc.Id ~= nReplacedFeatureId and Proc.Prc ~= 350 then -- controllo se la feature taglia l'intera sezione; in caso positivo la finitura non è necessaria bTailFinishingNeeded = not BL.IsFeatureCuttingEntireSection( Proc.Box, dRawW, dRawH) if not bTailFinishingNeeded and ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10) and ( Proc.Flg > 0) then nCuttingFeatureId = Proc.Id end end end return bTailFinishingNeeded, nReplacedFeatureId, nCuttingFeatureId end ------------------------------------------------------------------------------------------------------------- -- *** Inserimento delle travi nel grezzo *** ------------------------------------------------------------------------------------------------------------- local function VerifyBigSectionCut( dRawW, dRawH) -- lama principale local sCutting = ML.FindCutting( 'TailSide') local dMaxDepth = 50 if EgtMdbSetCurrMachining( sCutting or '') then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid or '') or '') then dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end local dMaxVertDepth = dMaxDepth - ( BD.DECR_VERT_CUT or 0) -- eventuale lama su testa sotto local sCutting2 = ML.FindCutting( 'TailSide_H2', false, true) local dMaxDepth2 = 0 if sCutting2 and EgtMdbSetCurrMachining( sCutting2) then local sTuuid2 = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid2) or '') then dMaxDepth2 = EgtTdbGetCurrToolMaxDepth() or dMaxDepth2 end end -- verifiche local dDimYRef = EgtIf( dRawH < BD.MIN_DIM_HBEAM + 10 * GEO.EPS_SMALL, dMaxDepth, abs( BD.MAX_DIM_HTCUT_HBEAM)) local bBigSectionCut = ( dRawW > 2 * dDimYRef - BD.CUT_EXTRA_MIN + 10 * GEO.EPS_SMALL) and ( dRawH > EgtIf( BD.TURN, 2 * dMaxVertDepth, dMaxVertDepth + dMaxDepth2) - 2 * BD.CUT_EXTRA_MIN + 10 * GEO.EPS_SMALL) return bBigSectionCut end ------------------------------------------------------------------------------------------------------------- function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, vBeam, bMachGroupOk) -- default per nuove costanti qualora non definite BD.OVM_BLADE_HBEAM = ( BD.OVM_BLADE_HBEAM or 11) BD.OVM_CHAIN_HBEAM = ( BD.OVM_CHAIN_HBEAM or 8) -- sovramateriale intermedio nullo se non definito dOvmMid = ( dOvmMid or 0) -- Determinazione minimo grezzo scaricabile BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) -- Creazione nuovo gruppo di lavoro if not bMachGroupOk then local sMgName = EgtGetMachGroupNewName( 'Mach_1') local NewMgId = EgtAddMachGroup( sMgName) if not NewMgId then local sOut = 'Errore nella creazione del gruppo di lavoro ' .. sMgName return false, sOut end end -- Impostazione della tavola EgtSetTable( 'Tab') -- salvo nota con lunghezza grezzo -- Recupero l'identificativo del gruppo di lavoro corrente local nMGrpId = EgtGetCurrMachGroup() -- Area tavola local b3Tab = EgtGetTableArea() -- Calcolo posizione estremo TR/BR della tavola rispetto a sua origine in BL local dPosY = EgtIf( BD.CENTER_BEAM, ( b3Tab:getDimY() + dRawW * EgtIf( BD.RIGHT_LOAD, -1, 1)) / 2, EgtIf( BD.RIGHT_LOAD, 0, b3Tab:getDimY())) BD.OriXR = Point3d( b3Tab:getDimX(), dPosY, 0) BD.PosXR = EgtIf( BD.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR) -- Impostazione dell'attrezzaggio di default EgtImportSetup() -- se pretagli di coda sono attivi, aumento di 10mm la lunghezza del grezzo per fare effettivamente tagliare del materiale. -- Altrimenti le lavorazioni pensano di essere nel vuoto e si muovono in rapido if BD.PRECUT_TAIL and VerifyBigSectionCut( dRawW, dRawH) then dRawL = dRawL + 10 end -- Lunghezza della barra local dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd') if not dBarLen then EgtSetInfo( nMGrpId, 'BARLEN', dRawL) end -- Inserimento dei pezzi con il loro grezzo local Cnt = 0 local Len = dRawL local nPrevRaw, dPrevDelta local DeltaS = dOvmHead local DeltaSMin = 0 local DeltaE = BD.OVM_MID -- controllo sezione larga e alta per considerare taglio con sega a catena local bBigSectionCut = VerifyBigSectionCut( dRawW, dRawH) for i = 1, #vBeam do -- assegno identificativo pezzo local Pz = vBeam[i].Id -- dati del pezzo local b3Part = EgtGetBBoxGlob( Pz or GDB_ID.NULL, GDB_BB.EXACT) local b3Solid = vBeam[i].Box if b3Part:isEmpty() or b3Solid:isEmpty() then break end -- creo o pulisco gruppo geometrie aggiuntive if not BL.CreateOrEmptyAddGroup( Pz) then local sOut = 'Error creating Additional Group in Part ' .. tostring( Pz) return false, sOut end -- analizzo le features per valutare l'esistenza di feature head/tail che renderebbero inutili le rispettive finiture o di tagli di testa/coda sostituiti da cui leggere il parametro Q05 local vProc = CollectFeatures( Pz, b3Solid, 0) local bSFinishingNeeded, nReplacedHeadCutFeatureId, nHeadCuttingFeatureId = AnalyzeHeadFeatures( b3Solid, vProc, dRawW, dRawH) local bEFinishingNeeded, nReplacedTailCutFeatureId, nTailCuttingFeatureId = AnalyzeTailFeatures( b3Solid, vProc, dRawW, dRawH) -- Scrivo gli id delle facce di taglio custom: serviranno dopo per calcolare l'elevazione rispetto a queste if nHeadCuttingFeatureId then EgtSetInfo( vBeam[i].Id, 'HEADCUTFEATUREID', nHeadCuttingFeatureId) else EgtRemoveInfo( vBeam[i].Id, 'HEADCUTFEATUREID') end if nTailCuttingFeatureId then EgtSetInfo( vBeam[i].Id, 'TAILCUTFEATUREID', nTailCuttingFeatureId) else EgtRemoveInfo( vBeam[i].Id, 'TAILCUTFEATUREID') end if bBigSectionCut then -- lascio in coda solo il materiale necessario; il resto verrà tolto nell'head cut successivo local lastB3Solid = nil local dOffset = dOvmHead if i > 1 then if vBeam[i].PosX then lastB3Solid = vBeam[i-1].Box dOffset = vBeam[i].PosX - vBeam[i-1].PosX - lastB3Solid:getDimX() else dOffset = dOvmMid end end local iSQ05Value = nil if nReplacedHeadCutFeatureId then iSQ05Value = EgtGetInfo( nReplacedHeadCutFeatureId, 'Q05', 'i') end if ( dOffset <= BD.OVM_CHAIN_HBEAM and iSQ05Value == 0) or not bSFinishingNeeded then DeltaSMin = 0 else DeltaSMin = BD.OVM_BLADE_HBEAM end local iEQ05Value = nil if nReplacedTailCutFeatureId then iEQ05Value = EgtGetInfo( nReplacedTailCutFeatureId, 'Q05', 'i') end if iEQ05Value == 0 or not bEFinishingNeeded then DeltaE = BD.OVM_CHAIN_HBEAM else DeltaE = BD.OVM_CHAIN_HBEAM + BD.OVM_BLADE_HBEAM end end EgtOutLog( 'PartSez=' .. EgtNumToString( b3Part:getDimY(), 1) .. 'x' .. EgtNumToString( b3Part:getDimZ(), 1), 3) -- se sezione compatibile e lunghezza disponibile sufficiente local PartLen = b3Solid:getDimX() local PartWidth = b3Solid:getDimY() local PartHeight = b3Solid:getDimZ() local NextLen = Len - DeltaS - PartLen - DeltaE if (( abs( PartWidth - dRawW) < 100 * GEO.EPS_SMALL and abs( PartHeight - dRawH) < 100 * GEO.EPS_SMALL) or ( abs( PartHeight - dRawW) < 100 * GEO.EPS_SMALL and abs( PartWidth - dRawH) < 100 * GEO.EPS_SMALL)) and NextLen + DeltaE >= 0 then -- eventuale sovramateriale di testa if i > 1 then if vBeam[i].PosX then DeltaS = max( vBeam[i].PosX - ( dRawL - Len), DeltaSMin) else DeltaS = max( dOvmMid - DeltaE, 0) end end -- dimensioni del grezzo local CrawLen = min( PartLen + DeltaS + DeltaE, Len) local Delta = CrawLen - PartLen - DeltaS -- creo e posiziono il grezzo local nRaw = EgtAddRawPart( Point3d(0,0,0), CrawLen, dRawW, dRawH, BD.RAWCOL) EgtMoveToCornerRawPart( nRaw, BD.OriXR, BD.PosXR) EgtMoveRawPart( nRaw, Vector3d( Len - dRawL, 0, 0)) -- assegno ordine in lavorazione Cnt = Cnt + 1 EgtSetInfo( nRaw, 'ORD', Cnt) -- aggiungo faccia per taglio iniziale al pezzo BL.AddPartStartFace( Pz, b3Solid) -- se sovramateriale di testa, lo notifico if DeltaS > 0.09 then EgtSetInfo( nRaw, 'HOVM', DeltaS) if nPrevRaw then EgtSetInfo( nPrevRaw, 'BDST', DeltaS + dPrevDelta) end end if DeltaE > 0.09 then EgtSetInfo( nRaw, 'TOVM', DeltaE) end -- aggiungo faccia per taglio finale al pezzo BL.AddPartEndFace( Pz, b3Solid) -- inserisco il pezzo nel grezzo EgtDeselectPartObjs( Pz) local ptPos = b3Part:getMin() - b3Solid:getMin() + Vector3d( Delta, ( dRawW - PartWidth) / 2, ( dRawH - PartHeight) / 2) EgtAddPartToRawPart( Pz, ptPos, nRaw) if abs( PartWidth - dRawW) > 100 * GEO.EPS_SMALL then -- rotazione attorno a centro geometria complessiva del pezzo EgtRotatePartInRawPart( Pz, X_AX(), 90) -- correggo per eccentricità solido rispetto a geometria complessiva del pezzo local vtEccOri = b3Solid:getCenter() - b3Part:getCenter() local vtEccRot = Vector3d( vtEccOri) vtEccRot:rotate( X_AX(), 90) EgtMovePartInRawPart( Pz, ( vtEccOri - vtEccRot)) end -- aggiorno la lunghezza residua della barra Len = Len - CrawLen -- aggiorno grezzo precedente nPrevRaw = nRaw dPrevDelta = Delta else local sOut = 'Error: part L(' .. EgtNumToString( PartLen, 1) .. ') too big for raw part L(' .. EgtNumToString( Len - 0.1, 1) .. ')' return false, sOut end -- se rimasto troppo poco grezzo, esco --if Len < BD.MinRaw then break end DeltaS = 0 end if nPrevRaw then EgtSetInfo( nPrevRaw, 'BDST', 10000) end -- Se rimasto materiale aggiungo grezzo dell'avanzo if Len > 10 then local nRaw = EgtAddRawPart( Point3d(0,0,0), Len, dRawW, dRawH, BD.RAWCOL) EgtMoveToCornerRawPart( nRaw, BD.OriXR, BD.PosXR) EgtMoveRawPart( nRaw, Vector3d( Len - dRawL, 0, 0)) -- assegno ordine in lavorazione Cnt = Cnt + 1 EgtSetInfo( nRaw, 'ORD', Cnt) end return true end ------------------------------------------------------------------------------------------------------------- function BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) if BD.GetMinUnloadableRaw then BD.MinRaw = BD.GetMinUnloadableRaw( dRawW, dRawH) else local H_S = 200 local H_L = 400 -- Determinazione minimo grezzo scaricabile if dRawH <= H_S then BD.MinRaw = BD.MINRAW_S elseif dRawH <= H_L then local Coeff = ( dRawH - H_S) / ( H_L - H_S) BD.MinRaw = ( 1 - Coeff) * BD.MINRAW_S + Coeff * BD.MINRAW_L else BD.MinRaw = BD.MINRAW_L end end end ------------------------------------------------------------------------------------------------------------- -- *** Inserimento delle lavorazioni nelle travi *** ------------------------------------------------------------------------------------------------------------- local function Verify90DegRotation( nRawId) if not nRawId then return false end -- dimensioni sezione trave in posizione normale (rotazione 0°) local dRawW = EgtGetRawPartBBox( nRawId):getDimY() local dRawH = EgtGetRawPartBBox( nRawId):getDimZ() -- verifica dell'altezza rispetto alla massima larghezza if not BD.MAX_WIDTH2 or not BD.MAX_HEIGHT2 then return ( dRawH < BD.MAX_WIDTH + 10 * GEO.EPS_SMALL and dRawW < BD.MAX_HEIGHT + 10 * GEO.EPS_SMALL) else return ( dRawH < BD.MAX_WIDTH + 10 * GEO.EPS_SMALL and dRawW < BD.MAX_HEIGHT + 10 * GEO.EPS_SMALL) or ( dRawH < BD.MAX_WIDTH2 + 10 * GEO.EPS_SMALL and dRawW < BD.MAX_HEIGHT2 + 10 * GEO.EPS_SMALL) end end ------------------------------------------------------------------------------------------------------------- local function PrintFeatures( vProc, b3Raw) EgtOutLog( ' RawBox=' .. tostring( b3Raw)) for i = 1, #vProc do local Proc = vProc[i] local sOut = string.format( ' Id=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Down=%s Side=%s Head=%s Tail=%s Fcse=%1d,%1d Diam=%.2f Fct=%2d Box=%s TopoName=%s', Proc.Id, Proc.Grp, Proc.Prc, Proc.TaskId, Proc.CutId, Proc.Flg, EgtIf( Proc.Down, 'T', 'F'), EgtIf( Proc.Side, 'T', 'F'), EgtIf( Proc.Head, 'T', 'F'), EgtIf( Proc.Tail, 'T', EgtIf( Proc.AdvTail, 'A', 'F')), Proc.Fcs, Proc.Fce, Proc.Diam, Proc.Fct, tostring( Proc.Box), Proc.TopologyLongName or '') -- info speciali per Block Haus Half Lap if Proc.Prc == 37 then local sSpec = string.format( ' N=%s Hd=%s', tostring( Proc.vtN or V_NULL()), EgtIf( Proc.HeadDir, 'T', 'F')) sOut = sOut .. sSpec end EgtOutLog( sOut) end end ------------------------------------------------------------------------------------------------------------- -- mi assicuro che i tagli di testa e coda troncanti (usati per ridurre i percorsi utensile in testa e coda) siano sempre fatti per primi local function ReorderTruncatingCuts( vProc, nPartId) if not nPartId or #vProc == 0 then return end local nHeadCuttingFeatureId = EgtGetInfo( nPartId, 'HEADCUTFEATUREID', 'i') local nTailCuttingFeatureId = EgtGetInfo( nPartId, 'TAILCUTFEATUREID', 'i') -- tagli di testa -- 1: si trovano gli indici del taglio di testa e del rispettivo taglio troncante local nHeadCutIndex, nHeadCuttingFeatureIndex for index, value in ipairs( vProc) do if value.Prc == 340 then nHeadCutIndex = index end if value.Id == nHeadCuttingFeatureId then nHeadCuttingFeatureIndex = index end end -- 2: se non c'è il taglio di testa, il taglio troncante è il primo. Se c'è il taglio di testa, il taglio troncante lo deve seguire. if not nHeadCutIndex and nHeadCuttingFeatureIndex then local HeadCuttingFeature = vProc[ nHeadCuttingFeatureIndex] table.remove( vProc, nHeadCuttingFeatureIndex) table.insert( vProc, 1, HeadCuttingFeature) elseif nHeadCutIndex and nHeadCuttingFeatureIndex then if abs( nHeadCutIndex - nHeadCuttingFeatureIndex) ~= 1 then local HeadCut = vProc[ nHeadCutIndex] local HeadCuttingFeature = vProc[ nHeadCuttingFeatureIndex] table.remove( vProc, nHeadCutIndex) -- rimuovere il primo potrebbe aver cambiato l'indice del secondo if nHeadCutIndex < nHeadCuttingFeatureIndex then nHeadCuttingFeatureIndex = nHeadCuttingFeatureIndex - 1 end table.remove( vProc, nHeadCuttingFeatureIndex) table.insert( vProc, nHeadCutIndex, HeadCut) table.insert( vProc, nHeadCutIndex + 1, HeadCuttingFeature) end end -- tagli di coda -- 1: si trovano gli indici del taglio di coda e del rispettivo taglio troncante local nTailCutIndex, nTailCuttingFeatureIndex for index, value in ipairs( vProc) do if value.Prc == 350 then nTailCutIndex = index end if value.Id == nTailCuttingFeatureId then nTailCuttingFeatureIndex = index end end -- 2: il taglio di coda c'è sempre. Il taglio troncante lo deve seguire. if nTailCutIndex and nTailCuttingFeatureIndex then if abs( nTailCutIndex - nTailCuttingFeatureIndex) ~= 1 then local TailCut = vProc[ nTailCutIndex] local TailCuttingFeature = vProc[ nTailCuttingFeatureIndex] table.remove( vProc, nTailCutIndex) -- rimuovere il primo potrebbe aver cambiato l'indice del secondo if nTailCutIndex < nTailCuttingFeatureIndex then nTailCuttingFeatureIndex = nTailCuttingFeatureIndex - 1 end table.remove( vProc, nTailCuttingFeatureIndex) table.insert( vProc, nTailCutIndex, TailCut) table.insert( vProc, nTailCutIndex + 1, TailCuttingFeature) end end return true end ------------------------------------------------------------------------------------------------------------- -- mi assicuro che vengano rispettate le dipendenze tra le feature local function ReorderFeatureWithDependency( vProc) -- si riordina considerando le dipendenze con alcuni limiti: -- * se ci sono dipendenze incrociate il risultato finale non è controllato ( A->B e B->C e C->A) -- * se ci sono dipendenze opposte va in errore ( A->B e B->A) -- si sistemano le feature da lavorare prima local i = 1 local nMaxIter = ( #vProc * #vProc) + 1 local nIter = 0 while i <= #vProc do nIter = nIter + 1 if nIter > nMaxIter then error( "UNEXPECTED ERROR ON DEPENDENCY") end -- si controllano solo i fori if Drill.Identify( vProc[i]) and vProc[i].Dependency and vProc[i].Dependency.ExecBefore and vProc[i].Dependency.ExecBefore.Id then local nRefId = vProc[i].Dependency.ExecBefore.Id local nRefIndex for j = 1, #vProc do if i ~= j and vProc[j].Id == nRefId then nRefIndex = j break end end -- se il processo deve stare prima, ma ora è dopo if nRefIndex and nRefIndex < i then table.insert( vProc, nRefIndex, table.remove( vProc, i)) i = max( nRefIndex - 1, 1) end end i = i + 1 end end ------------------------------------------------------------------------------------------------------------- local function OrderFeatures( vProc, b3Raw, nPartId) local dDrillPenalty = EgtIf( BD.PRESS_ROLLER, 200, 100) local dSmallDrillRange = EgtIf( b3Raw:getDimX() < BD.LEN_SHORT_PART, BD.DRILL_RANGE_SP or 200, BD.DRILL_RANGE or 600) -- funzione di confronto -- secondo centro box in X (taglio di intestazione prima di altri tagli di testa e taglio di separazione però prima di altri tagli di coda) local function CompareFeatures( B1, B2) -- se primo disabilitato e secondo no va dopo if B1.Flg == 0 and B2.Flg ~= 0 then return false end -- se secondo disabilitato e primo no va lasciato dopo if B2.Flg == 0 and B1.Flg ~= 0 then return true end -- se entrambi disabilitati seguo l'Id if B1.Flg == 0 and B2.Flg == 0 then return ( B1.Id < B2.Id) end -- se primo è intestazione va sempre prima if Hcut.Identify( B1) then return true end -- se l'altro è intestazione va sempre prima if Hcut.Identify( B2) then return false end -- se uno dipende dall'altro if B1.Dependency and B1.Dependency.ExecBefore and B1.Dependency.ExecBefore.Id == B2.Id then return true end if B2.Dependency and B2.Dependency.ExecBefore and B2.Dependency.ExecBefore.Id == B1.Id then return false end -- se uno di testa e non l'altro, privilegio quello di testa (a meno che non siano dei fori) if B1.Head ~= B2.Head and not Drill.Identify(B1) and not Drill.Identify(B2) then return B1.Head end -- se entrambi di testa e intersecano stesse facce e primo è scasso a due facce e secondo è un profilo caudato, lo scasso è una riduzione e va fatto prima if ( ( B1.Head and B2.Head) or ( B1.Tail and B2.Tail)) and B1.Topology == 'Rabbet' and ( ProfCamb.Identify( B2) or ProfConcave.Identify( B2) or ProfConvex.Identify( B2)) then return true end -- se entrambi di testa e intersecano stesse facce e primo è un profilo caudato e secondo è scasso a due facce, lo scasso è una riduzione e va lasciato dopo if ( ( B1.Head and B2.Head) or ( B1.Tail and B2.Tail)) and B2.Topology == 'Rabbet' and ( ProfCamb.Identify( B1) or ProfConcave.Identify( B1) or ProfConvex.Identify( B1)) then return false end -- se entrambi di testa e primo è scasso o mortasa e secondo no va messo dopo if B1.Head and B2.Head and ( LapJoint.Identify( B1) or Mortise.Identify( B1) or DtMortise.Identify( B1)) and not ( LapJoint.Identify( B2) or Mortise.Identify( B2) or DtMortise.Identify( B2)) then return false end -- se entrambi di testa e secondo è scasso o mortasa e primo no va lasciato dopo if B1.Head and B2.Head and ( LapJoint.Identify( B2) or Mortise.Identify( B2) or DtMortise.Identify( B2)) and not ( LapJoint.Identify( B1) or Mortise.Identify( B1) or DtMortise.Identify( B1)) then return true end -- se primo è feature di coda anticipata e l'altro non è feature di coda if B1.AdvTail and ( not Split.Identify( B2) or not B2.Tail) then return false end -- se secondo è feature di coda anticipata e l'altro non è feature di coda if B2.AdvTail and ( not Split.Identify( B1) or not B1.Tail) then return true end -- se primo è foro e secondo è un ribasso o tenone, il foro va sempre prima a meno che il ribasso non sia di testa if Drill.Identify(B1) and ( LapJoint.Identify(B2) or Mortise.Identify(B2) or Tenon.Identify(B2)) and B2.PassedByHole and B1.Box:getCenter():getX() > B2.Box:getMin():getX() and B1.Box:getCenter():getX() < B2.Box:getMax():getX() then return true end -- se primo è un ribasso e secondo è un foro o tenone, il ribasso va sempre dopo a meno che il ribasso non sia di testa if ( LapJoint.Identify(B1) or Mortise.Identify(B1) or Tenon.Identify(B1)) and B1.PassedByHole and Drill.Identify(B2) and B2.Box:getCenter():getX() > B1.Box:getMin():getX() and B2.Box:getCenter():getX() < B1.Box:getMax():getX() then return false end -- se primo è ribasso e secondo è una mortasa a coda di rondine, il ribasso va sempre prima a meno che la mortasa a coda di rondine non sia di testa if LapJoint.Identify(B1) and B1.PassedByDtMortise and DtMortise.SideIdentify(B2) and B2.Box:getCenter():getX() > B1.Box:getMin():getX() and B2.Box:getCenter():getX() < B1.Box:getMax():getX() then return true end -- se primo è mortasa a coda di rondine e secondo è ribasso, la mortasa a coda di rondine va sempre dopo a meno che la mortasa a coda di rondine non sia di testa if DtMortise.SideIdentify(B1) and LapJoint.Identify(B2) and B2.PassedByDtMortise and B1.Box:getCenter():getX() > B2.Box:getMin():getX() and B1.Box:getCenter():getX() < B2.Box:getMax():getX() then return false end -- se primo è feature di coda e l'altro è separazione o non è feature di coda if B1.Tail and ( Split.Identify( B2) or not B2.Tail) then return false end -- se secondo è feature di coda e l'altro è separazione o non è feature di coda if B2.Tail and ( Split.Identify( B1) or not B1.Tail) then return true end -- se primo è scasso o mortasa di coda e secondo no, sempre dopo if B1.Tail and ( LapJoint.Identify( B1) or Mortise.Identify( B1) or DtMortise.Identify( B1)) and not B2.Tail and ( ( LapJoint.Identify( B2) or Mortise.Identify( B2) or DtMortise.Identify( B2))) then return false end -- se secondo è scasso o mortasa di coda e primo no, va lasciato dopo if B2.Tail and ( LapJoint.Identify( B2) or Mortise.Identify( B2) or DtMortise.Identify( B2)) and not B1.Tail and ( ( LapJoint.Identify( B1) or Mortise.Identify( B1) or DtMortise.Identify( B1))) then return true end -- se entrambi di coda e il primo è una feature taglio di lama e il secondo no, feature taglio lama sempre prima if B1.Tail and B2.Tail and ( Cut.Identify( B1) or DoubleCut.Identify( B1)) and ( not Cut.Identify( B2) and not DoubleCut.Identify( B2)) then return true end -- se entrambi di coda e il secondo è una feature taglio di lama e il primo no, feature taglio lama sempre prima if B1.Tail and B2.Tail and ( Cut.Identify( B2) or DoubleCut.Identify( B2)) and ( not Cut.Identify( B1) and not DoubleCut.Identify( B1)) then return false end -- se primo è taglio longitudinale completo o altra lav. lunga, dopo tutte le altre feature non di coda if abs( B1.Box:getDimX() - b3Raw:getDimX()) < 0.2 * b3Raw:getDimX() then -- se anche l'altra è lunga, faccio prima quello piccolo in YZ if abs( B2.Box:getDimX() - b3Raw:getDimX()) < 0.2 * b3Raw:getDimX() then if abs( B1.Box:getDimY() * B1.Box:getDimZ() - B2.Box:getDimY() * B2.Box:getDimZ()) < 10 then return B1.Id < B2.Id else return B1.Box:getDimY() * B1.Box:getDimZ() < B2.Box:getDimY() * B2.Box:getDimZ() end else return B2.Tail or B1.Box:getMin():getX() + 20 > B2.Box:getCenter():getX() end end -- se secondo è taglio longitudinale completo o altra lav. lunga, dopo tutte le altre feature non di coda if abs( B2.Box:getDimX() - b3Raw:getDimX()) < 0.2 * b3Raw:getDimX() then return not ( B1.Tail or B2.Box:getMin():getX() + 20 > B1.Box:getCenter():getX()) end -- se primo è foro e l'altro no, lo penalizzo (a patto che il foro non attraversi nessuna feature) if Drill.Identify(B1) and not B1.Dependency and not Drill.Identify(B2) then return ( B1.Box:getCenter():getX() > B2.Box:getMax():getX() + dDrillPenalty) end -- se primo è altro e secondo è foro, lo premio (a patto che il foro non attraversi nessuna feature) if not Drill.Identify(B1) and not B2.Dependency and Drill.Identify(B2) then return ( B1.Box:getMax():getX() + dDrillPenalty > B2.Box:getCenter():getX()) end -- se prima è mortasa coda di rondine sul fianco e secondo taglio longitudinale, la coda di rondine va sempre prima if DtMortise.SideIdentify(B1) and ( LongCut.Identify(B2) or Long2Cut.Identify(B2)) and OverlapsX( B1.Box, B2.Box) then return true end -- se primo è taglio longitudinale e seconda è mortasa coda di rondine sul fianco, il taglio longitudinale va sempre dopo if ( LongCut.Identify(B1) or Long2Cut.Identify(B1)) and DtMortise.SideIdentify(B2) and OverlapsX( B1.Box, B2.Box) then return false end -- se entrambi tenoni e si intersecano, metto prima tenone vero e poi base tenone if ( Tenon.Identify( B1) or DtTenon.Identify( B1)) and ( Tenon.Identify( B2) or DtTenon.Identify( B2)) and B1.Box:getMin():getX() < B2.Box:getMax():getX() + 100 * GEO.EPS_SMALL and B2.Box:getMin():getX() < B1.Box:getMax():getX() + 100 * GEO.EPS_SMALL then return ( ( B1.Prc == 50 or B1.Prc == 55) and B2.Prc == 52) end -- se primo house mortise, secondo mortise e si intersecano, metto prima house mortise if Mortise.Identify( B1) and B1.Prc == 53 and ( Mortise.Identify( B2) or DtMortise.Identify( B2)) and B2.Prc ~= 53 and B1.Box:getMin():getX() < B2.Box:getMax():getX() + 100 * GEO.EPS_SMALL and B2.Box:getMin():getX() < B1.Box:getMax():getX() + 100 * GEO.EPS_SMALL then return true end -- se primo mortise, secondo house mortise e si intersecano, metto prima house mortise if ( Mortise.Identify( B1) or DtMortise.Identify( B1)) and B1.Prc ~= 53 and Mortise.Identify( B2) and B2.Prc == 53 and B1.Box:getMin():getX() < B2.Box:getMax():getX() + 100 * GEO.EPS_SMALL and B2.Box:getMin():getX() < B1.Box:getMax():getX() + 100 * GEO.EPS_SMALL then return false end -- se entrambi fori con posizione praticamente uguale ordino secondo diametro e faccia di inizio (Fcs) if B1.Prc == 40 and B2.Prc == 40 and abs( B1.Box:getCenter():getX() - B2.Box:getCenter():getX()) < dSmallDrillRange then if B1.IsPredrill and not B2.IsPredrill then return true elseif not B1.IsPredrill and B2.IsPredrill then return false elseif abs( B1.Diam - B2.Diam) < 1.0 then if B1.Fcs == B2.Fcs then if abs( B1.Box:getCenter():getX() - B2.Box:getCenter():getX()) < 1.0 then if abs( B1.Box:getCenter():getY() - B2.Box:getCenter():getY()) < 1.0 then if abs( B1.Box:getCenter():getZ() - B2.Box:getCenter():getZ()) < 1.0 then return ( B1.Id < B2.Id) else return ( B1.Box:getCenter():getZ() > B2.Box:getCenter():getZ()) end else return ( B1.Box:getCenter():getY() > B2.Box:getCenter():getY()) end else return ( B1.Box:getCenter():getX() > B2.Box:getCenter():getX()) end else return ( B1.Fcs > B2.Fcs) end else return ( B1.Diam > B2.Diam) end end -- confronto standard if abs( B1.Box:getCenter():getX() - B2.Box:getCenter():getX()) > 0.4 * ( B1.Box:getDimX() + B2.Box:getDimX()) then return B1.Box:getCenter():getX() > B2.Box:getCenter():getX() elseif abs( B1.Box:getCenter():getY() - B2.Box:getCenter():getY()) > 0.2 * ( B1.Box:getDimY() + B2.Box:getDimY()) then return B1.Box:getCenter():getY() > B2.Box:getCenter():getY() elseif abs( B1.Box:getCenter():getZ() - B2.Box:getCenter():getZ()) > 0.1 * ( B1.Box:getDimZ() + B2.Box:getDimZ()) then return B1.Box:getCenter():getZ() > B2.Box:getCenter():getZ() else return ( B1.Id < B2.Id) end end -- test della funzione di ordinamento if EgtGetDebugLevel() >= 3 then EgtOutLog( ' CompareFeatures Test ') local bCompTest = true for i = 1, #vProc do for j = i + 1, #vProc do local bComp1 = CompareFeatures( vProc[i], vProc[j]) local bComp2 = CompareFeatures( vProc[j], vProc[i]) if bComp1 == bComp2 then bCompTest = false EgtOutLog( string.format( ' ProcId : %d vs %d --> ERROR', vProc[i].Id, vProc[j].Id)) end end end if bCompTest then EgtOutLog( ' ALL OK') end end -- eseguo ordinamento table.sort( vProc, CompareFeatures) -- riunisco fori con lo stesso diametro e non troppo lontani local dDrillRange = dSmallDrillRange if BD.GO_FAST == 2 then dDrillRange = 6000 elseif BD.PRESS_ROLLER then dDrillRange = 2000 end for i = 1, #vProc do local ProcI = vProc[i] if ProcI.Prc == 40 and ProcI.Box and not ProcI.Box:isEmpty() then for j = i + 1, #vProc do local ProcJ = vProc[j] if ProcJ.Prc == 40 and ProcJ.Box and not ProcJ.Box:isEmpty() and ProcJ.Head == ProcI.Head and ProcJ.Tail == ProcI.Tail and abs( ProcJ.Diam - ProcI.Diam) < 1.0 and abs( ProcJ.Box:getCenter():getX() - ProcI.Box:getCenter():getX()) < dDrillRange then if j > i + 1 then local ProcK = vProc[i+1] if ProcK.Prc ~= 40 or abs( ProcK.Diam - ProcJ.Diam) > 1.0 then table.insert( vProc, i + 1, table.remove( vProc, j)) end end end end end end -- riunisco fori da fare in doppio local i = 1 while i < #vProc do local ProcI = vProc[i] if ProcI.Prc == 40 then local DouId = EgtGetInfo( ProcI.Id, 'DOU', 'i') if DouId then for j = i + 1, #vProc do if vProc[j].Id == DouId then table.insert( vProc, i, table.remove( vProc, j)) i = i + 1 break end end end end i = i + 1 end -- riunisco marcature, testi e decori non troppo lontani local dMarkRange = 300 for i = 1, #vProc do local ProcI = vProc[i] if ( ProcI.Prc == 60 or ProcI.Prc == 61 or ProcI.Prc == 959) and ProcI.Box and not ProcI.Box:isEmpty() then for j = i + 1, #vProc do local ProcJ = vProc[j] if ( ProcJ.Prc == 60 or ProcJ.Prc == 61 or ProcJ.Prc == 959) and ProcJ.Box and not ProcJ.Box:isEmpty() and ProcJ.Head == ProcI.Head and ProcJ.Tail == ProcI.Tail and abs( ProcJ.Box:getCenter():getX() - ProcI.Box:getCenter():getX()) < dMarkRange then if j > i + 1 then table.insert( vProc, i + 1, table.remove( vProc, j)) end break end end end end -- ordino BlockHaus HalfLap vicini (davanti, sotto, dietro, sopra) local dBHHLRange = 100 for i = 1, #vProc do local ProcI = vProc[i] if ProcI.Prc == 37 and ProcI.Box and not ProcI.Box:isEmpty() then for j = i + 1, #vProc do local ProcJ = vProc[j] if ProcJ.Prc == 37 and ProcJ.Box and not ProcJ.Box:isEmpty() and abs( ProcI.Box:getCenter():getX() - ProcJ.Box:getCenter():getX()) < dBHHLRange then if ProcI.HeadDir then if ProcJ.vtN:getY() < -0.5 then table.insert( vProc, i, table.remove( vProc, j)) break elseif ProcJ.vtN:getZ() < -0.5 and ProcI.vtN:getY() > -0.5 then table.insert( vProc, i, table.remove( vProc, j)) ProcI = vProc[i] elseif ProcJ.vtN:getY() > 0.5 and ProcI.vtN:getY() > -0.5 and ProcI.vtN:getZ() > -0.5 then table.insert( vProc, i, table.remove( vProc, j)) ProcI = vProc[i] end else if ProcJ.vtN:getY() > 0.5 then table.insert( vProc, i, table.remove( vProc, j)) break elseif ProcJ.vtN:getZ() < -0.5 and ProcI.vtN:getY() < 0.5 then table.insert( vProc, i, table.remove( vProc, j)) ProcI = vProc[i] elseif ProcJ.vtN:getY() < -0.5 and ProcI.vtN:getY() < 0.5 and ProcI.vtN:getZ() > -0.5 then table.insert( vProc, i, table.remove( vProc, j)) ProcI = vProc[i] end end end end end end ReorderTruncatingCuts( vProc, nPartId) -- si riverificano feature con dipendenze ReorderFeatureWithDependency( vProc) end ------------------------------------------------------------------------------------------------------------- local function ClassifyFeatures( vProc, b3Raw, Stats) local bAllOk = true local bSomeDown = false local bSomeSide = false local bSplitRot = false local nHeading local nSplitting local vMachineBeforeIntersectingDrillingsId = {} for i = 1, #vProc do local Proc = vProc[i] local bOk = true local bDown = false local bSide = false local bDownSideOnHeadOk = false if Proc.MachineBeforeIntersectingDrillings then table.insert( vMachineBeforeIntersectingDrillingsId, Proc.Id) end -- se senza geometria (già disabilitato) if Proc.Flg == 0 and not Proc.Double then bOk = false -- se intestatura elseif Hcut.Identify( Proc) then nHeading = i -- se separazione elseif Split.Identify( Proc) then nSplitting = i -- se taglio elseif Cut.Identify( Proc) then bOk, bDown = Cut.Classify( Proc, b3Raw) -- se doppio taglio elseif DoubleCut.Identify( Proc) then bOk, bDown = DoubleCut.Classify( Proc, b3Raw) -- se taglio longitudinale elseif LongCut.Identify( Proc) then bOk, bDown = LongCut.Classify( Proc) -- se doppio taglio longitudinale elseif Long2Cut.Identify( Proc) then -- se due facce longitudinali, classifico doppio taglio longitudinale if Long2Cut.GetLongFacesCount( Proc) == 2 then bOk, bDown = Long2Cut.Classify( Proc) -- altrimenti eseguo singolo taglio longitudinale else bOk, bDown = LongCut.Classify( Proc) end -- se taglio con lama elseif SawCut.Identify( Proc) then bOk, bDown = SawCut.Classify( Proc) -- se mezzo-legno di testa elseif RidgeLap.Identify( Proc) then bOk, bDown = RidgeLap.Classify( Proc, b3Raw) -- se scanalatura, scanalatura frontale, tacca, tacca cantonale, mezzo-legno, scanalatura-battuta, -- mezzolegno tipo chalet-tavola di chiusura, rivestimento, mezzolegno chalet, tasca, taglio triangolato elseif LapJoint.Identify( Proc) then bOk, bDown = LapJoint.Classify( Proc, b3Raw) -- se foratura elseif Drill.Identify( Proc) then bOk, bDown, bSide = Drill.Classify( Proc, b3Raw) bDownSideOnHeadOk = true -- se tenone elseif Tenon.Identify( Proc) then bOk, bDown = Tenon.Classify( Proc, b3Raw) -- se giunzione francese elseif FrenchRidgeLap.Identify( Proc) then bOk, bDown = FrenchRidgeLap.Classify( Proc) -- se block house front elseif BlockHausFront.Identify( Proc) then bOk, bDown = BlockHausFront.Classify( Proc) -- se mortasa (anche frontale) elseif Mortise.Identify( Proc) then bOk, bDown = Mortise.Classify( Proc) -- se tenone a coda di rondine elseif DtTenon.Identify( Proc) then bOk, bDown = DtTenon.Classify( Proc, b3Raw) -- se mortasa a coda di rondine (anche frontale) elseif DtMortise.Identify( Proc) then bOk, bDown = DtMortise.Classify( Proc) -- se marcatura elseif Mark.Identify( Proc) then bOk, bDown = Mark.Classify( Proc) -- se testo elseif Text.Identify( Proc) then bOk, bDown = Text.Classify( Proc) -- se giunto Gerber elseif ScarfJoint.Identify( Proc) then bOk, bDown = ScarfJoint.Classify( Proc) -- se giunto Gerber elseif Scarf.Identify( Proc) then bOk, bDown = Scarf.Classify( Proc) -- se giunto a gradino elseif StepJoint.Identify( Proc) then bOk, bDown = StepJoint.Classify( Proc) -- se tacca a gradino elseif StJoNotch.Identify( Proc) then bOk, bDown = StJoNotch.Classify( Proc) -- se arco elseif RoundArch.Identify( Proc) then bOk, bDown = RoundArch.Classify( Proc) -- se incastro tirolo elseif TyroleanDovetail.Identify( Proc) then bOk, bDown = TyroleanDovetail.Classify( Proc, b3Raw) -- se giunto coda di rondine elseif Dovetail.Identify( Proc) then bOk, bDown = Dovetail.Classify( Proc, b3Raw) -- se profilo front elseif ProfFront.Identify( Proc) then bOk, bDown, bSide = ProfFront.Classify( Proc, b3Raw) -- se profilo concavo elseif ProfConcave.Identify( Proc) then bOk, bDown, bSide = ProfConcave.Classify( Proc, b3Raw) -- se profilo convesso elseif ProfConvex.Identify( Proc) then bOk, bDown, bSide = ProfConvex.Classify( Proc, b3Raw) -- se profilo caudato elseif ProfCamb.Identify( Proc) then bOk, bDown, bSide = ProfCamb.Classify( Proc, b3Raw) -- se profilo head elseif ProfHead.Identify( Proc) then bOk, bDown, bSide = ProfHead.Classify( Proc, b3Raw) -- se contorno libero elseif FreeContour.Identify( Proc) then bOk, bDown, bSide, bDownSideOnHeadOk = FreeContour.Classify( Proc, b3Raw) -- se decorazione elseif Decor.Identify( Proc) then bOk, bDown = Decor.Classify( Proc) -- se Variant elseif Variant.Identify( Proc) then bOk, bDown = Variant.Classify( Proc, b3Raw) end -- assegno risultato if bOk then -- non ammessa feature di testa da lavorare ribaltata o ruotata (lettura laser) if Proc.Head and ( bDown or bSide) and not bDownSideOnHeadOk then Proc.Flg = 0 Proc.Down = true bAllOk = false table.insert( Stats, {Err = 1, Msg='Error : impossible to machine by orientation', CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id}) -- gestione feature di coda da lavorare ribaltata elseif Proc.Tail and bDown then Proc.Down = true bSomeDown = true bSplitRot = true -- gestione feature di coda da lavorare ruotata elseif Proc.Tail and bSide then Proc.Side = true bSomeSide = true bSplitRot = true -- caso normale else Proc.Down = bDown Proc.Side = bSide if bDown then bSomeDown = true end if bSide then bSomeSide = true end end elseif Proc.Flg == 0 then bAllOk = false Proc.ErrMsg = 'Error : out of the part' table.insert( Stats, {Err = 1, Msg=Proc.ErrMsg, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id}) else Proc.Flg = 0 bAllOk = false if not Proc.ErrMsg then Proc.ErrMsg = 'Error : impossible to machine' end table.insert( Stats, {Err = 1, Msg=Proc.ErrMsg, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id}) end end -- se necessario ribaltamento, assegno intestatura alla fase ribaltata if bSomeDown and nHeading then vProc[nHeading].Down = true -- se altrimenti necessaria rotazione (senza ribaltamento), assegno intestatura alla fase ribaltata (creata ad hoc) elseif bSomeSide and nHeading then vProc[nHeading].Down = true bSomeDown = true end -- se necessaria separazione del ribaltato o ruotato, la assegno sempre alla fase ribaltata if bSplitRot and nSplitting then vProc[nSplitting].Down = true bSomeDown = true end -- si cerca di riclassificare le feature che dipendono da altre (in caso siano su rotazioni diverse) for i = 1, #vProc do local Proc = vProc[i] -- FORATURA if Drill.Identify( Proc) and Proc.Dependency then if Proc.Dependency.ExecBefore then if Proc.Dependency.ExecBefore.Down then local bMachiningSideChanged = Drill.Classify( Proc, b3Raw, 'DOWN') end end end end return bAllOk, bSomeDown, bSomeSide, bSplitRot end ------------------------------------------------------------------------------------------------------------- local function AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, bNeedHCut, b3Raw, nOrd, sDownOrSideOrStd, bPreMove, vtMove, dCurrOvmT) local bOk = true local sErr = '' local nNewPhase = -1 local AddedIds EgtOutLog( ' * Process ' .. tostring( Proc.Id) .. ' *', 1) -- se intestatura ( 1-340-X ) if Hcut.Identify( Proc) then -- esecuzione taglio di testa bOk, sErr = Hcut.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, bNeedHCut) -- se separazione ( 2-350-X ) elseif Split.Identify( Proc) then -- esecuzione separazione o eliminazione grezzo residuo bOk, sErr, nNewPhase = Split.Make( Proc, nPhase, nRawId, nPartId, nOrd, sDownOrSideOrStd, bPreMove, vtMove, dCurrOvmT) -- se taglio ( 1/2-010-X) elseif Cut.Identify( Proc) then -- esecuzione taglio bOk, sErr = Cut.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, nil, nil, nil, nil, nil, dCurrOvmT) -- se doppio taglio ( 1/2-011-X) elseif DoubleCut.Identify( Proc) then -- esecuzione doppio taglio bOk, sErr = DoubleCut.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se taglio longitudinale ( 0/3/4-010-X) elseif LongCut.Identify( Proc) then -- esecuzione taglio longitudinale bOk, sErr = LongCut.Make( Proc, nPhase, nRawId, nPartId) -- se doppio taglio longitudinale ( 0-012-X) elseif Long2Cut.Identify( Proc) then -- se due facce longitudinali, eseguo doppio taglio longitudinale if Long2Cut.GetLongFacesCount( Proc) == 2 then bOk, sErr, _, AddedIds = Long2Cut.Make( Proc, nPhase, nRawId, nPartId) -- altrimenti eseguo singolo taglio longitudinale else bOk, sErr = LongCut.Make( Proc, nPhase, nRawId, nPartId) end -- se taglio con lama ( 0/3/4-013-X) elseif SawCut.Identify( Proc) then -- esecuzione taglio bOk, sErr = SawCut.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se mezzo-legno di testa ( 1/2-030-X) elseif RidgeLap.Identify( Proc) then -- esecuzione mezzo-legno di testa bOk, sErr = RidgeLap.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se fessura ( 3/4-016-X) o se fessura frontale ( 3/4-017-X) o se tacca ( 3/4-020-X) o se tacca cantonale ( 3/4-025-X) -- o se mezzo-legno ( 3/4-030-X) o se scanalatura/battuta ( 3/4-032-X) o se mezzo legno tipo chalet/tavola di chiusura ( 3/4-033-X) -- o se rivestimento ( 3/4-034-X) o se mezzolegno chalet ( 4-037-X) o se tasca ( 4-039-X) o se taglio triangolato ( 4-120-X) elseif LapJoint.Identify( Proc) then -- esecuzione mezzo-legno o scanalatura bOk, sErr, _, AddedIds = LapJoint.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se smusso ( 3/4-036-X) elseif Chamfer.Identify( Proc) then -- esecuzione smusso bOk, sErr = Chamfer.Make( Proc, nPhase, nRawId, nPartId) -- se foratura ( 3/4-040-X) elseif Drill.Identify( Proc) then -- esecuzione foratura bOk, sErr = Drill.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se giunzione francese ( 1/2-035-X) elseif FrenchRidgeLap.Identify( Proc) then -- esecuzione giunzione francese bOk, sErr = FrenchRidgeLap.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se block house front ( 3/4-038-X) elseif BlockHausFront.Identify( Proc) then -- esecuzione giunzione francese bOk, sErr = BlockHausFront.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se tenone ( 1/2-050-X) elseif Tenon.Identify( Proc) then -- esecuzione tenone bOk, sErr = Tenon.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se mortasa ( 3/4-050-X) anche frontale ( 3/4-051-X) elseif Mortise.Identify( Proc) then -- esecuzione mortasa bOk, sErr = Mortise.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se tenone a coda di rondine ( 1/2-055-X) elseif DtTenon.Identify( Proc) then -- esecuzione tenone bOk, sErr = DtTenon.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se mortasa a coda di rondine ( 3/4-055-X) anche frontale ( 3/4-056-X) elseif DtMortise.Identify( Proc) then -- esecuzione mortasa bOk, sErr = DtMortise.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se marcatura ( 3/4-060-X) elseif Mark.Identify( Proc) then -- esecuzione marcatura bOk, sErr = Mark.Make( Proc, nPhase, nRawId, nPartId) -- se testo ( 4-061-X) elseif Text.Identify( Proc) then -- esecuzione testo bOk, sErr = Text.Make( Proc, nPhase, nRawId, nPartId) -- se giunto Gerber ( 1/2-071-X) elseif ScarfJoint.Identify( Proc) then -- esecuzione giunto Gerber bOk, sErr = ScarfJoint.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se giunto Gerber ( 1/2-070-X) elseif Scarf.Identify( Proc) then -- esecuzione giunto Gerber bOk, sErr = Scarf.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se giunto a gradino ( 1/2-080-X) elseif StepJoint.Identify( Proc) then -- esecuzione giunto a gradino bOk, sErr = StepJoint.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se tacca a gradino ( 3/4-080-X) elseif StJoNotch.Identify( Proc) then -- esecuzione tacca a gradino bOk, sErr = StJoNotch.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se profilo Front ( 3/4-100-X) elseif ProfFront.Identify( Proc) then -- esecuzione profilo bOk, sErr = ProfFront.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se profilo concavo ( 3/4-101-X) elseif ProfConcave.Identify( Proc) then -- esecuzione profilo bOk, sErr = ProfConcave.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se profilo convesso ( 3/4-102-X) elseif ProfConvex.Identify( Proc) then -- esecuzione profilo bOk, sErr = ProfConvex.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se profilo caudato ( 3/4-103-X) elseif ProfCamb.Identify( Proc) then -- esecuzione profilo bOk, sErr = ProfCamb.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se arco ( 4-104-X) elseif RoundArch.Identify( Proc) then -- esecuzione arco bOk, sErr = RoundArch.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se profilo Head ( 3/4-106-X) elseif ProfHead.Identify( Proc) then -- esecuzione profilo bOk, sErr = ProfHead.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se incastro tirolo ( 1/2/3/4-136-X) elseif TyroleanDovetail.Identify( Proc) then bOk, sErr = TyroleanDovetail.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se giunto coda di rondine ( 1/2/3/4-138-X) elseif Dovetail.Identify( Proc) then bOk, sErr = Dovetail.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH, dCurrOvmT) -- se contorno libero ( 0/3/4-250-X) elseif FreeContour.Identify( Proc) then -- esecuzione contorno bOk, sErr = FreeContour.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH) -- se decorazione ( 0/3/4-959-X) elseif Decor.Identify( Proc) then -- esecuzione decorazione bOk, sErr = Decor.Make( Proc, nPhase, nRawId, nPartId) -- se Variant elseif Variant.Identify( Proc) then -- esecuzione variante custom bOk, sErr = Variant.Make( Proc, nPhase, nRawId, nPartId) -- altrimenti feature sconosciuta else sErr = 'Error on process ' .. tostring( Proc.Id) .. ' unknown type (' .. tonumber( Proc.Grp) .. '-' .. tonumber( Proc.Prc) .. ')' EgtOutLog( sErr) bOk = false end return bOk, sErr, ( nNewPhase or -1), AddedIds end ------------------------------------------------------------------------------------------------------------- local function VerifyNeedForHeadCut( vProc, bSomeDown, bSomeSide) -- verifico se necessaria la rotazione di 90 gradi if not bSomeSide then return false end -- verifico se viene dopo un pezzo diviso quando ruotato (quindi con rimanenza scaricata sul carico) local nPrevPhase = EgtGetCurrPhase() - 1 local nPrevDispId = EgtGetPhaseDisposition( nPrevPhase) or GDB_ID.NULL local nPrevType = EgtGetInfo( nPrevDispId, 'TYPE') if nPrevType ~= 'MID2' and nPrevType ~= 'END2' then return false end -- verifico se c'è una sola lavorazione ribaltata (quindi è il taglio di testa) local nDownCnt = 0 for i = 1, #vProc do if vProc[i].Down then nDownCnt = nDownCnt + 1 end end return ( nDownCnt == 1) end ------------------------------------------------------------------------------------------------------------- local function SetCutsOnFrontMortises( vProc) -- ciclo sulle feature for i = 1, #vProc do if vProc[i].Fct > 0 and Cut.Identify( vProc[i]) then for j = 1, #vProc do if vProc[j].Fct > 0 and Mortise.FrontIdentify( vProc[j]) then -- se esiste intersezione tra le due features if vProc[i].Box:getMin():getX() < vProc[j].Box:getMax():getX() + 100 * GEO.EPS_SMALL and vProc[j].Box:getMin():getX() < vProc[i].Box:getMax():getX() + 100 * GEO.EPS_SMALL then -- recupero il piano del taglio local ptC1, vtN1 = Cut.GetCutPlane( vProc[i]) -- recupero il piano frontale della mortasa local ptC2, vtN2 = Mortise.GetCutPlane( vProc[j]) -- verifico se i piani coincidono local bSamePlane = ( ptC1 and vtN1 and ptC2 and vtN2 and AreSameVectorApprox( vtN1, vtN2) and ( ptC2 - ptC1) * vtN1 < 1.0) if bSamePlane then vProc[i].CutFront = vProc[j].Id end -- log local sMsg = string.format( 'Cut %d meet Mortise %d', vProc[i].Id, vProc[j].Id) .. EgtIf( bSamePlane, ' with same plane', '') EgtOutLog( sMsg, 3) end elseif vProc[j].Fct > 0 and DtMortise.FrontIdentify( vProc[j]) then -- se esiste intersezione tra le due features if vProc[i].Box:getMin():getX() < vProc[j].Box:getMax():getX() + 100 * GEO.EPS_SMALL and vProc[j].Box:getMin():getX() < vProc[i].Box:getMax():getX() + 100 * GEO.EPS_SMALL then -- recupero il piano del taglio local ptC1, vtN1 = Cut.GetCutPlane( vProc[i]) -- recupero il piano frontale della mortasa local ptC2, vtN2 = DtMortise.GetCutPlane( vProc[j]) -- verifico se i piani coincidono local bSamePlane = ( ptC1 and vtN1 and ptC2 and vtN2 and AreSameVectorApprox( vtN1, vtN2) and ( ptC2 - ptC1) * vtN1 < 1.0) if bSamePlane then vProc[i].CutFront = vProc[j].Id end -- log local sMsg = string.format( 'Cut %d meet DtMortise %d', vProc[i].Id, vProc[j].Id) .. EgtIf( bSamePlane, ' with same plane', '') EgtOutLog( sMsg, 3) end end end end end end ------------------------------------------------------------------------------------------------------------- local function MoveDrillsOnTenon( vProc) -- se non richiesto spostamento fori su tenone, esco if not BD.OFFSET_DRILL_TENON or abs( BD.OFFSET_DRILL_TENON) < 0.1 then return end -- ciclo sulle feature for i = 1, #vProc do if vProc[i].Flg ~= 0 and Tenon.Identify( vProc[i]) then for j = 1, #vProc do if Drill.Identify( vProc[j]) then -- se esiste intersezione tra tenone e foro if vProc[i].Box:getMin():getX() < vProc[j].Box:getMax():getX() + 100 * GEO.EPS_SMALL and vProc[j].Box:getMin():getX() < vProc[i].Box:getMax():getX() + 100 * GEO.EPS_SMALL then -- verifico se foro già spostato if not EgtExistsInfo( vProc[j].Id, 'MOV') then -- recupero curva ausiliaria del foro local AuxDriId = EgtGetInfo( vProc[j].Id, 'AUXID', 'i') AuxDriId = EgtIf( AuxDriId, AuxDriId + vProc[j].Id, nil) -- recupero versore normale del tenone local AuxTenId = EgtGetInfo( vProc[i].Id, 'AUXID', 'i') AuxTenId = EgtIf( AuxTenId, AuxTenId + vProc[i].Id, GDB_ID.NULL) local vtExtr = EgtCurveExtrusion( AuxTenId, GDB_RT.GLOB) -- se tutto ok, eseguo spostamento if AuxDriId and vtExtr then local vtMove = -vtExtr * BD.OFFSET_DRILL_TENON EgtMove( AuxDriId, vtMove, GDB_RT.GLOB) EgtSetInfo( vProc[j].Id, 'MOV', vtMove) end end end end end end end end ------------------------------------------------------------------------------------------------------------- -- Controlla se la feature ProcMirror è la specchiata di Proc, per feature di tipo tasca o simile local function CheckMirrorPocket( Proc, ProcMirror, b3Raw, AuxId) -- recupero i dati geometrici della curva Proc local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local ptBC = EgtGP( AuxId, GDB_RT.GLOB) local rfDtMrt = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 0, GDB_RT.GLOB) local b3DtMrt = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfDtMrt) local b3Proc = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) -- recupero e verifico l'entità curva ProcMirror local AuxIdMirror = EgtGetInfo( ProcMirror.Id, 'AUXID', 'i') if AuxIdMirror then AuxIdMirror = AuxIdMirror + ProcMirror.Id end if not AuxIdMirror or ( EgtGetType( AuxIdMirror) & GDB_FY.GEO_CURVE) == 0 then return false end -- se Mortise, se curva di contorno aperta la rendo chiusa if Mortise.SideIdentify( ProcMirror) then BL.ConvertToClosedCurve( ProcMirror, AuxIdMirror) end -- recupero i dati geometrici della curva ProcMirror local vtExtrMirror = EgtCurveExtrusion( AuxIdMirror, GDB_RT.GLOB) local ptBCMirror = EgtGP( AuxIdMirror, GDB_RT.GLOB) local b3DtMrtMirror = EgtGetBBoxRef( ProcMirror.Id, GDB_BB.STANDARD, rfDtMrt) local b3ProcMirror = EgtGetBBoxGlob( ProcMirror.Id, GDB_BB.STANDARD) -- verifico se le mortase sono specchiate : -- devono avere estrusioni opposte if not AreOppositeVectorApprox( vtExtr, vtExtrMirror) then return false end -- se di tipo Dt, devono avere l'asse allineato if DtMortise.SideIdentify( Proc) or DtMortise.SideIdentify( ProcMirror) then local vtAx = EgtEV( AuxId, GDB_RT.GLOB) - EgtSV( AuxId, GDB_RT.GLOB) local vtAxMirror = EgtEV( AuxIdMirror, GDB_RT.GLOB) - EgtSV( AuxIdMirror, GDB_RT.GLOB) if not AreSameVectorApprox( vtAx, vtAxMirror) then return false end end -- devono avere il centro allineato, essere equidistanti dalla mezzeria trave e non essere troppo vicine local vtDisplacement = ptBC - ptBCMirror local ptCenRaw = b3Raw:getCenter() if AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) then local dYMinDistance = max( b3Proc:getMin():getY(), b3ProcMirror:getMin():getY()) - min( b3Proc:getMax():getY(), b3ProcMirror:getMax():getY()) if not ( abs( vtDisplacement:getX()) < 500 * GEO.EPS_SMALL and abs( vtDisplacement:getZ()) < 500 * GEO.EPS_SMALL and ( abs( ptBC:getY() - ptCenRaw:getY()) - abs( ptBCMirror:getY() - ptCenRaw:getY())) < 500 * GEO.EPS_SMALL and dYMinDistance > MIRROR_POCKETS_MIN_DISTANCE + 10 * GEO.EPS_SMALL) then return false end elseif AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then local dZMinDistance = max( b3Proc:getMin():getZ(), b3ProcMirror:getMin():getZ()) - min( b3Proc:getMax():getZ(), b3ProcMirror:getMax():getZ()) if not ( abs( vtDisplacement:getX()) < 500 * GEO.EPS_SMALL and abs( vtDisplacement:getY()) < 500 * GEO.EPS_SMALL and ( abs( ptBC:getZ() - ptCenRaw:getZ()) - abs( ptBCMirror:getZ() - ptCenRaw:getZ())) < 500 * GEO.EPS_SMALL and dZMinDistance > MIRROR_POCKETS_MIN_DISTANCE + 10 * GEO.EPS_SMALL) then return false end else return false end -- devono avere box con le stesse dimensioni if not ( abs( b3DtMrt:getDimX() - b3DtMrtMirror:getDimX()) < 500 * GEO.EPS_SMALL and abs( b3DtMrt:getDimY() - b3DtMrtMirror:getDimY()) < 500 * GEO.EPS_SMALL and abs( b3DtMrt:getDimZ() - b3DtMrtMirror:getDimZ()) < 500 * GEO.EPS_SMALL) then return false end return true end ------------------------------------------------------------------------------------------------------------- -- Verifica se Proc (mortasa) è lavorabile in doppio e nel caso ne imposta i dati. local function VerifyMortiseMirrored( Proc, vProc, b3Raw) -- 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 = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end -- recupero versore estrusione della curva supplementare local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT) -- Se curva di contorno aperta la converto in curva chiusa BL.ConvertToClosedCurve( Proc, AuxId) -- recupero i dati della faccia di fondo local frMor, dL, dW = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 0, GDB_ID.ROOT) -- determino larghezza della mortasa if dL < dW then dL, dW = dW, dL end local ptC = ORIG() local vtN = V_NULL() if frMor then ptC = frMor:getOrigin() vtN = frMor:getVersZ() end -- se mortasa passante esco local bOpenBtm = not AreSameVectorApprox( vtExtr, vtN) if bOpenBtm then return end -- determino altezza della mortasa local b3Mor = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frMor) local dMorH = b3Mor:getDimZ() -- elevazione del punto centrale local _, dCenElev = BL.GetPointDirDepth( nPartId, ptC, vtN) dMorH = max( dMorH, dCenElev or 0) -- recupero lavorazione adatta local sPockType = 'Mortise' local sPocketing if Proc.Prc ~= 53 then sPocketing = Mortise.VerifyMortiseOrPocket( Proc, dW, dMorH, nil, sPockType, false, true) end if not sPocketing then sPockType = 'Pocket' sPocketing = Mortise.VerifyMortiseOrPocket( Proc, dW, dMorH, nil, sPockType, false, true) end if not sPocketing or not EgtMdbSetCurrMachining( sPocketing) then return end -- recupero il suo utensile if not EgtTdbSetCurrTool( EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) or '') then return end -- recupero eventuale utensile in doppio e suo diametro local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') if not sToolDoubleName or not EgtTdbSetCurrTool( sToolDoubleName) or not EgtFindToolInCurrSetup( sToolDoubleName) then return end local dToolDoubleDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM, 'd') -- verifico se possibile in doppio (diametro utensile e direzione feature) if dToolDoubleDiam < dW + GEO.EPS_SMALL and ( AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) or AreSameVectorApprox( vtExtr, Z_AX())) then for i = 1, #vProc do local ProcMirror = vProc[i] if Mortise.SideIdentify( ProcMirror) and ProcMirror.Id ~= Proc.Id and ProcMirror.Flg ~= 0 then if CheckMirrorPocket( Proc, ProcMirror, b3Raw, AuxId) then if ( not BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Y_AX())) or ( BD.DOWN_HEAD and AreOppositeVectorApprox( vtExtr, Y_AX())) then Proc.Double = 2 Proc.MirrorId = ProcMirror.Id Proc.MirrorCutId = ProcMirror.CutId Proc.MirrorTaskId = ProcMirror.TaskId ProcMirror.Flg = 0 ProcMirror.Double = 0 elseif BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Z_AX()) then Proc.Double = 3 Proc.MirrorId = ProcMirror.Id Proc.MirrorCutId = ProcMirror.CutId Proc.MirrorTaskId = ProcMirror.TaskId ProcMirror.Flg = 0 ProcMirror.Double = 0 end break end end end end end ------------------------------------------------------------------------------------------------------------- -- Verifica se Proc (mortasa a coda di rondine) è lavorabile in doppio e nel caso ne imposta i dati. local function VerifyDtMortiseMirrored( Proc, vProc, b3Raw) -- verifico se con tasca local bPocket = ( EgtGetInfo( Proc.Id, 'P05', 'i') == 1) if bPocket then return end -- recupero e verifico l'entità curva ausiliaria 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 return end local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- 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 -- recupero lavorazione adatta local dMaxDiam = 2 * dMinRad local sMilling = ML.FindMilling( 'DtMortise', nil, nil, dMaxDiam, nil, true, false, true) if not sMilling or not EgtMdbSetCurrMachining( sMilling) then return end -- recupero il suo utensile if not EgtTdbSetCurrTool( EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) or '') then return end -- recupero eventuale utensile in doppio e suo diametro local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') if not sToolDoubleName or not EgtTdbSetCurrTool( sToolDoubleName) or not EgtFindToolInCurrSetup( sToolDoubleName) then return end local dToolDoubleDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM, 'd') -- verifico se possibile in doppio (diametro utensile e direzione feature) if dToolDoubleDiam < dMaxDiam + GEO.EPS_SMALL and ( AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) or AreSameVectorApprox( vtExtr, Z_AX())) then for i = 1, #vProc do local ProcMirror = vProc[i] if DtMortise.SideIdentify( ProcMirror) and ProcMirror.Id ~= Proc.Id and ProcMirror.Flg ~= 0 then if CheckMirrorPocket( Proc, ProcMirror, b3Raw, AuxId) then if ( not BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Y_AX())) or ( BD.DOWN_HEAD and AreOppositeVectorApprox( vtExtr, Y_AX())) then Proc.Double = 2 Proc.MirrorId = ProcMirror.Id Proc.MirrorCutId = ProcMirror.CutId Proc.MirrorTaskId = ProcMirror.TaskId ProcMirror.Flg = 0 ProcMirror.Double = 0 elseif BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Z_AX()) then Proc.Double = 3 Proc.MirrorId = ProcMirror.Id Proc.MirrorCutId = ProcMirror.CutId Proc.MirrorTaskId = ProcMirror.TaskId ProcMirror.Flg = 0 ProcMirror.Double = 0 end break end end end end end ------------------------------------------------------------------------------------------------------------- -- Disabilita la foratura dall'altra parte dello stesso foro local function DisableOtherDrilling( Proc, vProc) local ProcMirror for i = 1, #vProc do if vProc[i].Id == Proc.Id and not vProc[i].Double then ProcMirror = vProc[i] break end end if ProcMirror then ProcMirror.Flg = 0 ProcMirror.Double = 0 end end ------------------------------------------------------------------------------------------------------------- -- Verifica se Proc (foratura) è lavorabile in doppio e nel caso ne restituisce la direzione di specchiatura. local function VerifyDrillMirrored( Proc, vProc, b3Raw) -- 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 end -- verifico se foratura splittata oppure da specchiare local bIsDrillingOkForMirror = abs( Proc.Flg) == 2 or ( Proc.Mirror ~= nil) if not bIsDrillingOkForMirror then return end -- recupero direzione e dimensioni del foro local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local dDiam = 2 * EgtArcRadius( AuxId) local dLen = abs( EgtCurveThickness( AuxId)) local dMachiningDepth = EgtIf( abs( Proc.Flg) == 2, dLen / 2 + BD.DRILL_OVERLAP, dLen) -- recupero lavorazione adatta local sDrilling, sType, dMaxDepth = ML.FindDrilling( dDiam, dMachiningDepth, true, false, true) if not sDrilling then sDrilling, sType, dMaxDepth = ML.FindDrilling( dDiam, 0, true, false, true) dMachiningDepth = dMaxDepth or dMachiningDepth end if not sDrilling or not EgtMdbSetCurrMachining( sDrilling) then return end local dDrillingStep = EgtMdbGetCurrMachiningParam( MCH_MP.STEP) -- recupero il suo utensile if not EgtTdbSetCurrTool( EgtMdbGetCurrMachiningParam( MCH_MP.TOOL) or '') then return end -- recupero diametro utensile e lunghezza della parte inclinata della punta local dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM, 'd') local dToolTipLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) - EgtTdbGetCurrToolParam( MCH_TP.LEN) -- recupero eventuale utensile in doppio, suo diametro e massima lavorazione local sToolDoubleName = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'DOUBLE', 's') if not sToolDoubleName or not EgtTdbSetCurrTool( sToolDoubleName) or not EgtFindToolInCurrSetup( sToolDoubleName) then return end local dToolDoubleDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM, 'd') local dToolDoubleMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) dMachiningDepth = min( dMachiningDepth, dToolDoubleMaxDepth) -- recupero la lunghezza della parte inclinata della punta local dToolDoubleTipLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) - EgtTdbGetCurrToolParam( MCH_TP.LEN) -- se foratura splittata, verifico che la distanza minima tra le due punte sia rispettata local dTipDistance = 2 * dDrillingStep - dToolTipLength - dToolDoubleTipLength if abs( Proc.Flg) == 2 and not ( ( dTipDistance - MIRROR_DRILLINGS_MIN_DISTANCE) > 10 * GEO.EPS_SMALL) then EgtOutLog( 'Double drilling skipped, tip distance too small ( ' .. dTipDistance .. ' mm) ') return end -- verifico se in doppio if ( abs( dToolDiam - dToolDoubleDiam) < 10 * GEO.EPS_SMALL) then if Proc.Fce ~= 0 or Proc.Mirror then if Proc.Flg == -2 then vtExtr = -vtExtr end local ProcToDisable = EgtIf( abs( Proc.Flg) == 2, Proc, Proc.Mirror) if ( not BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Y_AX())) or ( BD.DOWN_HEAD and AreOppositeVectorApprox( vtExtr, Y_AX())) then Proc.Double = 2 Proc.MachDepthDouble = dMachiningDepth Proc.MirrorId = ProcToDisable.Id Proc.MirrorCutId = ProcToDisable.CutId Proc.MirrorTaskId = ProcToDisable.TaskId DisableOtherDrilling( ProcToDisable, vProc) elseif BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Z_AX()) then Proc.Double = 3 Proc.MachDepthDouble = dMachiningDepth Proc.MirrorId = ProcToDisable.Id Proc.MirrorCutId = ProcToDisable.CutId Proc.MirrorTaskId = ProcToDisable.TaskId DisableOtherDrilling( ProcToDisable, vProc) end end end end ------------------------------------------------------------------------------------------------------------- -- Cerca in vProc la presenza di feature da lavorare in doppio. Se le trova scrive in Proc la direzione di specchiatura e l'utensile da utilizzare. local function SetMirroredFeatures( vProc, b3Raw) for i = 1, #vProc do local Proc = vProc[i] if Proc.Flg ~= 0 then -- Proc.Double -> 0: nessuna specchiatura, 1: specchiatura X, 2: specchiatura Y, 3: specchiatura Z -- Proc.MirrorId -> Id della feature mirrorata if DtMortise.SideIdentify( Proc) and BD.DOUBLE_HEAD_DOVETAIL then VerifyDtMortiseMirrored( Proc, vProc, b3Raw) elseif Mortise.SideIdentify( Proc) and BD.DOUBLE_HEAD_MORTISE then VerifyMortiseMirrored( Proc, vProc, b3Raw) elseif Drill.Identify( Proc) and BD.DOUBLE_HEAD_DRILLING then VerifyDrillMirrored( Proc, vProc, b3Raw) end end end end ------------------------------------------------------------------------------------------------------------- -- verifica se ci sono forature da lavorare dopo tagli di testa o coda e nel caso le classifica come Head o Tail e gli assegna l'Id della rispettiva feature di taglio local function SetDrillingsToMachineAfterHeadOrTailCut( vProc, vMachineBeforeIntersectingDrillings) for i = 1, #vProc do if Drill.Identify( vProc[i]) then -- recupero e verifico l'entità foro local AuxId = EgtGetInfo( vProc[i].Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + vProc[i].Id end if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then return false end -- recupero il vettore estrusione local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local bOpen = ( vProc[i].Fcs ~= 0 and vProc[i].Fce ~= 0) local ptCen = EgtCP( AuxId, GDB_RT.GLOB) local vDistHead, vDistTail -- check intersezione con feature di testa if vMachineBeforeIntersectingDrillings.Head.Id then -- verifico che ci sia intersezione tra la feature foro e la feature taglio di testa local bIntersectionWithHead = vMachineBeforeIntersectingDrillings.Head.Box and vProc[i].Box:getMin():getX() < vMachineBeforeIntersectingDrillings.Head.Box:getMax():getX() + 100 * GEO.EPS_SMALL and vMachineBeforeIntersectingDrillings.Head.Box:getMin():getX() < vProc[i].Box:getMax():getX() + 100 * GEO.EPS_SMALL -- verifico che ci sia intersezione tra la direzione di estrusione e la faccia della feature taglio di testa if bIntersectionWithHead then _, _, vDistHead = EgtLineSurfTmInters( ptCen, -vtExtr, vMachineBeforeIntersectingDrillings.Head.Id, GDB_RT.GLOB) end end -- check intersezione con feature di coda if vMachineBeforeIntersectingDrillings.Tail.Id then -- verifico che ci sia intersezione tra la feature foro e la feature taglio di coda local bIntersectionWithTail = vMachineBeforeIntersectingDrillings.Tail.Box and vProc[i].Box:getMin():getX() < vMachineBeforeIntersectingDrillings.Tail.Box:getMax():getX() + 100 * GEO.EPS_SMALL and vMachineBeforeIntersectingDrillings.Tail.Box:getMin():getX() < vProc[i].Box:getMax():getX() + 100 * GEO.EPS_SMALL -- verifico che ci sia intersezione tra la direzione di estrusione e la faccia della feature taglio di coda if bIntersectionWithTail then _, _, vDistTail = EgtLineSurfTmInters( ptCen, -vtExtr, vMachineBeforeIntersectingDrillings.Tail.Id, GDB_RT.GLOB) end end -- se esiste intersezione tra il foro e la feature di testa if vDistHead and #vDistHead > 0 then -- verifico che il foro sia di testa if ( bOpen or ( not bOpen and vtExtr:getX() > 0 and vProc[i].Fcs ~= 0) or ( not bOpen and vtExtr:getX() < 0 and vProc[i].Fce ~= 0)) then if vProc[i].Dependency and vProc[i].Dependency.ExecAfter and vProc[i].Dependency.ExecAfter.Id == vMachineBeforeIntersectingDrillings.Head.Id then vProc[i].MachineAfterHeadCutId = vMachineBeforeIntersectingDrillings.Head.Id end vProc[i].Head = true end -- se esiste intersezione tra il foro e la feature di coda elseif vDistTail and #vDistTail > 0 then -- verifico che il foro sia di coda if ( bOpen or ( not bOpen and vtExtr:getX() < 0 and vProc[i].Fcs ~= 0) or ( not bOpen and vtExtr:getX() > 0 and vProc[i].Fce ~= 0)) then if vProc[i].Dependency and vProc[i].Dependency.ExecAfter and vProc[i].Dependency.ExecAfter.Id == vMachineBeforeIntersectingDrillings.Tail.Id then vProc[i].MachineAfterTailCutId = vMachineBeforeIntersectingDrillings.Tail.Id end vProc[i].Tail = true end end end end end ------------------------------------------------------------------------------------------------------------- local function AreDrillingsMirrored( Proc, ProcMirror, b3Raw) if Proc.Id == ProcMirror.Id then return false end -- geometria ausiliaria foro principale 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 -- geometria ausiliaria foro specchiato local AuxIdMirror = EgtGetInfo( ProcMirror.Id, 'AUXID', 'i') if AuxIdMirror then AuxIdMirror = AuxIdMirror + ProcMirror.Id end if not AuxIdMirror or EgtGetType( AuxIdMirror ) ~= GDB_TY.CRV_ARC then return false end -- dati del foro principale local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local ptBC = EgtGP( AuxId, GDB_RT.GLOB) -- dati del foro specchiato local vtExtrMirror = EgtCurveExtrusion( AuxIdMirror, GDB_RT.GLOB) local ptBCMirror = EgtGP( AuxIdMirror, GDB_RT.GLOB) -- direzione fori local nDouble if AreOppositeVectorApprox( vtExtr, vtExtrMirror) then -- fori lungo Y -- per macchine tipo PF il foro principale è sul lato back, per macchine tipo PF1250 è sul lato front if ( BD.TWO_EQUAL_HEADS and AreSameVectorApprox( vtExtr, Y_AX())) or ( BD.DOWN_HEAD and AreOppositeVectorApprox( vtExtr, Y_AX())) then nDouble = 2 -- fori lungo Z elseif BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Z_AX()) then nDouble = 3 else return false end else return false end -- centri allineati, equidistanti dalla mezzeria trave, non troppo vicini local vtDisplacement = ptBC - ptBCMirror local ptCenRaw = b3Raw:getCenter() if nDouble == 2 then local dYMinDistance = max( Proc.Box:getMin():getY(), ProcMirror.Box:getMin():getY()) - min( Proc.Box:getMax():getY(), ProcMirror.Box:getMax():getY()) if not ( abs( vtDisplacement:getX()) < 100 * GEO.EPS_SMALL and abs( vtDisplacement:getZ()) < 100 * GEO.EPS_SMALL and ( abs( ptBC:getY() - ptCenRaw:getY()) - abs( ptBCMirror:getY() - ptCenRaw:getY())) < 100 * GEO.EPS_SMALL and dYMinDistance > MIRROR_DRILLINGS_MIN_DISTANCE + 10 * GEO.EPS_SMALL) then return false end else local dZMinDistance = max( Proc.Box:getMin():getZ(), ProcMirror.Box:getMin():getZ()) - min( Proc.Box:getMax():getZ(), ProcMirror.Box:getMax():getZ()) if not ( abs( vtDisplacement:getX()) < 100 * GEO.EPS_SMALL and abs( vtDisplacement:getY()) < 100 * GEO.EPS_SMALL and ( abs( ptBC:getZ() - ptCenRaw:getZ()) - abs( ptBCMirror:getZ() - ptCenRaw:getZ())) < 100 * GEO.EPS_SMALL and dZMinDistance > MIRROR_DRILLINGS_MIN_DISTANCE + 10 * GEO.EPS_SMALL) then return false end end -- fori della stessa profondità if abs( Proc.Len - ProcMirror.Len) > 10 * GEO.EPS_SMALL then return false end return true end ------------------------------------------------------------------------------------------------------------- function GetFeatureInfoAndDependency( vProc, b3Raw, nPartId) if vProc and #vProc > 0 and nPartId then -- recupero ID per tagli troncanti testa e coda local nHeadCuttingFeatureId = EgtGetInfo( nPartId, 'HEADCUTFEATUREID', 'i') or 0 local nTailCuttingFeatureId = EgtGetInfo( nPartId, 'TAILCUTFEATUREID', 'i') or 0 -- ciclo tutte le feature for i = 1, #vProc do local Proc = vProc[i] -- calcolo topologia della feature if NeedTopologyFeature( Proc) then Topology.Classify( Proc, b3Raw) -- se non richiesto, setto 'SPECIAL' else Proc.Topology = 'SPECIAL' Proc.TopologyLongName = Proc.Topology end -- controllo la feature con tutte le altre per recuperare le dipendenze for j = 1, #vProc do -- non si controlla feature con sé stessa if i ~= j then local ProcB = vProc[j] -- verifico se feature tipo LapJoint è attraversata da almeno un foro if ( Proc.Topology == 'Pocket' or Proc.Topology == 'Tunnel' or Proc.Topology == 'Groove' or Mortise.Identify( Proc)) and Drill.Identify( ProcB) and Overlaps( Proc.Box, ProcB.Box) then -- se foro in coda non setto la dipendenza if not ProcB.AffectedFaces.Left then Proc.PassedByHole = true ProcB.Dependency = {} ProcB.Dependency.ExecBefore = Proc end end -- verifico se feature tipo LapJoint è attraversata da almeno una mortasa a coda di rondine if ( Proc.Topology == 'Pocket' or Proc.Topology == 'Tunnel' or Proc.Topology == 'Groove') and DtMortise.SideIdentify( ProcB) and Overlaps( Proc.Box, ProcB.Box) and DtMortise.IsDeeper( ProcB, b3Raw) then Proc.PassedByDtMortise = true end -- se tenone è attraversato da foro allora il foro deve essere fatto prima if Tenon.Identify( Proc) and Drill.Identify( ProcB) and Overlaps( Proc.Box, ProcB.Box) then Proc.PassedByHole = true end -- se taglio attraversato da foro, si definisce precedenza in base ad angolo if Drill.Identify( Proc) and Cut.Identify( ProcB) and Overlaps( Proc.Box, ProcB.Box) then -- recupero e verifico l'entità foro local DrillAuxId = ( EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0) + Proc.Id local vtDrillExtr = EgtCurveExtrusion( DrillAuxId, GDB_RT.GLOB) local bOpen = ( Proc.Fce ~= 0) and ( Proc.Fce ~= Proc.Fcs) local ptCut, vtCutN = EgtSurfTmFacetCenter( ProcB.Id, 0, GDB_ID.ROOT) local dMaxAngleDrillOnCut = BD.MAX_ANGLE_DRILL_CUT or 10 if GetAngle( vtDrillExtr, vtCutN) > dMaxAngleDrillOnCut then if bOpen and GetAngle( -vtDrillExtr, vtCutN) < dMaxAngleDrillOnCut then ProcB.Dependency = {} ProcB.Dependency.ExecBefore = Proc Proc.Dependency = {} Proc.Dependency.ExecAfter = ProcB else Proc.Dependency = {} Proc.Dependency.ExecBefore = ProcB ProcB.Dependency = {} ProcB.Dependency.ExecAfter = Proc end else ProcB.Dependency = {} ProcB.Dependency.ExecBefore = Proc Proc.Dependency = {} Proc.Dependency.ExecAfter = ProcB end end -- verifiche per specchiature if BD.DOWN_HEAD or BD.TWO_EQUAL_HEADS then -- forature if BD.DOUBLE_HEAD_DRILLING and Drill.Identify( Proc) and Drill.Identify( ProcB) and not Proc.Mirror then if AreDrillingsMirrored( Proc, ProcB, b3Raw) then Proc.Mirror = ProcB end end end -- verifiche per tagli troncanti testa e coda: devono sempre essere subito dopo il taglio di testa e il taglio di coda, rispettivamente if Proc.Prc == 340 and ProcB == nHeadCuttingFeatureId then Proc.Dependency = {} Proc.Dependency.ExecBefore = ProcB elseif Proc == nHeadCuttingFeatureId and ProcB.Prc == 340 then ProcB.Dependency = {} ProcB.Dependency.ExecBefore = Proc elseif Proc.Prc == 350 and ProcB == nTailCuttingFeatureId then Proc.Dependency = {} Proc.Dependency.ExecBefore = ProcB elseif Proc == nTailCuttingFeatureId and ProcB.Prc == 350 then ProcB.Dependency = {} ProcB.Dependency.ExecBefore = Proc end -- se una feature deve essere lavorata prima dei tagli troncanti, si setta che non esiste taglio troncante if Proc.Dependency and Proc.Dependency.ExecBefore and Proc.Dependency.ExecBefore.Id == nHeadCuttingFeatureId then -- EgtRemoveInfo( nPartId, 'HEADCUTFEATUREID') end if Proc.Dependency and Proc.Dependency.ExecBefore and Proc.Dependency.ExecBefore.Id == nTailCuttingFeatureId then -- EgtRemoveInfo( nPartId, 'TAILCUTFEATUREID') end end end end end end ------------------------------------------------------------------------------------------------------------- function BeamExec.ProcessFeatures() if BD.IMPROVE_HEAD_TAIL_DRILLINGS == nil then BD.IMPROVE_HEAD_TAIL_DRILLINGS = true end -- costanti per doppio MIRROR_DRILLINGS_MIN_DISTANCE = 40 MIRROR_POCKETS_MIN_DISTANCE = EgtIf( BD.DOWN_HEAD, 35, 50) -- verifica se possibile rotazione di 90 gradi BD.ROT90 = BD.ROT90 and Verify90DegRotation( EgtGetFirstRawPart()) -- ciclo sui pezzi local nTotErr = 0 local Stats = {} local nOrd = 1 local nRawId = EgtGetFirstRawPart() while nRawId do -- verifico che il grezzo contenga pezzi oppure sia abbastanza lungo da essere scaricato coi carrelli local nPartId = EgtGetFirstPartInRawPart( nRawId) if not nPartId and EgtGetRawPartBBox( nRawId):getDimX() < BD.MinRaw then break end -- aggiungo la fase, se non è la prima if nOrd == 1 then EgtSetCurrPhase( 1) else BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, 0) end local nPhase = EgtGetCurrPhase() local nDispId = EgtGetPhaseDisposition( nPhase) EgtSetInfo( nDispId, 'TYPE', EgtIf( nPartId, 'START', 'REST')) EgtSetInfo( nDispId, 'ORD', nOrd) EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( nRawId) .. ' Part=' .. tostring( nPartId) .. ' ***', 1) -- ingombro del grezzo e sovramateriale di testa local b3Raw = EgtGetRawPartBBox( nRawId) local dCurrOvmH = EgtGetInfo( nRawId, 'HOVM', 'd') or 0 local dCurrOvmT = EgtGetInfo( nRawId, 'TOVM', 'd') or 0 -- recupero le feature di lavorazione della trave local vProc = CollectFeatures( nPartId, b3Raw, dCurrOvmH, dCurrOvmT) -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse GetFeatureInfoAndDependency( vProc, b3Raw, nPartId) -- verifica presenza forature influenzate da lavorazioni di testa o coda if BD.IMPROVE_HEAD_TAIL_DRILLINGS then local vMachBeforeIntersDrillings = CalcHeadTailMachBeforeIntersDrillings( vProc, b3Raw) SetDrillingsToMachineAfterHeadOrTailCut( vProc, vMachBeforeIntersDrillings) end -- verifica presenza di feature specchiate per eventuali lavorazioni simultanee if BD.TWO_EQUAL_HEADS or BD.DOWN_HEAD then SetMirroredFeatures( vProc, b3Raw) end -- le ordino lungo X OrderFeatures( vProc, b3Raw, nPartId) -- le classifico local bAllOk, bSomeDown, bSomeSide, bSplitRot = ClassifyFeatures( vProc, b3Raw, Stats) if not bAllOk then nTotErr = nTotErr + 1 end -- debug if EgtGetDebugLevel() >= 1 then PrintFeatures( vProc, b3Raw) end EgtOutLog( ' *** AddMachinings ***', 1) -- scrivo nel RawPart se ci sono feature lavorate con trave ruotata a 90 o 180 deg if bSomeSide then EgtSetInfo( nRawId, 'ROTATE90', 1) else EgtSetInfo( nRawId, 'ROTATE90', 0) end if bSomeDown then EgtSetInfo( nRawId, 'ROTATE180', 1) else EgtSetInfo( nRawId, 'ROTATE180', 0) end -- verifico se comunque necessario taglio di testa local bNeedHCut = VerifyNeedForHeadCut( vProc, bSomeDown, bSomeSide) -- inserisco corrispondenze di tagli coincidenti con mortase normali o a coda di rondine di testa SetCutsOnFrontMortises( vProc) -- eventuale spostamento fori sui tenoni MoveDrillsOnTenon( vProc) -- identifico la condizione di lavorazione, in base a bSomeDown e bSomeSide local sDownOrSideOrStd = 'STD' -- se richiesto ribaltamento (oppure rotazione) if ( bSomeDown or bSomeSide) and not BD.DOWN_HEAD and not BD.TURN then sDownOrSideOrStd = 'DOWN' -- ribalto le travi della fase corrente local nRId = nRawId while nRId do EgtRotateRawPart( nRId, X_AX(), 180) nRId = EgtGetNextRawPart( nRId) end EgtSetInfo( nDispId, 'ROT', -2) -- flag feature precedente in doppio local nPrevDouble = 0 -- inserisco le lavorazioni da lavorare ribaltate local i = 1 while i <= #vProc do -- creo la lavorazione local Proc = vProc[i] if Proc.Flg ~= 0 and Proc.Down then -- dato che ho ruotato, aggiorno alcune proprietà della feature Proc.Box = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) Proc.Face = BL.GetFacetsInfo( Proc, b3Raw) Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) Proc.DistanceToNextPart = BL.GetDistanceToNextPart( nRawId, nPhase) Proc.PrevDouble = nPrevDouble nPrevDouble = Proc.Double local bOk, sMsg, nNewPhase, AddedIds = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, bNeedHCut, b3Raw, nOrd, sDownOrSideOrStd, nil, nil, dCurrOvmT) -- lavorazioni da fare dopo separazione if AddedIds and #AddedIds > 0 then for j = 1, #AddedIds do table.insert( vProc, AddedIds[j]) end end if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=1, Msg=sMsg, Rot=-2, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=-2, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end else table.insert( Stats, {Err=0, Msg='', Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=0, Msg='', Rot=-2, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end end -- se è taglio di separazione, verifico se ha già aggiunto una nuova fase oppure se è da creare if nNewPhase > 0 then nPhase = nNewPhase elseif nNewPhase == 0 then BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, BD.RAW_OFFSET) EgtRotateRawPart( nRawId, X_AX(), 180) -- se grezzo successivo senza pezzi e finale, va tolto local nNextRawId = EgtGetNextRawPart( nRawId) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BD.MinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end nPhase = EgtGetCurrPhase() nDispId = EgtGetPhaseDisposition( nPhase) EgtSetInfo( nDispId, 'TYPE', 'MID2') EgtSetInfo( nDispId, 'ORD', nOrd) EgtSetInfo( nDispId, 'ROT', -2) end end i = i + 1 end -- se separazione non ancora effettuata, aggiungo nuova fase con le travi in posizione standard if not bSplitRot then BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, 0) -- altrimenti else -- aggiungo nuova fase con le travi in posizione standard BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, BD.RAW_OFFSET) -- se grezzo successivo senza pezzi e finale, va tolto local nNextRawId = EgtGetNextRawPart( nRawId) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BD.MinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end end nPhase = EgtGetCurrPhase() nDispId = EgtGetPhaseDisposition( nPhase) local nType = 'MID' if bSplitRot then nType = EgtIf( bSomeSide, 'MID2', 'END2') end EgtSetInfo( nDispId, 'TYPE', nType) EgtSetInfo( nDispId, 'ORD', nOrd) end -- se richiesta rotazione if bSomeSide and not BD.DOWN_HEAD and not BD.TURN then sDownOrSideOrStd = 'SIDE' -- vettore movimento grezzi per rotazione di 90deg local dDeltaYZ = EgtGetRawPartBBox( nRawId):getDimY() - EgtGetRawPartBBox( nRawId):getDimZ() local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BD.RIGHT_LOAD, -1, 1), dDeltaYZ / 2) local bPreMove = ( dDeltaYZ < 0) -- ruoto le travi della fase corrente local nRId = nRawId while nRId do if bPreMove then EgtMoveRawPart( nRId, vtMove) end EgtRotateRawPart( nRId, X_AX(), EgtIf( BD.RIGHT_LOAD, -90, 90)) if not bPreMove then EgtMoveRawPart( nRId, vtMove) end nRId = EgtGetNextRawPart( nRId) end EgtSetInfo( nDispId, 'ROT', -1) -- flag feature precedente in doppio local nPrevDouble = 0 -- inserisco le lavorazioni da lavorare ruotate local nSideMchOk = 0 local i = 1 while i <= #vProc do -- creo la lavorazione local Proc = vProc[i] if Proc.Flg ~= 0 and Proc.Side then -- dato che ho ruotato, aggiorno alcune proprietà della feature Proc.Box = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) Proc.Face = BL.GetFacetsInfo( Proc, b3Raw) Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) Proc.DistanceToNextPart = BL.GetDistanceToNextPart( nRawId, nPhase) Proc.PrevDouble = nPrevDouble nPrevDouble = Proc.Double local bOk, sMsg, nNewPhase, AddedIds = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, false, b3Raw, nOrd, sDownOrSideOrStd, bPreMove, vtMove, dCurrOvmT) -- lavorazioni da fare dopo separazione if AddedIds and #AddedIds > 0 then for j = 1, #AddedIds do table.insert( vProc, AddedIds[j]) end end if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=-1, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=1, Msg=sMsg, Rot=-1, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=-1, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=-1, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end else table.insert( Stats, {Err=0, Msg='', Rot=-1, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=0, Msg='', Rot=-1, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end end if bOk then nSideMchOk = nSideMchOk + 1 end -- se era taglio di separazione, aggiungo nuova fase if nNewPhase > 0 then nPhase = nNewPhase elseif nNewPhase == 0 then BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, BD.RAW_OFFSET) if bPreMove then EgtMoveRawPart( nRawId, vtMove) end EgtRotateRawPart( nRawId, X_AX(), EgtIf( BD.RIGHT_LOAD, -90, 90)) if not bPreMove then EgtMoveRawPart( nRawId, vtMove) end -- se grezzo successivo senza pezzi e finale, va tolto local nNextRawId = EgtGetNextRawPart( nRawId) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BD.MinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end nPhase = EgtGetCurrPhase() nDispId = EgtGetPhaseDisposition( nPhase) EgtSetInfo( nDispId, 'TYPE', 'MID2') EgtSetInfo( nDispId, 'ORD', nOrd) EgtSetInfo( nDispId, 'ROT', -1) end end i = i + 1 end -- se non sono state inserite lavorazioni di fianco, elimino la fase perchè inutile e dannosa if nSideMchOk == 0 then EgtRemoveLastPhase() end -- se separazione non ancora effettuata, aggiungo nuova fase con le travi in posizione standard if not bSplitRot then BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, 0) -- altrimenti else BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, BD.RAW_OFFSET) -- se grezzo successivo senza pezzi e finale, va tolto local nNextRawId = EgtGetNextRawPart( nRawId) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BD.MinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end end nPhase = EgtGetCurrPhase() nDispId = EgtGetPhaseDisposition( nPhase) EgtSetInfo( nDispId, 'TYPE', EgtIf( not bSplitRot, 'MID', 'END2')) EgtSetInfo( nDispId, 'ORD', nOrd) end sDownOrSideOrStd = 'STD' -- flag feature precedente in doppio local nPrevDouble = 0 -- inserisco le lavorazioni non ribaltate della trave local i = 1 while i <= #vProc do -- creo la lavorazione local Proc = vProc[i] if Proc.Flg ~= 0 and ( not ( Proc.Down or Proc.Side) or BD.DOWN_HEAD or BD.TURN) then -- dato che ho ruotato, aggiorno alcune proprietà della feature Proc.Box = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) Proc.Face = BL.GetFacetsInfo( Proc, b3Raw) Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) Proc.DistanceToNextPart = BL.GetDistanceToNextPart( nRawId, nPhase) Proc.PrevDouble = nPrevDouble nPrevDouble = Proc.Double local bOk, sMsg, nNewPhase, AddedIds = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, false, b3Raw, nOrd, sDownOrSideOrStd, nil, nil, dCurrOvmT) -- lavorazioni da fare dopo separazione if AddedIds and #AddedIds > 0 then for j = 1, #AddedIds do table.insert( vProc, AddedIds[j]) end end if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=0, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end else table.insert( Stats, {Err=0, Msg='', Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId, ProcId = Proc.Id, PartId = nPartId}) if Proc.Double == 2 or Proc.Double == 3 then table.insert( Stats, {Err=0, Msg='', Rot=0, CutId=Proc.MirrorCutId, TaskId=Proc.MirrorTaskId, ProcId = Proc.MirrorId, PartId = nPartId}) end end -- se era taglio di separazione, aggiungo nuova fase if nNewPhase > 0 then nPhase = nNewPhase elseif nNewPhase == 0 then BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, BD.RAW_OFFSET) -- se grezzo successivo senza pezzi e finale, va tolto local nNextRawId = EgtGetNextRawPart( nRawId) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BD.MinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end nPhase = EgtGetCurrPhase() nDispId = EgtGetPhaseDisposition( nPhase) EgtSetInfo( nDispId, 'TYPE', 'END') EgtSetInfo( nDispId, 'ORD', nOrd) end end i = i + 1 end EgtOutLog( ' *** End AddMachinings ***', 1) -- passo al grezzo successivo nOrd = nOrd + 1 nRawId = EgtGetNextRawPart( nRawId) end -- Aggiornamento finale di tutto EgtSetCurrPhase( 1) local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings() -- eventuale ricalcolo per macchine tipo PF (ma tengo warning del primo calcolo) if EgtExistsInfo( EgtGetCurrMachGroup(), 'RECALC') then EgtOutLog( ' **** RECALC ****') bApplOk, sApplErrors, _ = EgtApplyAllMachinings() EgtRemoveInfo( EgtGetCurrMachGroup(), 'RECALC') end if not bApplOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err = 1, Msg=sApplErrors, Rot=0, CutId=0, TaskId=0}) elseif sApplWarns and #sApplWarns > 0 then local vLine = EgtSplitString( sApplWarns, '\r\n') for i = 1, #vLine do local nPos = vLine[i]:find( '(WRN', 1, true) if nPos then local sData = vLine[i]:sub( nPos + 1, -2) local vVal = EgtSplitString( sData, ',') local nWarn = EgtGetVal( vVal[1] or '', 'WRN', 'i') local nCutId = EgtGetVal( vVal[2] or '', 'CUTID', 'i') if nWarn and nCutId then table.insert( Stats, { Err=-nWarn, Msg=vLine[i], Rot=0, CutId=nCutId, TaskId=0}) end end end end return ( nTotErr == 0), Stats end ------------------------------------------------------------------------------------------------------------- return BeamExec