-- BeamExec.lua by Egaltech s.r.l. 2022/08/18 -- 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. -- 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.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 local ML = require( 'MachiningLib') local BL = require( 'BeamLib') 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') 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 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 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 ------------------------------------------------------------------------------------------------------------- -- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra, rappresentata dalle sue dimensioni W e H local function IsFeatureCuttingEntireSection( b3Proc, dRawW, dRawH) return ((abs(b3Proc:getDimY() - dRawW) < 10 * GEO.EPS_SMALL or b3Proc:getDimY() > dRawW) and (abs(b3Proc:getDimZ() - dRawH) < 10 * GEO.EPS_SMALL or b3Proc:getDimZ() > dRawH)) 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') local nMachineBeforeIntersectingDrillingsIdHead, dMachineBeforeIntersectingDrillingsXHead, nMachineBeforeIntersectingDrillingsIdTail, dMachineBeforeIntersectingDrillingsXTail = nil, GEO.INFINITO, nil, -GEO.INFINITO local b3MachineBeforeIntersectingDrillingsBoxHead, b3MachineBeforeIntersectingDrillingsBoxTail = nil, nil 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 if nGrp and nPrc and nDo == 1 then local Proc = {} 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.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) if Proc.Box and not Proc.Box:isEmpty() then Proc.Head = IsHeadFeature( Proc, b3Raw, dCurrOvmH) Proc.Tail, Proc.AdvTail = IsTailFeature( Proc, b3Raw, dCurrOvmH, dCurrOvmT) if Proc.Fct == 1 and IsFeatureCuttingEntireSection( Proc.Box , dRawW, dRawH) and ( Proc.Head or Proc.Tail) and Proc.Prc ~= 340 and Proc.Prc ~= 350 then if Proc.Head and Proc.Box:getCenter():getX() < dMachineBeforeIntersectingDrillingsXHead then dMachineBeforeIntersectingDrillingsXHead = Proc.Box:getCenter():getX() nMachineBeforeIntersectingDrillingsIdHead = Proc.Id b3MachineBeforeIntersectingDrillingsBoxHead = Proc.Box elseif Proc.Tail and Proc.Box:getCenter():getX() > dMachineBeforeIntersectingDrillingsXTail then dMachineBeforeIntersectingDrillingsXTail = Proc.Box:getCenter():getX() nMachineBeforeIntersectingDrillingsIdTail = Proc.Id b3MachineBeforeIntersectingDrillingsBoxTail = Proc.Box end end 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.Fcs, Proc.Fce = Drill.GetData( Proc, b3Raw) -- 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.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.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 table.insert( vProc, Proc2) end -- se BlockHaus HalfLap elseif Proc.Prc == 37 then local nFacInd = BL.GetFaceWithMostAdj( Proc.Id, 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 local vMachineBeforeIntersectingDrillings = { Head = { Id = nMachineBeforeIntersectingDrillingsIdHead, Box = b3MachineBeforeIntersectingDrillingsBoxHead}, Tail = { Id = nMachineBeforeIntersectingDrillingsIdTail, Box = b3MachineBeforeIntersectingDrillingsBoxTail} } return vProc, vMachineBeforeIntersectingDrillings end ------------------------------------------------------------------------------------------------------------- local function AnalyzeHeadFeatures( b3Solid, vProc, dRawW, dRawH) local nReplacedFeatureId = nil local bHeadFinishingNeeded = true 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 IsFeatureCuttingEntireSection( Proc.Box, dRawW, dRawH) end end return bHeadFinishingNeeded, nReplacedFeatureId end ------------------------------------------------------------------------------------------------------------- local function AnalyzeTailFeatures( b3Solid, vProc, dRawW, dRawH) local nReplacedFeatureId = nil local bTailFinishingNeeded = true 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 IsFeatureCuttingEntireSection( Proc.Box, dRawW, dRawH) end end return bTailFinishingNeeded, nReplacedFeatureId 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, 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) -- 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') -- Area tavola local b3Tab = EgtGetTableArea() -- Calcolo posizione estremo TR/BR della tavola rispetto a sua origine in BL BD.OriXR = Point3d( b3Tab:getDimX(), EgtIf( BD.RIGHT_LOAD, 0, b3Tab:getDimY()), 0) BD.PosXR = EgtIf( BD.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR) -- Impostazione dell'attrezzaggio di default EgtImportSetup() -- 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 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 lastB3Solid = vBeam[i-1].Box dOffset = vBeam[i].PosX - vBeam[i-1].PosX - lastB3Solid:getDimX() 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 = AnalyzeHeadFeatures( b3Solid, vProc, dRawW, dRawH) 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 bEFinishingNeeded, nReplacedTailCutFeatureId = AnalyzeTailFeatures( b3Solid, vProc, dRawW, dRawH) 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 and vBeam[i].PosX then DeltaS = max( vBeam[i].PosX - ( dRawL - Len), DeltaSMin) 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) -- 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 -- 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', 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)) -- 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 ------------------------------------------------------------------------------------------------------------- local function OrderFeatures( vProc, b3Raw) local dDrillPenalty = EgtIf( BD.PRESS_ROLLER, 200, 100) local dSmallDrillRange = EgtIf( b3Raw:getDimX() < BD.LEN_SHORT_PART, 200, 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 di testa e non l'altro, privilegio quello di testa if B1.Head ~= B2.Head then return B1.Head 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 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 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 è 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 è 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 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 if B1.Prc == 40 and B2.Prc ~= 40 then return ( B1.Box:getCenter():getX() > B2.Box:getMax():getX() + dDrillPenalty) end -- se primo è altro e secondo è foro, lo premio if B1.Prc ~= 40 and B2.Prc == 40 then return ( B1.Box:getMax():getX() + dDrillPenalty > B2.Box:getCenter():getX()) 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 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 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 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 = FreeContour.Classify( Proc, b3Raw) -- se decorazione elseif Decor.Identify( Proc) then bOk, bDown = Decor.Classify( Proc) end -- assegno risultato if bOk then -- non ammessa feature di testa da lavorare ribaltata o ruotata 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}) -- 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}) 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}) 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 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 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 = 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 = 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) -- 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) -- 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 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 ------------------------------------------------------------------------------------------------------------- -- 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 vProc[i].MachineAfterHeadCutId = vMachineBeforeIntersectingDrillings.Head.Id 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 vProc[i].MachineAfterTailCutId = vMachineBeforeIntersectingDrillings.Tail.Id vProc[i].Tail = true end end end end end ------------------------------------------------------------------------------------------------------------- function BeamExec.ProcessFeatures() if BD.IMPROVE_HEAD_TAIL_DRILLINGS == nil then BD.IMPROVE_HEAD_TAIL_DRILLINGS = true end -- 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, vMachineBeforeIntersectingDrillings = CollectFeatures( nPartId, b3Raw, dCurrOvmH, dCurrOvmT) -- verifica presenza forature influenzate da lavorazioni di testa o coda if BD.IMPROVE_HEAD_TAIL_DRILLINGS then SetDrillingsToMachineAfterHeadOrTailCut( vProc, vMachineBeforeIntersectingDrillings) end -- le ordino lungo X OrderFeatures( vProc, b3Raw) -- 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) -- 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) -- inserisco le lavorazioni da lavorare ribaltate for i = 1, #vProc do -- creo la lavorazione local Proc = vProc[i] if Proc.Flg ~= 0 and Proc.Down then local bOk, sMsg, nNewPhase = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, bNeedHCut, b3Raw, nOrd, sDownOrSideOrStd, nil, nil, dCurrOvmT) if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId}) elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId}) else table.insert( Stats, {Err=0, Msg='', Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId}) 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 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, 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) -- inserisco le lavorazioni da lavorare ruotate local nSideMchOk = 0 for i = 1, #vProc do -- creo la lavorazione local Proc = vProc[i] if Proc.Flg ~= 0 and Proc.Side then local bOk, sMsg, nNewPhase = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, false, b3Raw, nOrd, sDownOrSideOrStd, bPreMove, vtMove, dCurrOvmT) if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId}) elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId}) else table.insert( Stats, {Err=0, Msg='', Rot=-2, CutId=Proc.CutId, TaskId=Proc.TaskId}) 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 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' -- inserisco le lavorazioni non ribaltate della trave for i = 1, #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 local bOk, sMsg, nNewPhase = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, false, b3Raw, nOrd, sDownOrSideOrStd, nil, nil, dCurrOvmT) if not bOk then nTotErr = nTotErr + 1 table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId}) elseif sMsg and #sMsg > 0 then table.insert( Stats, {Err=-1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId}) else table.insert( Stats, {Err=0, Msg='', Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId}) 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 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