Files
DataBeam/LuaLibs/BeamExec.lua
T
DarioS 4789452523 DataBeam :
- Corrette rotazioni 90 deg per macchine con carico da destra.
2022-12-14 11:18:33 +01:00

1802 lines
86 KiB
Lua

-- BeamExec.lua by Egaltech s.r.l. 2022/12/23
-- 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.
-- 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
-- leggo se ci sono feature collegate
local nAddAdjId = EgtGetInfo( ProcId, 'ADJID', 'i')
local nAddMainId = EgtGetInfo( ProcId, 'MAINID', 'i')
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
-- 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 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
Proc2.AdjId = Proc.AdjId
Proc2.MainId = Proc.MainId
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, 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 di testa e non l'altro, privilegio quello di testa
if B1.Head ~= B2.Head then
return B1.Head
end
-- se primo è foro e secondo è un ribasso, il foro va sempre prima
if Drill.Identify(B1) and LapJoint.Identify(B2) 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, il ribasso va sempre dopo
if LapJoint.Identify(B1) 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 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 or -1)
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
-------------------------------------------------------------------------------------------------------------
-- Estrazione parametri P da lavorazioni di tipo DtMortise
local function GetPParametersDtMortise( Proc)
local vPParameters = {
{ 'P01', 'd'},
{ 'P02', 'd'},
{ 'P03', 'd'},
{ 'P04', 'i'},
{ 'P05', 'i'},
{ 'P06', 'd'},
{ 'P07', 'd'},
{ 'P09', 'd'},
{ 'P10', 'd'},
{ 'P11', 'd'},
{ 'P12', 'd'},
{ 'P13', 'd'},
{ 'P14', 'd'},
{ 'P15', 'd'}
}
for i = 1, #vPParameters do
vPParameter = vPParameters[i]
vPParameter[3] = EgtGetInfo( Proc.Id, vPParameter[1], vPParameter[2])
end
return vPParameters
end
-------------------------------------------------------------------------------------------------------------
-- Controlla se la feature ProcMirror è la specchiata di Proc, per feature di tipo DtMortise
local function CheckMirrorDtMortise( Proc, ProcMirror, dHBeam)
local bIsMirror = true
local vPParametersProc = GetPParametersDtMortise( Proc)
local vPParametersMirror = GetPParametersDtMortise( ProcMirror)
local nP02, nP06 = 2, 6
-- controllo che i parametri P delle due feature, tranne P02 e P06, siano uguali
for i = 1, #vPParametersProc do
local vPParameterProc = vPParametersProc[i]
local vPParameterMirror = vPParametersMirror[i]
if vPParameterProc[1] ~= 'P02' and vPParameterProc[1] ~= 'P06'then
bIsMirror = ( abs( vPParameterProc[3] - vPParameterMirror[3]) < 100 * GEO.EPS_SMALL)
if bIsMirror == false then break end
elseif vPParameterProc[1] == 'P02' then
nP02 = i
elseif vPParameterProc[1] == 'P06' then
nP06 = i
end
end
-- se gli altri parametri P sono uguali, verifico che P02 e P06 siano compatibili con feature specchiate
if bIsMirror == true then
bIsMirror = ( ( vPParametersProc[nP02][3] == 0 and abs( vPParametersMirror[nP02][3] - dHBeam) < 100 * GEO.EPS_SMALL) and
( vPParametersProc[nP06][3] == 90 and vPParametersMirror[nP06][3] == -90)) or
( ( vPParametersMirror[nP02][3] == 0 and abs( vPParametersProc[nP02][3] - dHBeam) < 100 * GEO.EPS_SMALL) and
( vPParametersMirror[nP06][3] == 90 and vPParametersProc[nP06][3] == -90))
end
return bIsMirror
end
-------------------------------------------------------------------------------------------------------------
-- Cerca se esiste una feature specchiata di Proc e nel caso ne restituisce la posizione in vProc
local function FindMirrorFeature( vProc, Proc, sFeatureType, dHBeam)
local nProcMirror
-- se mortasa a coda di rondine
if sFeatureType == 'DtMortise' then
Proc.Side = EgtGetInfo( Proc.Id, 'SIDE', 'i')
for i = 1, #vProc do
local ProcMirror = vProc[i]
if DtMortise.SideIdentify(ProcMirror) then
ProcMirror.Side = EgtGetInfo( ProcMirror.Id, 'SIDE', 'i')
if ( Proc.Side == 1 and ProcMirror.Side == 3) or ( Proc.Side == 3 and ProcMirror.Side == 1) or
( Proc.Side == 2 and ProcMirror.Side == 4) or ( Proc.Side == 4 and ProcMirror.Side == 2) then
local bIsMirror = CheckMirrorDtMortise( Proc, ProcMirror, dHBeam)
if bIsMirror then nProcMirror = i end
end
end
end
end
-- se foratura (da implementare)
return nProcMirror
end
-------------------------------------------------------------------------------------------------------------
-- Cerca in vProc la presenza di feature specchiate. Se le trova scrive in Proc e nelle info l'Id della specchiata.
local function SetMirroredFeatures( vProc, dHBeam)
for i = 1, #vProc do
local Proc = vProc[i]
local sFeatureType
if DtMortise.SideIdentify(Proc) then
sFeatureType = 'DtMortise'
elseif Drill.Identify(Proc) then
sFeatureType = 'Drill'
end
if ( sFeatureType == 'DtMortise' or sFeatureType == 'Drill') and not Proc.MirrorId then
local nProcMirror = FindMirrorFeature( vProc, Proc, sFeatureType, dHBeam)
if nProcMirror then
Proc.MirrorId = vProc[nProcMirror].Id
vProc[nProcMirror].MirrorId = Proc.Id
EgtSetInfo( Proc.Id, 'MIRRORID', vProc[nProcMirror].Id)
EgtSetInfo( vProc[nProcMirror].Id, 'MIRRORID', Proc.Id)
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
-- verifica presenza di feature specchiate per eventuali lavorazioni simultanee
local bConcurrentDoubleHead = BD.DOUBLE_HEAD_MIRRORED_FEATURES and ( BD.TWO_EQUAL_HEADS or BD.TWO_UP_DOWN_HEADS)
if bConcurrentDoubleHead then
SetMirroredFeatures( vProc, EgtGetRawPartBBox( nRawId):getDimZ())
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 * 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)
-- 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