Files
DataBeam/LuaLibs/BeamExec.lua

1378 lines
63 KiB
Lua

-- BeamExec.lua by Egaltech s.r.l. 2021/12/20
-- 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).
-- 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 BM = 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()
-------------------------------------------------------------------------------------------------------------
-- *** Inserimento delle travi nel grezzo ***
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, vBeam, bMachGroupOk)
-- 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 DeltaE = BD.OVM_MID
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
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) < 10 * GEO.EPS_SMALL and abs( PartHeight - dRawH) < 10 * GEO.EPS_SMALL) or
( abs( PartHeight - dRawW) < 10 * GEO.EPS_SMALL and abs( PartWidth - dRawH) < 10 * GEO.EPS_SMALL)) and
NextLen + DeltaE >= 0 then
-- eventuale sovramateriale di testa
if vBeam[i].PosX then
DeltaS = max( vBeam[i].PosX - ( dRawL - Len), 0)
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
-- 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) > 10 * 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
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
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
-------------------------------------------------------------------------------------------------------------
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)
-- feature sempre di testa o coda per il gruppo (se non troppo lunga)
if Proc.Grp == 1 or Proc.Grp == 2 then
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
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)
end
if DtMortise.Identify( Proc) then
return DtMortise.IsTailFeature( Proc, b3Raw)
end
if RoundArch.Identify( Proc) then
return RoundArch.IsTailFeature( Proc, b3Raw)
end
if Dovetail.Identify( Proc) then
return Dovetail.IsTailFeature( Proc, b3Raw)
end
if FreeContour.Identify( Proc) then
return FreeContour.IsTailFeature( Proc, b3Raw)
end
-- non è di coda
return false
end
-------------------------------------------------------------------------------------------------------------
local function 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', '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 CollectFeatures( PartId, b3Raw, dCurrOvmH)
-- recupero le feature
local vProc = {}
local LayerId = {}
LayerId[1] = BL.GetAddGroup( PartId)
LayerId[2] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Processings')
for nInd = 1, 2 do
local ProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL)
while ProcId do
local nEntType = EgtGetType( ProcId)
if nEntType == GDB_TY.SRF_MESH or nEntType == GDB_TY.EXT_TEXT or
nEntType == GDB_TY.CRV_LINE or nEntType == GDB_TY.CRV_ARC or nEntType == GDB_TY.CRV_BEZ or nEntType == GDB_TY.CRV_COMPO then
local nGrp = EgtGetInfo( ProcId, 'GRP', 'i')
local nPrc = EgtGetInfo( ProcId, 'PRC', 'i')
local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1
local nCutId = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0
local nTaskId = EgtGetInfo( ProcId, 'TASKID', 'i') or 0
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 = IsTailFeature( Proc, b3Raw, dCurrOvmH)
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 = IsHeadFeature( Proc, b3Raw, dCurrOvmH)
Proc.Tail = IsTailFeature( Proc, b3Raw, dCurrOvmH)
-- 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)
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
return vProc
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 è 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 a Zmax
if abs( B2.Box:getDimX() - b3Raw:getDimX()) < 0.2 * b3Raw:getDimX() then
return B1.Box:getMax():getZ() > B2.Box:getMax():getZ()
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 then
for j = i + 1, #vProc do
local ProcJ = vProc[j]
if ProcJ.Prc == 40 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 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.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 then
for j = i + 1, #vProc do
local ProcJ = vProc[j]
if ProcJ.Prc == 37 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
for i = 1, #vProc do
local Proc = vProc[i]
local bOk = true
local bDown = false
local bSide = false
local bDownSideOnHeadOk = false
-- 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)
local bOk = true
local sErr = ''
local bNewPhase = false
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 = Split.Make( Proc, nPhase, nRawId, nPartId)
-- richiedo il passaggio alla seconda fase di lavorazione di questa trave
bNewPhase = true
-- se taglio ( 1/2-010-X)
elseif Cut.Identify( Proc) then
-- esecuzione taglio
bOk, sErr = Cut.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH)
-- 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)
-- 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)
-- 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)
-- 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)
-- se giunto Gerber ( 1/2-070-X)
elseif Scarf.Identify( Proc) then
-- esecuzione giunto Gerber
bOk, sErr = Scarf.Make( Proc, nPhase, nRawId, nPartId, dCurrOvmH)
-- 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)
-- 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)
-- 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, bNewPhase
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
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessFeatures()
-- 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
-- recupero le feature di lavorazione della trave
local vProc = CollectFeatures( nPartId, b3Raw, dCurrOvmH)
-- 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)
-- se richiesto ribaltamento (oppure rotazione)
if ( bSomeDown or bSomeSide) and not BD.DOWN_HEAD then
-- 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, bNewPhase = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, bNeedHCut, b3Raw)
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 era taglio di separazione, aggiungo nuova fase
if bNewPhase 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 then
-- 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, bNewPhase = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, false, b3Raw)
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 bNewPhase 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
-- 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) then
local bOk, sMsg, bNewPhase = AddFeatureMachining( Proc, nPhase, nRawId, nPartId, dCurrOvmH, false, b3Raw)
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 bNewPhase 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