diff --git a/ProgettoRestylingWall/Wall/BatchProcess.lua b/ProgettoRestylingWall/Wall/BatchProcess.lua
new file mode 100644
index 0000000..616cd84
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/BatchProcess.lua
@@ -0,0 +1,657 @@
+-- BatchProcess.lua by Egaltech s.r.l. 2022/02/24
+-- Gestione calcolo batch disposizione e lavorazioni per Pareti
+-- 2020/07/24 Nuvola di punti riferita allo Zero Tavola.
+-- 2020/10/28 Corretto spostamento pezzi per rotazioni (0 o 180) e inversioni( 0, 90, 180, o 270).
+-- 2020/12/03 Ora riconosciute rotazioni di inversione con angoli negativi.
+-- 2021/03/05 Aggiunta gestione altri angoli di inversione e rotazione combinati.
+-- 2021/03/06 La creazione del file ori si fa solo alla fine se non ci sono stati errori o se edit.
+-- 2021/03/08 Aggiunta gestione lavorazione su macchine per travi.
+-- 2021/04/09 Corretto spostamento pezzi per rotazioni e inversioni.
+-- 2021/07/28 Aggiunta scelta direzione di vista per modifica e simulazione.
+-- 2021/10/27 Nel controllo spessore si deve considerare anche PosY.
+-- 2022/02/24 Se ricalcolo si aggiorna il setup. In ogni caso si verifica prima di simulazione.
+
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+-- Per test
+--WALL = {}
+--WALL.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
+--WALL.MACHINE = '90480019_MW'
+--WALL.FLAG = 5
+
+-- Log dati in input
+local sFlag = ''
+if WALL.FLAG == 0 then
+ sFlag = 'GENERATE'
+elseif WALL.FLAG == 1 then
+ sFlag = 'MODIFY'
+elseif WALL.FLAG == 2 then
+ sFlag = 'SIMULATE'
+elseif WALL.FLAG == 3 then
+ sFlag = 'CHECK'
+elseif WALL.FLAG == 4 then
+ sFlag = 'CHECK+GENERATE'
+elseif WALL.FLAG == 5 then
+ sFlag = 'CLOUD'
+elseif WALL.FLAG == 11 then
+ sFlag = 'TOOLS'
+elseif WALL.FLAG == 12 then
+ sFlag = 'JOBS'
+else
+ sFlag = 'FLAG='..tostring( WALL.FLAG)
+end
+local sLog = 'BatchProcess : ' .. WALL.FILE .. ', ' .. WALL.MACHINE .. ', ' .. sFlag
+EgtOutLog( sLog)
+
+-- Cancello file di log specifico
+local sLogFile = EgtChangePathExtension( WALL.FILE, '.txt')
+EgtEraseFile( sLogFile)
+
+-- Funzioni per scrittura su file di log specifico
+local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
+ local hFile = io.open( sLogFile, 'a')
+ hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
+ hFile:write( sMsg .. '\n')
+ hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
+ hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
+ hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
+ hFile:close()
+end
+local function WriteTimeToLogFile( dTime)
+ local hFile = io.open( sLogFile, 'a')
+ hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
+ hFile:close()
+end
+
+-- Funzione per gestire visualizzazione dopo errore
+local function PostErrView( nErr, sMsg)
+ if nErr ~= 0 and ( WALL.FLAG == 1 or WALL.FLAG == 2 or WALL.FLAG == 5) then
+ EgtSetView( SCE_VD.ISO_SW, false)
+ EgtZoom( SCE_ZM.ALL)
+ EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
+ end
+end
+
+-- Funzione per gestire visualizzazione dopo warning
+local function PostWarnView( nWarn, sMsg)
+ if nWarn ~= 0 and ( WALL.FLAG == 1 or WALL.FLAG == 2 or WALL.FLAG == 5) then
+ EgtSetView( SCE_VD.ISO_SW, false)
+ EgtZoom( SCE_ZM.ALL)
+ EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
+ end
+end
+
+-- Funzione per aggiornare dati ausiliari
+local function UpdateAuxData( sAuxFile)
+ local bModif = false
+ -- Se definito LOAD90, aggiorno
+ local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
+ if sLoad90 ~= '' then
+ local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
+ EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
+ bModif = true
+ end
+ return bModif
+end
+
+-- Imposto direttorio libreria specializzata per Travi
+local sBaseDir = EgtGetSourceDir()
+EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua')
+
+-- Impostazione della macchina corrente
+EgtResetCurrMachGroup()
+local sMachine = 'Essetre-' .. WALL.MACHINE
+if not EgtSetCurrMachine( sMachine) then
+ WALL.ERR = 11
+ WALL.MSG = 'Error selecting machine : ' .. sMachine
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+end
+
+-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
+local sMachDir = EgtGetCurrMachineDir()
+if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then
+ WALL.ERR = 12
+ WALL.MSG = 'Error not configured for walls machine : ' .. sMachine
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+end
+
+-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
+EgtRemoveBaseMachineDirFromPackagePath()
+EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua')
+
+-- Se modalità visualizzazione finestre per DB esco
+if WALL.FLAG > 10 then
+ WALL.ERR = 0
+ return
+end
+
+-- Carico le librerie
+_G.package.loaded.WallExec = nil
+local WE = require( 'WallExec')
+--local BL = require( 'BeamLib')
+
+-- Carico i dati globali
+local WD = require( 'WallData')
+
+-- Dati del file
+local sDir, sTitle, sExt = EgtSplitPath( WALL.FILE)
+local bBtl = ( string.upper( sExt or '') ~= '.NGE')
+local sNgeFile = sDir..sTitle..'.nge'
+local sBtmFile = sDir..sTitle..'.btm'
+local sPntFile = sDir..sTitle..'.pnt'
+
+-- In generale va completamente riprocessato
+local bToProcess = true
+local bToRecalc = false
+-- se BTL, barra ed esiste già il corrispondente progetto Nge
+if bBtl and string.find( sTitle, 'Bar_', 1, true) and EgtExistsFile( sNgeFile) then
+ local sOriFile = sDir..sTitle..'.ori'..sExt
+ local sDiffFile = sDir..sTitle..'.diff.txt'
+ EgtEraseFile( sDiffFile)
+ local _, nDiff = EgtTextFileCompare( WALL.FILE, sOriFile, ';', sDiffFile)
+ -- se BTL corrente coincide con originale, salto il riprocessamento
+ if nDiff == 0 then
+ bToProcess = false
+ -- se cambiata configurazione macchina da ultima elaborazione, devo riprocessare
+ if EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Wall\\TS3Data.lua') == -1 or
+ EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Tools\\Tools.data') == -1 then
+ bToRecalc = true
+ end
+ end
+end
+
+-- Inizializzo contatori errori e avvisi
+local nErrCnt = 0
+local nWarnCnt = 0
+
+-- Se da elaborare
+if bToProcess then
+ EgtOutLog( ' +++ Processing Parts >>>')
+ -- Se Btl, lo importo
+ if bBtl then
+ -- cancello eventuale vecchio progetto omonimo
+ EgtEraseFile( sNgeFile)
+ -- eseguo import
+ EgtNewFile()
+ if not EgtImportBtl( WALL.FILE, EIB_FL.TS3_POS + EIB_FL.USEUATTR) then
+ WALL.ERR = 13
+ WALL.MSG = 'Error importing BTL file : ' .. WALL.FILE
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+ -- altrimenti Nge, lo apro
+ else
+ if not EgtOpenFile( WALL.FILE) then
+ WALL.ERR = 13
+ WALL.MSG = 'Error opening NGE file : ' .. WALL.FILE
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+ end
+
+ -- Aggiorno eventuali dati ausiliari
+ UpdateAuxData( sBtmFile)
+
+ -- Recupero informazione se progetto o produzione
+ local bProj = ( EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL, 'PROJECT', 'i') == 1)
+
+ -- Dimensioni del pannello
+ local dRawL = ( EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL, 'PANELLEN', 'd') or 100)
+ local dRawW = ( EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL, 'PANELWIDTH', 'd') or 50)
+ local dExtraL = 0
+ local dExtraW = 0
+ if bProj then
+ if WD.BEAM_MACHINE then
+ if dRawL < WD.MIN_LENGTH then
+ dExtraL = WD.MIN_LENGTH - dRawL
+ dRawL = WD.MIN_LENGTH
+ elseif dRawL < WD.MAX_LENGTH then
+ dExtraL = min( WD.MAX_LENGTH - dRawL, 3000)
+ dRawL = dRawL + dExtraL
+ end
+ if dRawW + 10 < WD.MIN_WIDTH then
+ dExtraW = WD.MIN_WIDTH - dRawW
+ dRawW = WD.MIN_WIDTH
+ elseif dRawW < WD.MAX_WIDTH then
+ dExtraW = min( WD.MAX_WIDTH - dRawW, 10)
+ dRawW = dRawW + dExtraW
+ end
+ else
+ dExtraW = 10
+ dRawW = dRawW + dExtraW
+ end
+ end
+
+ -- Recupero l'elenco ordinato delle pareti
+ local vWall = {}
+ local nPartId = EgtGetFirstPart()
+ while nPartId do
+ table.insert( vWall, { Id = nPartId, Name = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
+ nPartId = EgtGetNextPart( nPartId)
+ end
+ if #vWall == 0 then
+ WALL.ERR = 14
+ WALL.MSG = 'Error no beams in the file : ' .. WALL.FILE
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ else
+ local sOut = ''
+ for i = 1, #vWall do
+ sOut = sOut .. vWall[i].Name .. ', '
+ end
+ sOut = sOut:sub( 1, -3)
+ EgtOutLog( 'Travi trovate : ' .. sOut, 1)
+ end
+
+ -- Ne recupero le dimensioni
+ for i = 1, #vWall do
+ local Ls = EgtGetFirstNameInGroup( vWall[i].Id, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ WALL.ERR = 15
+ WALL.MSG = 'Box undefined for beam ' .. vWall[i].Name
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ else
+ vWall[i].Box = b3Solid
+ end
+ end
+
+ -- Ne recupero la posizione
+ for i = 1, #vWall do
+ local PosX = EgtGetInfo( vWall[i].Id, 'POSX', 'd')
+ vWall[i].PosX = PosX + min( dExtraL, 1200)
+ if WD.USE_POSY then
+ local PosY = EgtGetInfo( vWall[i].Id, 'POSY', 'd')
+ vWall[i].PosY = max( PosY, 0)
+ else
+ vWall[i].PosY = 0
+ end
+ local PosZ = EgtGetInfo( vWall[i].Id, 'POSZ', 'd')
+ vWall[i].PosZ = PosZ + dExtraW / 2
+ end
+
+ -- Eseguo eventuali rotazioni e inversioni testa-coda
+ for i = 1, #vWall do
+ local b3Solid = vWall[i].Box
+ -- rotazione
+ local dRotAng = EgtGetInfo( vWall[i].Id, 'ROTATED', 'd')
+ if dRotAng then
+ if abs( dRotAng) > GEO.EPS_ANG_SMALL then
+ local ptRotCen = b3Solid:getCenter()
+ EgtRotate( vWall[i].Id, ptRotCen, X_AX(), dRotAng, GDB_RT.GLOB)
+ b3Solid:rotate( ptRotCen, X_AX(), dRotAng)
+ end
+ EgtSetInfo( vWall[i].Id, 'ROTATED_DONE', dRotAng)
+ end
+ -- inversione
+ local dInvAng = EgtGetInfo( vWall[i].Id, 'INVERTED', 'd')
+ if dInvAng then
+ if abs( dInvAng - 180) > GEO.EPS_ANG_SMALL and abs( dInvAng + 180) > GEO.EPS_ANG_SMALL then
+ local ptInvCen = b3Solid:getCenter()
+ EgtRotate( vWall[i].Id, ptInvCen, Z_AX(), dInvAng - 180, GDB_RT.GLOB)
+ b3Solid:rotate( ptInvCen, Z_AX(), dInvAng - 180)
+ end
+ EgtSetInfo( vWall[i].Id, 'INVERTED_DONE', dInvAng)
+ end
+ -- correzioni per rotazioni non centrate di produzioni TS3 (quasi sempre multipli di 90 deg)
+ local sType = EgtGetInfo( vWall[i].Id, 'TYPE', 's')
+ if not bProj and dRotAng and dInvAng and sType ~= 'LAYER' then
+ if abs( dInvAng - 0) < GEO.EPS_ANG_SMALL then
+ if abs( dRotAng - 180) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ elseif abs( dRotAng - 270) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ end
+ elseif abs( dInvAng - 90) < GEO.EPS_ANG_SMALL or abs( dInvAng + 270) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ if abs( dRotAng - 180) < GEO.EPS_ANG_SMALL or abs( dRotAng + 180) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ elseif abs( dRotAng - 270) < GEO.EPS_ANG_SMALL or abs( dRotAng + 90) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ end
+ elseif abs( dInvAng - 180) < GEO.EPS_ANG_SMALL or abs( dInvAng + 180) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ if abs( dRotAng - 0) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ elseif abs( dRotAng - 270) < GEO.EPS_ANG_SMALL or abs( dRotAng + 90) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ elseif abs( dRotAng - 90) < GEO.EPS_ANG_SMALL or abs( dRotAng + 270) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ end
+ elseif abs( dInvAng - 270) < GEO.EPS_ANG_SMALL or abs( dInvAng + 90) < GEO.EPS_ANG_SMALL then
+ if abs( dRotAng - 0) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ end
+ end
+ end
+ end
+
+ -- Ne verifico le dimensioni
+ local dRawH = vWall[1].Box:getDimZ() + vWall[1].PosY
+ local vWallErr = {}
+ for i = 2, #vWall do
+ local dDimH = vWall[i].Box:getDimZ() + vWall[i].PosY
+ if abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL then
+ table.insert( vWallErr, i)
+ end
+ end
+ if #vWallErr > 0 then
+ local sOut = 'Rimosse pareti con spessore diverso dalla prima :\n'
+ for i = #vWallErr, 1, -1 do
+ sOut = sOut .. vWall[vWallErr[i]].Name .. '\n'
+ table.remove( vWall, vWallErr[i])
+ end
+ WALL.ERR = 16
+ WALL.MSG = sOut
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ -- Verifico dimensioni massime grezzo
+ if dRawL > WD.MAX_LENGTH + 10 * GEO.EPS_SMALL or dRawW > WD.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > WD.MAX_HEIGHT + 10 * GEO.EPS_SMALL then
+ local sOut = 'Grezzo (' .. EgtNumToString( dRawL, 2) .. ' x ' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
+ 'oltre il limite della macchina ('..EgtNumToString( WD.MAX_LENGTH, 2)..' x '..EgtNumToString( WD.MAX_WIDTH, 2)..' x '..EgtNumToString( WD.MAX_HEIGHT, 2)..') '
+ WALL.ERR = 17
+ WALL.MSG = sOut
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ -- Verifico dimensioni minime del grezzo
+ if dRawL < WD.MIN_LENGTH - 10 * GEO.EPS_SMALL or dRawW < WD.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < WD.MIN_HEIGHT - 10 * GEO.EPS_SMALL then
+ local sOut = 'Grezzo (' .. EgtNumToString( dRawL, 2) .. ' x ' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
+ 'sotto il limite della macchina ('..EgtNumToString( WD.MIN_LENGTH, 2)..' x '..EgtNumToString( WD.MIN_WIDTH, 2)..' x '..EgtNumToString( WD.MIN_HEIGHT, 2)..')'
+ WALL.ERR = 17
+ WALL.MSG = sOut
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ -- Sistemo le pareti nel grezzo
+ local bPbOk, sPbErr = WE.ProcessWalls( dRawL, dRawW, dRawH, vWall)
+ if not bPbOk then
+ WALL.ERR = 18
+ WALL.MSG = sPbErr
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ -- Imposto Nome file CN
+ local _, sName, _ = EgtSplitPath( WALL.FILE)
+ EgtSetInfo( EgtGetCurrMachGroup(), 'NcName', sName .. '.cnc')
+
+ -- Abilito Vmill
+ EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
+
+ -- Lavoro le features
+ local bPfOk, Stats = WE.ProcessFeatures()
+ local sOutput = ''
+ for i = 1, #Stats do
+ local sMsg = Stats[i].Msg
+ sMsg = string.gsub( sMsg or '', '\n', ' ', 10)
+ sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
+ if Stats[i].Err == 0 then
+ WALL.ERR = 0
+ WALL.MSG = '---'
+ WALL.ROT = Stats[i].Rot or 0
+ WALL.CUTID = Stats[i].CutId
+ WALL.TASKID = Stats[i].TaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ elseif Stats[i].Err > 0 then
+ nErrCnt = nErrCnt + 1
+ sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, sMsg)
+ WALL.ERR = 19
+ WALL.MSG = sMsg
+ WALL.ROT = Stats[i].Rot or 0
+ WALL.CUTID = Stats[i].CutId
+ WALL.TASKID = Stats[i].TaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ elseif Stats[i].Err < 0 then
+ nWarnCnt = nWarnCnt + 1
+ sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, sMsg)
+ WALL.ERR = -19
+ WALL.MSG = sMsg
+ WALL.ROT = Stats[i].Rot or 0
+ WALL.CUTID = Stats[i].CutId
+ WALL.TASKID = Stats[i].TaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ end
+ end
+
+ -- Salvo il progetto
+ EgtSaveFile( sNgeFile)
+
+ -- Se non ci sono errori o modalità modifica, salvo il file originale
+ if nErrCnt == 0 or WALL.FLAG == 1 then
+ EgtCopyFile( WALL.FILE, sDir..sTitle..'.ori'..sExt)
+ end
+
+ -- Visualizzazione avvisi o errori
+ if #sOutput > 0 then EgtOutLog( sOutput) end
+ if nErrCnt > 0 then
+ PostErrView( 19, sOutput)
+ elseif nWarnCnt > 0 then
+ PostWarnView( 19, sOutput)
+ end
+
+-- Altrimenti carico il progetto salvato e dichiaro nessun errore
+else
+ EgtOutLog( ' +++ Loading Project already processed >>>')
+ -- Carico il progetto già fatto
+ EgtOpenFile( sNgeFile)
+ -- Dichiaro nessun errore
+ local nPartId = EgtGetFirstPart()
+ while nPartId do
+ local nCutId = EgtGetInfo( nPartId, 'CUTID')
+ if nCutId then
+ local LayerId = {}
+ LayerId[1] = EgtGetFirstNameInGroup( nPartId, 'Outline')
+ LayerId[2] = EgtGetFirstNameInGroup( nPartId, 'Processings')
+ for nInd = 1, #LayerId do
+ local nProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL)
+ while nProcId do
+ local bIsFea = EgtExistsInfo( nProcId, 'GRP') and EgtExistsInfo( nProcId, 'PRC')
+ local nTaskId = EgtGetInfo( nProcId, 'TASKID')
+ if bIsFea and nTaskId then
+ WALL.ERR = 0
+ WALL.MSG = '---'
+ WALL.ROT = 0
+ WALL.CUTID = nCutId
+ WALL.TASKID = nTaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ end
+ nProcId = EgtGetNext( nProcId)
+ end
+ end
+ end
+ nPartId = EgtGetNextPart( nPartId)
+ end
+ -- Aggiorno eventuali dati ausiliari
+ UpdateAuxData( sBtmFile)
+ -- Passo in modalità lavora
+ EgtSetCurrMachGroup( EgtGetLastMachGroup())
+ -- Se necessario eseguo aggiornamento con ricalcolo delle lavorazioni
+ if bToRecalc then
+ EgtOutLog( ' +++ Recalculating all dispositions and machinings >>>')
+ EgtImportSetup()
+ EgtApplyAllMachinings()
+ -- copia del file btl originale (per dichiarare progetto ricalcolato)
+ EgtCopyFile( WALL.FILE, sDir..sTitle..'.ori'..sExt)
+ end
+ -- Salvo il progetto
+ EgtSaveFile( sNgeFile)
+end
+
+-- *** Eseguo simulazione con verifica collisione in cieco ***
+if ( WALL.FLAG == 0 and ( bToProcess or bToRecalc)) or WALL.FLAG == 3 or WALL.FLAG == 4 then
+ EgtOutLog( ' +++ Simulating with collision check >>>')
+ -- verifico setup
+ local bSetUpOk, SetUpErrors = EgtVerifyCurrSetup()
+ if not bSetUpOk then
+ local sToolsList = ""
+ for ToolIndex = 1, #SetUpErrors do
+ sToolsList = sToolsList .. SetUpErrors[ToolIndex]
+ if ToolIndex ~= #SetUpErrors then
+ sToolsList = sToolsList .. ", "
+ end
+ end
+ WriteErrToLogFile( 19, 'Error in setup: tool/s ' .. sToolsList .. ' not found', 0, 0, 0)
+ return
+ end
+ -- lancio simulazione
+ local bSimOk, nErr, sErr = EgtSimulate()
+ if not bSimOk then
+ if nErr == MCH_SHE.INIT then
+ WALL.ERR = 19
+ WALL.MSG = 'Error starting simulation'
+ elseif nErr == MCH_SHE.COLLISION then
+ WALL.ERR = 22
+ WALL.MSG = 'Head-part collision'
+ elseif nErr == MCH_SHE.OUTSTROKE then
+ WALL.ERR = 23
+ WALL.MSG = 'Axis outstroke ' .. sErr
+ elseif nErr == MCH_SHE.SPECIAL then
+ WALL.ERR = 24
+ WALL.MSG = 'Special error ' .. sErr
+ else
+ WALL.ERR = 25
+ WALL.MSG = 'General failure (contact supplier)'
+ end
+ WALL.ROT = 0
+ WALL.CUTID = 0
+ WALL.TASKID = 0
+ local vItem = EgtSplitString( sErr, ';') or {}
+ for i = 1, #vItem do
+ vItem[i] = EgtTrim( vItem[i] or '')
+ if string.find( vItem[i], 'CUTID', 1, true) then
+ WALL.CUTID = EgtGetVal( vItem[i], 'CUTID', 'i') or 0
+ elseif string.find( vItem[i], 'TASKID', 1, true) then
+ WALL.TASKID = EgtGetVal( vItem[i], 'TASKID', 'i') or 0
+ end
+ end
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ return
+ end
+end
+
+-- *** Genero programma CN *** ( se richiesto)
+if WALL.FLAG == 0 or WALL.FLAG == 4 then
+ EgtOutLog( ' +++ Generating NC part program >>>')
+ local sInfo = 'EgtCAM5 - '
+ if EgtGetExeVersion then
+ sInfo = 'EgtCAM5 ver.' .. EgtGetExeVersion() .. ' - '
+ end
+ if not EgtGenerate( '', sInfo .. sNgeFile) then
+ WALL.ERR = 20
+ local _, sName, _ = EgtSplitPath( WALL.FILE)
+ WALL.MSG = 'Error generating NC part program : ' .. sName
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+end
+
+-- *** Eseguo stima tempi ***
+EgtOutLog( ' +++ Estimating T&L >>>')
+if not EgtEstimate( '', 'EgtCAM5 - ' .. sNgeFile) then
+ WALL.ERR = 21
+ local _, sName, _ = EgtSplitPath( WALL.FILE)
+ WALL.MSG = 'Error estimating production time : ' .. sName
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+end
+local Ttot = EgtGetInfo( EgtGetCurrMachGroup(), 'Ttot')
+local sTime = 'Total Time = ' .. EgtNumToString( Ttot, 1)
+EgtOutLog( sTime)
+
+-- Se modalità Cloud, importo la nuvola di punti
+if WALL.FLAG == 5 then
+ EgtOutLog( ' +++ Importing Point Cloud >>>')
+ -- Creo gruppo Cloud nel gruppo di lavorazione
+ local nMGrpId = EgtGetCurrMachGroup()
+ local nCloudId = EgtGetFirstNameInGroup( nMGrpId or GDB_ID.NULL, 'Cloud')
+ if nCloudId then
+ EgtEmptyGroup( nCloudId)
+ else
+ nCloudId = EgtGroup( nMGrpId)
+ EgtSetName( nCloudId, 'Cloud')
+ end
+ -- Recupero BBox della tavola
+ local b3Tab = EgtGetTableArea()
+ if not b3Tab or b3Tab:isEmpty() then
+ WALL.ERR = 22
+ WALL.MSG = 'Machine table not found'
+ return
+ end
+ -- Recupero i punti della nuvola
+ local hFile = io.open( sPntFile, 'r')
+ if not hFile then
+ WALL.ERR = 23
+ WALL.MSG = 'Missing point cloud file'
+ return
+ end
+ local vPoints = {}
+ local sLine = hFile:read( '*l')
+ while sLine do
+ local vCoord = EgtSplitString( sLine, ' ')
+ if vCoord and #vCoord >= 2 then
+ local dX = tonumber( vCoord[1]) + b3Tab:getMax():getX()
+ local dY = tonumber( vCoord[2]) + b3Tab:getMin():getY()
+ local dZ = b3Tab:getMax():getZ()
+ EgtOutLog( ' X='..EgtNumToString( dX, 3)..' Y='..EgtNumToString( dY, 3), 3)
+ table.insert( vPoints, { dX, dY, dZ})
+ end
+ sLine = hFile:read( '*l')
+ end
+ hFile:close()
+ -- Inserisco la curva di contorno della nuvola
+ local nClCrvId = EgtCurveCompoFromPoints( nCloudId, vPoints, GDB_RT.GLOB)
+ if not nClCrvId then
+ WALL.ERR = 24
+ WALL.MSG = 'Failed to create Point cloud Contour'
+ return
+ end
+ EgtCloseCurveCompo( nClCrvId)
+ EgtApproxCurve( nClCrvId, GDB_CA.LINES, 1.0)
+ EgtSetColor( nClCrvId, 'RED')
+end
+
+-- Se modifica o simula, imposto la vista ISO 3d opportuna
+if WALL.FLAG == 1 or WALL.FLAG == 2 then
+ local vView = { SCE_VD.ISO_NW, SCE_VD.ISO_SW, SCE_VD.ISO_NE, SCE_VD.ISO_SE}
+ local nV = min( max( WD.SIMUL_VIEW_DIR or 2, 1), 4)
+ EgtSetView( vView[nV], false)
+-- se cloud, imposto la vista TOP
+elseif WALL.FLAG == 5 then
+ EgtSetView( SCE_VD.TOP, false)
+end
+
+-- Completamento senza errori e avvisi
+if nWarnCnt == 0 then
+ WALL.ERR = 0
+ WALL.MSG = '---'
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+end
+
+-- Scrittura tempo totale stimato di lavorazione
+WriteTimeToLogFile( Ttot)
+
+EgtOutLog( ' +++ BatchProcess completed')
diff --git a/ProgettoRestylingWall/Wall/BatchProcessNew.lua b/ProgettoRestylingWall/Wall/BatchProcessNew.lua
new file mode 100644
index 0000000..ca59a6a
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/BatchProcessNew.lua
@@ -0,0 +1,713 @@
+-- BatchProcess.lua by Egaltech s.r.l. 2022/01/20
+-- Gestione calcolo batch disposizione e lavorazioni per Pareti
+-- 2021/01/15 Per nuova interfaccia Egt.
+-- 2021/11/10 Aggiunta modifica per gestione modifiche manuali come in Beam.
+-- 2022/01/06 Per CUTID/TASKID senza ToProcess si verificano anche eventuali Duplo.
+-- 2022/01/17 Eliminata assegnazione Feature ok se non calcolata.
+-- 2022/01/20 Si aggiorna il setup anche quando si creano le lavorazioni (MachGroup vecchio...).
+
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( true)
+
+-- Per test --**CB: inizializzazione**
+--WALL = {}
+--WALL.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
+--WALL.MACHINE = 'Essetre-90480019_MW'
+--WALL.FLAG = 3
+
+-- Log dati in input
+local sFlag = ''
+if WALL.FLAG == 0 then
+ sFlag = 'GENERATE'
+elseif WALL.FLAG == 1 then
+ sFlag = 'MODIFY'
+elseif WALL.FLAG == 2 then
+ sFlag = 'SIMULATE'
+elseif WALL.FLAG == 3 then
+ sFlag = 'CHECK'
+elseif WALL.FLAG == 4 then
+ sFlag = 'CHECK+GENERATE'
+elseif WALL.FLAG == 5 then
+ sFlag = 'CLOUD'
+elseif WALL.FLAG == 6 then
+ sFlag = 'CREATE_PANEL'
+else
+ sFlag = 'FLAG='..tostring( WALL.FLAG)
+end
+local sLog = 'BatchProcess : ' .. WALL.FILE .. ', ' .. WALL.MACHINE .. ', ' .. sFlag
+EgtOutLog( sLog)
+
+-- Cancello file di log specifico
+local sLogFile = EgtChangePathExtension( WALL.FILE, '.txt')
+EgtEraseFile( sLogFile)
+
+-- Funzioni per scrittura su file di log specifico
+local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
+ local hFile = io.open( sLogFile, 'a')
+ hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
+ hFile:write( sMsg .. '\n')
+ hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
+ hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
+ hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
+ hFile:close()
+end
+local function BWMessageId( nMsgId, sMsg, params)
+ if WALL.BW and nMsgId and nMsgId > 0 then
+ local sFinalMsg = '$$' .. nMsgId
+ for Index = 1, #params do
+ sFinalMsg = sFinalMsg .. ',' .. params[Index]
+ end
+ return sFinalMsg
+ else
+ return string.format( sMsg, table.unpack( params))
+ end
+end
+
+local function WriteTimeToLogFile( dTime)
+ local hFile = io.open( sLogFile, 'a')
+ hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
+ hFile:close()
+end
+
+-- Funzione per gestire visualizzazione dopo errore
+local function PostErrView( nErr, sMsg)
+ if nErr ~= 0 and ( WALL.FLAG == 1 or WALL.FLAG == 2 or WALL.FLAG == 5) then
+ EgtSetView( SCE_VD.ISO_SW, false)
+ EgtZoom( SCE_ZM.ALL)
+ EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
+ end
+end
+
+-- Funzione per gestire visualizzazione dopo warning
+local function PostWarnView( nWarn, sMsg)
+ if nWarn ~= 0 and ( WALL.FLAG == 1 or WALL.FLAG == 2 or WALL.FLAG == 5) then
+ EgtSetView( SCE_VD.ISO_SW, false)
+ EgtZoom( SCE_ZM.ALL)
+ EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
+ end
+end
+
+-- Funzione per aggiornare dati ausiliari
+local function UpdateAuxData( sAuxFile)
+ local bModif = false
+ -- Se definito LOAD90, aggiorno
+ local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
+ if sLoad90 ~= '' then
+ local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
+ EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
+ bModif = true
+ end
+ return bModif
+end
+
+-- Funzione di reset gruppo di lavoro in caso di impossibilità di inserire i pezzi
+local function ResetMachGroup( vWall)
+ for i = 1, #vWall do
+ EgtErase( vWall[i].Id)
+ end
+ EgtRemoveMachGroup( EgtGetCurrMachGroup() or GDB_ID.NULL)
+end
+
+-- **CB: INIZIO PROGRAMMA**
+
+-- Imposto direttorio libreria specializzata per Travi
+local sBaseDir = EgtGetSourceDir()
+EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua')
+
+-- Se necessario, impostazione della macchina corrente
+local sMachine = WALL.MACHINE
+if WALL.FLAG ~= 6 then
+ EgtResetCurrMachGroup()
+ if not EgtSetCurrMachine( sMachine) then
+ WALL.ERR = 11
+ WALL.MSG = 'Error selecting machine : ' .. sMachine
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+end
+
+-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Pareti
+local sMachDir = EgtGetCurrMachineDir()
+if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then
+ WALL.ERR = 12
+ WALL.MSG = 'Error not configured for walls machine : ' .. sMachine
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+end
+
+-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
+EgtRemoveBaseMachineDirFromPackagePath()
+EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua')
+
+-- Carico le librerie
+_G.package.loaded.WallExec = nil
+local WE = require( 'WallExec')
+local WL = require( 'WallLib')
+
+-- Carico i dati globali
+local WD = require( 'WallData')
+
+-- Dati del file
+local sDir, sTitle, sExt = EgtSplitPath( WALL.FILE)
+local sOriFile = sDir..sTitle..'.ori.bwe'
+local sNgeFile = sDir..sTitle..'.bwe'
+local sBtmFile = sDir..sTitle..'.btm'
+local sPntFile = sDir..sTitle..'.pnt'
+
+-- In generale va completamente riprocessato
+local bToProcess = true
+local bToRecalc = false
+-- se BTL, barra ed esiste già il corrispondente progetto Nge
+if EgtExistsFile( sOriFile) then
+ bToProcess = false
+ EgtCopyFile( sOriFile, sNgeFile)
+ -- se cambiata configurazione macchina da ultima elaborazione, devo aggiornare
+ if EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Wall\\TS3Data.lua') == -1 or
+ EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Tools\\Tools.data') == -1 or
+ EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\' .. sMachine ..'.mlde') == -1 then
+ bToRecalc = true
+ end
+end
+
+-- Inizializzo contatori errori e avvisi
+local nErrCnt = 0
+local nWarnCnt = 0
+
+-- Se da elaborare
+if bToProcess then
+ EgtOutLog( ' +++ Processing Parts >>>')
+
+ -- Flag di pannello da creare
+ local bCreatePanel
+ -- Dimensioni del pannello ed elenco pareti
+ local dPanelLen
+ local dPanelWidth
+ local vWall = {}
+ -- flag per Nesting da Btl
+ local bNestingFromBtl = false
+ local nRawOutlineId = GDB_ID.NULL
+
+ -- Se necessario, apro il file Bwe **cb: se ~= 'create panel "**
+ if WALL.FLAG ~= 6 then
+ if not EgtOpenFile( WALL.FILE) then
+ WALL.ERR = 13
+ WALL.MSG = 'Error opening BWE file : ' .. WALL.FILE
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+ -- faccio copia del file originale
+ EgtCopyFile( WALL.FILE, sOriFile)
+
+ -- Aggiorno eventuali dati ausiliari
+ --UpdateAuxData( sBtmFile)
+
+ -- Se già presente un gruppo di lavoro
+ if EgtGetFirstMachGroup() then
+ -- Barra già presente
+ bCreatePanel = false
+ -- Rendo corrente il gruppo di lavoro
+ EgtSetCurrMachGroup()
+ -- Area tavola
+ local b3Tab = EgtGetTableArea()
+ -- Calcolo posizione estremo TR della tavola rispetto a sua origine in BL
+ WD.OriTR = Point3d( b3Tab:getDimX(), b3Tab:getDimY(), 0)
+
+ -- altrimenti devo recuperare i pezzi per creare il pannello
+ else
+ -- Pannello da creare
+ bCreatePanel = true
+ -- Recupero l'elenco ordinato delle pareti
+ local nPartId = EgtGetFirstPart()
+ while nPartId do
+ table.insert( vWall, { Id = nPartId, Name = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
+ nPartId = EgtGetNextPart( nPartId)
+ end
+ if #vWall == 0 then
+ WALL.ERR = 14
+ WALL.MSG = 'Error no beams in the file : ' .. WALL.FILE
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ else
+ local sOut = ''
+ for i = 1, #vWall do
+ sOut = sOut .. vWall[i].Name .. ', '
+ end
+ sOut = sOut:sub( 1, -3)
+ EgtOutLog( 'Pareti trovate : ' .. sOut, 1)
+ end
+ -- variabile che indica se ci sono fori orizzontali lunghi
+ local bUseMinRawYForLongDrill = false
+ -- recupero libreria fori
+ _G.package.loaded.WProcessDrill = nil
+ local Drill = require( 'WProcessDrill')
+ -- Ne recupero le dimensioni
+ for i = 1, #vWall do
+ local Ls = EgtGetFirstNameInGroup( vWall[i].Id, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ WALL.ERR = 15
+ WALL.MSG = 'Box undefined for wall ' .. vWall[i].Name
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ else
+ vWall[i].Box = b3Solid
+ end
+ -- recupero lista feature e ciclo
+ local vPartProc = WE.CollectFeatures( vWall[i].Id)
+ for nInd = 1, #vPartProc do
+ if Drill.Identify( vPartProc[nInd]) and Drill.UseMinYForLongDrill(vPartProc[nInd]) then
+ bUseMinRawYForLongDrill = true
+ end
+ end
+ end
+ -- se parete con fori lunghi orizzontali
+ local dMinY = 0
+ if bUseMinRawYForLongDrill then
+ -- considero minima larghezza per permettere di farli
+ dMinY = ( WD.MINRAWY_HOR_DRILL or 2800)
+ end
+ -- Assegno dimensioni del pannello
+ dPanelLen = vWall[1].Box:getDimX() + 20
+ dPanelWidth = math.max( vWall[1].Box:getDimY() + 20, dMinY)
+ -- Assegno posizione prima ed unica parete
+ vWall[1].PosX = 10
+ vWall[1].PosZ = 10
+ vWall[1].Rot = 0
+ vWall[1].Flip = 0
+ end
+
+ -- Altrimenti, opero sul progetto corrente
+ else
+ -- Recupero l'identificativo del gruppo di lavoro corrente
+ local nMGrpId = EgtGetCurrMachGroup()
+ -- Pannello da creare
+ bCreatePanel = true
+ -- leggo se grezzo da nesting btl
+ bNestingFromBtl = EgtGetInfo( nMGrpId, 'BTLNESTING', 'b') or false
+ if bNestingFromBtl then
+ -- recupero superficie
+ nRawOutlineId = EgtGetInfo( nMGrpId, 'RAWOUTLINEID') or GDB_ID.NULL
+ if nRawOutlineId ~= GDB_ID.NULL then
+ local nRawPartId = EgtGetParent( EgtGetParent( nRawOutlineId))
+ EgtSetStatus( nRawPartId, GDB_ST.ON)
+ local b3RawSurf = EgtGetBBoxGlob( nRawPartId, GDB_BB.STANDARD)
+ EgtSetStatus( nRawPartId, GDB_ST.OFF)
+ --EgtSurfTmBBox( nRawOutlineId, b3RawSurf, false, GDB_RT.GLOB)
+ if b3RawSurf then
+ -- Lunghezza e larghezza del pannello
+ dPanelLen = b3RawSurf:getDimX()
+ dPanelWidth = b3RawSurf:getDimY()
+ end
+ end
+ else
+ -- Lunghezza e larghezza del pannello
+ dPanelLen = EgtGetInfo( nMGrpId, 'PANELLEN', 'd')
+ dPanelWidth = EgtGetInfo( nMGrpId, 'PANELWIDTH', 'd')
+ end
+ -- Recupero l'elenco ordinato delle pareti da inserire nel pannello
+ for i = 1, 100 do
+ local sKey = 'PART'..tostring( i)
+ local sVal = EgtGetInfo( nMGrpId, sKey)
+ local vVal = EgtSplitString( sVal or '')
+ if not vVal or #vVal < 5 then break end
+ local nPartId = tonumber( vVal[1])
+ local dPosX = tonumber( vVal[2])
+ local dPosY = tonumber( vVal[3])
+ local dRot = tonumber( vVal[4])
+ local dFlip = tonumber( vVal[5])
+ table.insert( vWall, { Id = nPartId, PosX = dPosX, PosZ = dPosY, Rot = dRot, Flip = dFlip, Name = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
+ end
+ if #vWall == 0 then
+ WALL.ERR = 14
+ WALL.MSG = 'Error : no walls in the project'
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ return
+ else
+ local sOut = ''
+ for i = 1, #vWall do
+ sOut = sOut .. vWall[i].Name .. ', '
+ end
+ sOut = sOut:sub( 1, -3)
+ EgtOutLog( 'Pareti trovate : ' .. sOut, 1)
+ end
+ -- Ne recupero le dimensioni
+ for i = 1, #vWall do
+ local Ls = EgtGetFirstNameInGroup( vWall[i].Id, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ WALL.ERR = 15
+ WALL.MSG = 'Box undefined for beam ' .. vWall[i].Name
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ return
+ else
+ vWall[i].Box = b3Solid
+ end
+ end
+ end
+
+ -- Se devo creare il pannello
+ if bCreatePanel then
+ -- Ne verifico le dimensioni
+ local dRawH = vWall[1].Box:getDimZ()
+ local vWallErr = {}
+ for i = 2, #vWall do
+ local dDimH = vWall[i].Box:getDimZ()
+ if abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL then
+ table.insert( vWallErr, i)
+ end
+ end
+ if #vWallErr > 0 then
+ local sOut = 'Rimosse pareti con spessore diverso dalla prima :\n'
+ for i = #vWallErr, 1, -1 do
+ sOut = sOut .. vWall[vWallErr[i]].Name .. '\n'
+ table.remove( vWall, vWallErr[i])
+ end
+ ResetMachGroup( vWall)
+ WALL.ERR = 16
+ WALL.MSG = sOut
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ local dRawL = dPanelLen
+ local dRawW = dPanelWidth
+
+ -- Verifico dimensioni massime grezzo
+ if dRawL > WD.MAX_LENGTH + 10 * GEO.EPS_SMALL or dRawW > WD.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > WD.MAX_HEIGHT + 10 * GEO.EPS_SMALL then
+ ResetMachGroup( vWall)
+ local sOut = BWMessageId( 1, 'Grezzo (%s x %s x %s) oltre il limite della macchina (%s x %s x %s)',
+ {EgtNumToString( dRawL, 2), EgtNumToString( dRawW, 2), EgtNumToString( dRawH, 2),
+ EgtNumToString( WD.MAX_LENGTH, 2), EgtNumToString( WD.MAX_WIDTH, 2), EgtNumToString( WD.MAX_HEIGHT, 2)})
+ WALL.ERR = 17
+ WALL.MSG = sOut
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ -- Verifico dimensioni minime del grezzo
+ if dRawL < WD.MIN_LENGTH - 10 * GEO.EPS_SMALL or dRawW < WD.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < WD.MIN_HEIGHT - 10 * GEO.EPS_SMALL then
+ ResetMachGroup( vWall)
+ local sOut = 'Grezzo (' .. EgtNumToString( dRawL, 2) .. ' x ' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
+ 'sotto il limite della macchina ('..EgtNumToString( WD.MIN_LENGTH, 2)..' x '..EgtNumToString( WD.MIN_WIDTH, 2)..' x '..EgtNumToString( WD.MIN_HEIGHT, 2)..')'
+ WALL.ERR = 17
+ WALL.MSG = sOut
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+
+ -- Sistemo le pareti nel grezzo
+ local bPbOk, sPbErr = WE.ProcessWalls( dRawL, dRawW, dRawH, vWall, WALL.FLAG == 6, true, nRawOutlineId)
+ if not bPbOk then
+ WALL.ERR = 18
+ WALL.MSG = sPbErr
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ else
+ -- Scrivo altezza grezzo nel gruppo di lavoro corrente
+ local nMGrpId = EgtGetCurrMachGroup()
+ EgtSetInfo( nMGrpId, 'PANELHEIGHT', dRawH)
+ end
+ -- altrimenti sistemo
+ else
+ -- recupero il grezzo
+ local nRawId = EgtGetFirstRawPart()
+ -- ciclo sui pezzi
+ local nPartId = EgtGetFirstPartInRawPart( nRawId)
+ while nPartId do
+ WL.CreateOrEmptyAddGroup( nPartId)
+ nPartId = EgtGetNextPartInRawPart( nPartId)
+ end
+ end
+
+ -- Se richiesta solo pannello, esco
+ if WALL.FLAG == 6 then
+ -- Completamento senza errori e avvisi
+ if nWarnCnt == 0 then
+ WALL.ERR = 0
+ WALL.MSG = '---'
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ end
+ EgtOutLog( ' +++ BatchProcess completed')
+ return
+ end
+
+ -- Imposto Nome file CN
+ local _, sName, _ = EgtSplitPath( WALL.FILE)
+ EgtSetInfo( EgtGetCurrMachGroup(), 'NcName', sName .. '.cnc')
+
+ -- Abilito Vmill
+ EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
+
+ -- Aggiorno Setup utensili
+ EgtImportSetup()
+
+ -- Lavoro le features
+ local bPfOk, Stats = WE.ProcessFeatures()
+ local sOutput = ''
+ for i = 1, #Stats do
+ local sMsg = Stats[i].Msg
+ sMsg = string.gsub( sMsg or '', '\n', ' ', 10)
+ sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
+ if Stats[i].Err == 0 then
+ WALL.ERR = 0
+ WALL.MSG = '---'
+ WALL.ROT = Stats[i].Rot or 0
+ WALL.CUTID = Stats[i].CutId
+ WALL.TASKID = Stats[i].TaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ elseif Stats[i].Err > 0 then
+ nErrCnt = nErrCnt + 1
+ sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, sMsg)
+ WALL.ERR = 19
+ WALL.MSG = sMsg
+ WALL.ROT = Stats[i].Rot or 0
+ WALL.CUTID = Stats[i].CutId
+ WALL.TASKID = Stats[i].TaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ elseif Stats[i].Err < 0 then
+ nWarnCnt = nWarnCnt + 1
+ sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, sMsg)
+ WALL.ERR = -19
+ WALL.MSG = sMsg
+ WALL.ROT = Stats[i].Rot or 0
+ WALL.CUTID = Stats[i].CutId
+ WALL.TASKID = Stats[i].TaskId
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ end
+ end
+
+ -- Salvo il progetto
+ EgtSaveFile( sNgeFile)
+ -- copio come originale (per dichiarare progetto ricalcolato)
+ EgtCopyFile( sNgeFile, sOriFile)
+
+ -- Visualizzazione avvisi o errori
+ if #sOutput > 0 then EgtOutLog( sOutput) end
+ if nErrCnt > 0 then
+ PostErrView( 19, sOutput)
+ elseif nWarnCnt > 0 then
+ PostWarnView( 19, sOutput)
+ end
+
+-- Altrimenti carico il progetto salvato e dichiaro nessun errore
+else
+ EgtOutLog( ' +++ Loading Project already processed >>>')
+ -- Carico il progetto già fatto
+ EgtOpenFile( sNgeFile)
+ -- Dichiaro nessun errore
+ --local nPartId = EgtGetFirstPart()
+ --while nPartId do
+ -- local vDup = EgtDuploList( nPartId)
+ -- if not vDup or #vDup == 0 then
+ -- vDup = { nPartId}
+ -- end
+ -- for i = 1, #vDup do
+ -- local nCutId = EgtGetInfo( vDup[i], 'CUTID', 'i')
+ -- if nCutId then
+ -- local LayerId = {}
+ -- LayerId[1] = EgtGetFirstNameInGroup( vDup[i], 'Outline')
+ -- LayerId[2] = EgtGetFirstNameInGroup( vDup[i], 'Processings')
+ -- for nInd = 1, #LayerId do
+ -- local nProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL)
+ -- while nProcId do
+ -- local bIsFea = EgtExistsInfo( nProcId, 'GRP') and EgtExistsInfo( nProcId, 'PRC')
+ -- local nTaskId = EgtGetInfo( nProcId, 'TASKID', 'i')
+ -- if bIsFea and nTaskId then
+ -- WALL.ERR = 0
+ -- WALL.MSG = '---'
+ -- WALL.ROT = 0
+ -- WALL.CUTID = nCutId
+ -- WALL.TASKID = nTaskId
+ -- WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ -- end
+ -- nProcId = EgtGetNext( nProcId)
+ -- end
+ -- end
+ -- end
+ -- end
+ -- nPartId = EgtGetNextPart( nPartId)
+ --end
+ -- Aggiorno eventuali dati ausiliari
+ --UpdateAuxData( sBtmFile)
+ -- Passo in modalità lavora
+ EgtSetCurrMachGroup( EgtGetLastMachGroup())
+ -- Se necessario eseguo aggiornamento con setup corrente e ricalcolo delle lavorazioni
+ if bToRecalc then
+ EgtOutLog( ' +++ Recalculating all dispositions and machinings >>>')
+ EgtImportSetup()
+ EgtApplyAllMachinings()
+ -- Salvo il progetto
+ EgtSaveFile( sNgeFile)
+ -- copio come originale (per dichiarare progetto ricalcolato)
+ EgtCopyFile( sNgeFile, sOriFile)
+ end
+end
+
+-- *** Eseguo simulazione con verifica collisione in cieco ***
+if ( WALL.FLAG == 0 and ( bToProcess or bToRecalc)) or WALL.FLAG == 3 or WALL.FLAG == 4 then
+ EgtOutLog( ' +++ Simulating with collision check >>>')
+ -- verifico setup
+ local bSetUpOk, SetUpErrors = EgtVerifyCurrSetup()
+ if not bSetUpOk then
+ local sToolsList = ""
+ for ToolIndex = 1, #SetUpErrors do
+ sToolsList = sToolsList .. SetUpErrors[ToolIndex]
+ if ToolIndex ~= #SetUpErrors then
+ sToolsList = sToolsList .. ", "
+ end
+ end
+ WriteErrToLogFile( 19, 'Error in setup: tool/s ' .. sToolsList .. ' not found', 0, 0, 0)
+ return
+ end
+ -- lancio simulazione
+ local bSimOk, nErr, sErr = EgtSimulate()
+ if not bSimOk then
+ if nErr == MCH_SHE.INIT then
+ WALL.ERR = 19
+ WALL.MSG = 'Error starting simulation'
+ elseif nErr == MCH_SHE.COLLISION then
+ WALL.ERR = 22
+ WALL.MSG = 'Head-part collision'
+ elseif nErr == MCH_SHE.OUTSTROKE then
+ WALL.ERR = 23
+ WALL.MSG = 'Axis outstroke ' .. sErr
+ elseif nErr == MCH_SHE.SPECIAL then
+ WALL.ERR = 24
+ WALL.MSG = 'Special error ' .. sErr
+ else
+ WALL.ERR = 25
+ WALL.MSG = 'General failure (contact supplier)'
+ end
+ WALL.ROT = 0
+ WALL.CUTID = 0
+ WALL.TASKID = 0
+ local vItem = EgtSplitString( sErr, ';') or {}
+ for i = 1, #vItem do
+ vItem[i] = EgtTrim( vItem[i] or '')
+ if string.find( vItem[i], 'CUTID', 1, true) then
+ WALL.CUTID = EgtGetVal( vItem[i], 'CUTID', 'i') or 0
+ elseif string.find( vItem[i], 'TASKID', 1, true) then
+ WALL.TASKID = EgtGetVal( vItem[i], 'TASKID', 'i') or 0
+ end
+ end
+ WriteErrToLogFile( WALL.ERR, WALL.MSG, WALL.ROT, WALL.CUTID, WALL.TASKID)
+ return
+ end
+end
+
+-- *** Genero programma CN *** ( se richiesto)
+if WALL.FLAG == 0 or WALL.FLAG == 4 then
+ EgtOutLog( ' +++ Generating NC part program >>>')
+ local sInfo = 'EgtCAM5 - '
+ if EgtGetExeVersion then
+ sInfo = 'EgtCAM5 ver.' .. EgtGetExeVersion() .. ' - '
+ end
+ if not EgtGenerate( '', sInfo .. sNgeFile) then
+ WALL.ERR = 20
+ local _, sName, _ = EgtSplitPath( WALL.FILE)
+ WALL.MSG = 'Error generating NC part program : ' .. sName
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+ end
+end
+
+-- *** Eseguo stima tempi ***
+EgtOutLog( ' +++ Estimating T&L >>>')
+if not EgtEstimate( '', 'EgtCAM5 - ' .. sNgeFile) then
+ WALL.ERR = 21
+ local _, sName, _ = EgtSplitPath( WALL.FILE)
+ WALL.MSG = 'Error estimating production time : ' .. sName
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+ PostErrView( WALL.ERR, WALL.MSG)
+ return
+end
+local Ttot = EgtGetInfo( EgtGetCurrMachGroup(), 'Ttot', 'd')
+local sTime = 'Total Time = ' .. EgtNumToString( Ttot, 1)
+EgtOutLog( sTime)
+
+-- Se modalità Cloud, importo la nuvola di punti
+if WALL.FLAG == 5 then
+ EgtOutLog( ' +++ Importing Point Cloud >>>')
+ -- Creo gruppo Cloud nel gruppo di lavorazione
+ local nMGrpId = EgtGetCurrMachGroup()
+ local nCloudId = EgtGetFirstNameInGroup( nMGrpId or GDB_ID.NULL, 'Cloud')
+ if nCloudId then
+ EgtEmptyGroup( nCloudId)
+ else
+ nCloudId = EgtGroup( nMGrpId)
+ EgtSetName( nCloudId, 'Cloud')
+ end
+ -- Recupero BBox della tavola
+ local b3Tab = EgtGetTableArea()
+ if not b3Tab or b3Tab:isEmpty() then
+ WALL.ERR = 22
+ WALL.MSG = 'Machine table not found'
+ return
+ end
+ -- Recupero i punti della nuvola
+ local hFile = io.open( sPntFile, 'r')
+ if not hFile then
+ WALL.ERR = 23
+ WALL.MSG = 'Missing point cloud file'
+ return
+ end
+ local vPoints = {}
+ local sLine = hFile:read( '*l')
+ while sLine do
+ local vCoord = EgtSplitString( sLine, ' ')
+ if vCoord and #vCoord >= 2 then
+ local dX = tonumber( vCoord[1]) + b3Tab:getMax():getX()
+ local dY = tonumber( vCoord[2]) + b3Tab:getMin():getY()
+ local dZ = b3Tab:getMax():getZ()
+ EgtOutLog( ' X='..EgtNumToString( dX, 3)..' Y='..EgtNumToString( dY, 3), 3)
+ table.insert( vPoints, { dX, dY, dZ})
+ end
+ sLine = hFile:read( '*l')
+ end
+ hFile:close()
+ -- Inserisco la curva di contorno della nuvola
+ local nClCrvId = EgtCurveCompoFromPoints( nCloudId, vPoints, GDB_RT.GLOB)
+ if not nClCrvId then
+ WALL.ERR = 24
+ WALL.MSG = 'Failed to create Point cloud Contour'
+ return
+ end
+ EgtCloseCurveCompo( nClCrvId)
+ EgtApproxCurve( nClCrvId, GDB_CA.LINES, 1.0)
+ EgtSetColor( nClCrvId, 'RED')
+end
+
+-- Se modifica o simula, imposto la vista ISO 3d opportuna
+if WALL.FLAG == 1 or WALL.FLAG == 2 then
+ local vView = { SCE_VD.ISO_NW, SCE_VD.ISO_SW, SCE_VD.ISO_NE, SCE_VD.ISO_SE}
+ local nV = min( max( WD.SIMUL_VIEW_DIR or 2, 1), 4)
+ EgtSetView( vView[nV], false)
+-- se cloud, imposto la vista TOP
+elseif WALL.FLAG == 5 then
+ EgtSetView( SCE_VD.TOP, false)
+end
+
+-- Completamento senza errori e avvisi
+if nWarnCnt == 0 then
+ WALL.ERR = 0
+ WALL.MSG = '---'
+ WriteErrToLogFile( WALL.ERR, WALL.MSG)
+end
+
+-- Scrittura tempo totale stimato di lavorazione
+WriteTimeToLogFile( Ttot)
+
+EgtOutLog( ' +++ BatchProcess completed')
diff --git a/ProgettoRestylingWall/Wall/GetWallData.lua b/ProgettoRestylingWall/Wall/GetWallData.lua
new file mode 100644
index 0000000..6c62842
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/GetWallData.lua
@@ -0,0 +1,48 @@
+-- GetWallData.lua by Egaltech s.r.l. 2021/11/22
+-- Recupero dati da file WallData.lua di macchina
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+-- Per test
+--GWD = {}
+--GWD.MACHINE = 'Essetre-90480019_MW'
+
+local sLog = 'GetWallData : ' .. GWD.MACHINE
+EgtOutLog( sLog)
+
+-- Imposto direttorio libreria specializzata per Travi
+local sBaseDir = EgtGetSourceDir()
+EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua')
+
+-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Pareti
+local sMachDir = EgtGetCurrMachineDir()
+if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then
+ GWD.ERR = 12
+ GWD.MSG = 'Error not configured for walls machine : ' .. GWD.MACHINE
+ WriteErrToLogFile( GWD.ERR, GWD.MSG)
+ PostErrView( GWD.ERR, GWD.MSG)
+ return
+end
+
+-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
+EgtRemoveBaseMachineDirFromPackagePath()
+EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua')
+
+-- Carico i dati globali
+local WD = require( 'WallData')
+
+-- Assegno valori di interesse
+GWD.SIMUL_VIEW_DIR = WD.SIMUL_VIEW_DIR
+GWD.ORIG_CORNER = WD.ORIG_CORNER
+GWD.NESTING_CORNER = WD.NESTING_CORNER
+GWD.HOR_DRILL_DIAM = WD.HOR_DRILL_DIAM
+GWD.MIN_HEIGHT = WD.MIN_HEIGHT
+GWD.MAX_HEIGHT = WD.MAX_HEIGHT
+
+-- Tutto ok
+GWD.ERR = 0
+
+EgtOutLog( ' +++ GetWallData completed')
diff --git a/ProgettoRestylingWall/Wall/Images/Overturn.png b/ProgettoRestylingWall/Wall/Images/Overturn.png
new file mode 100644
index 0000000..9854743
Binary files /dev/null and b/ProgettoRestylingWall/Wall/Images/Overturn.png differ
diff --git a/ProgettoRestylingWall/Wall/Images/Process.png b/ProgettoRestylingWall/Wall/Images/Process.png
new file mode 100644
index 0000000..e51b0b9
Binary files /dev/null and b/ProgettoRestylingWall/Wall/Images/Process.png differ
diff --git a/ProgettoRestylingWall/Wall/Images/Rotate.png b/ProgettoRestylingWall/Wall/Images/Rotate.png
new file mode 100644
index 0000000..fc5b749
Binary files /dev/null and b/ProgettoRestylingWall/Wall/Images/Rotate.png differ
diff --git a/ProgettoRestylingWall/Wall/Images/WallMachinings.png b/ProgettoRestylingWall/Wall/Images/WallMachinings.png
new file mode 100644
index 0000000..e88dd70
Binary files /dev/null and b/ProgettoRestylingWall/Wall/Images/WallMachinings.png differ
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WMachiningLib.lua b/ProgettoRestylingWall/Wall/LuaLibs/WMachiningLib.lua
new file mode 100644
index 0000000..efc4d5c
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WMachiningLib.lua
@@ -0,0 +1,181 @@
+-- MachiningLib.lua by Egaltech s.r.l. 2022/01/12
+-- Libreria ricerca lavorazioni per Pareti
+
+-- Tabella per definizione modulo
+local WMachiningLib = {}
+
+-- Include
+require( 'EgtBase')
+
+EgtOutLog( ' WMachiningLib started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local Cuttings = require( 'CutData')
+local Millings = require( 'MillingData')
+local Pocketings = require( 'PocketingData')
+local Sawings = require( 'SawingData')
+local Drillings = require( 'DrillData')
+local Surfacings
+if EgtExistsFile( EgtGetCurrMachineDir() .. '\\Wall\\SurfacingData.lua') then
+ Surfacings = require( 'SurfacingData')
+end
+
+---------------------------------------------------------------------
+local function SetCurrMachiningAndTool( sMachName)
+ if not EgtMdbSetCurrMachining( sMachName) then return false end
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ local sTool = EgtTdbGetToolFromUUID( sTuuid)
+ if not sTool then return false end
+ if not EgtTdbSetCurrTool( sTool) then return false end
+ return EgtTdbGetCurrToolParam( MCH_TP.ACTIVE)
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindCutting( sType, dDepth, nTool_ID)
+ for i = 1, #Cuttings do
+ local Cutting = Cuttings[i]
+ if Cutting.On and Cutting.Type == sType and SetCurrMachiningAndTool( Cutting.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ local dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0
+ local dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or 0
+ local dSawMaxDepth = EgtTdbGetCurrToolMaxDepth() or 0
+ local nMyTool_ID = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'Tool_ID', 'i')
+ if nMchType == MCH_MY.SAWING and
+ ( not dDepth or dSawMaxDepth > dDepth - 10 * GEO.EPS_SMALL) and
+ ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) then
+ return Cutting.Name, dSawDiam, dSawThick, dSawMaxDepth
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindMilling( sType, dDepth, sTuuid, nTool_ID, dMaxDiam, dMaxMat, bTipFeed, dMinSideElev)
+ for i = 1, #Millings do
+ local Milling = Millings[i]
+ if Milling.On and Milling.Type == sType and SetCurrMachiningAndTool( Milling.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ local sMyTuuid = EgtGetMachiningParam( MCH_MP.TUUID)
+ local dTMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
+ local dTMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, dTMaxMat, EgtTdbGetCurrToolMaxDepth())
+ local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
+ local dTDiamTh = EgtTdbGetCurrToolThDiam() or 0
+ local dTTipFeed = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED)
+ local dTMaxDepthOnSide = min( EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or 0, 0.5 * ( dTDiam - dTDiamTh))
+ local nMyTool_ID = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'Tool_ID', 'i')
+ if nMchType == MCH_MY.MILLING and
+ ( not sTuuid or sTuuid == sMyTuuid) and
+ ( not dDepth or dTMaxDepth > dDepth - GEO.EPS_SMALL) and
+ ( not dMaxDiam or dTDiam < dMaxDiam + GEO.EPS_SMALL) and
+ ( not dMaxMat or dTMaxMat < dMaxMat + GEO.EPS_SMALL) and
+ ( not bTipFeed or dTTipFeed > 1) and
+ ( not dMinSideElev or dTMaxDepthOnSide > dMinSideElev - GEO.EPS_SMALL) and
+ ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) then
+ return Milling.Name, dTMaxDepth, dTMaxMat, dTDiam
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindNailing( nType)
+ for i = 1, #Millings do
+ local Milling = Millings[i]
+ if Milling.On and Milling.Type == 'Nailing' and SetCurrMachiningAndTool( Milling.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ local sTName = EgtTdbGetCurrToolParam( MCH_TP.NAME)
+ if nMchType == MCH_MY.MILLING and
+ sTName == tostring( nType) then
+ return Milling.Name
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindPocketing( sType, dMaxDiam, dDepth, nTool_ID)
+ for i = 1, #Pocketings do
+ local Pocketing = Pocketings[i]
+ if Pocketing.On and Pocketing.Type == sType and SetCurrMachiningAndTool( Pocketing.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
+ local dTMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth())
+ local nMyTool_ID = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'Tool_ID', 'i')
+ if nMchType == MCH_MY.POCKETING and
+ ( not dMaxDiam or dTDiam < dMaxDiam + GEO.EPS_SMALL) and
+ ( not dDepth or dTMaxDepth > dDepth - GEO.EPS_SMALL) and
+ ( not nTool_ID or nTool_ID == 0 or nTool_ID == nMyTool_ID) then
+ return Pocketing.Name, dTDiam, dTMaxDepth
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindSawing( sType)
+ for i = 1, #Sawings do
+ local Sawing = Sawings[i]
+ if Sawing.On and Sawing.Type == sType and SetCurrMachiningAndTool( Sawing.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ if nMchType == MCH_MY.MORTISING then
+ return Sawing.Name
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindDrilling( dDiam, dDepth, sHead, bOnlyPockets)
+ if bOnlyPockets == nil or not bOnlyPockets then
+ -- ricerca sulle forature, dal diametro maggiore al minore
+ for i = #Drillings, 1, -1 do
+ local Drilling = Drillings[i]
+ if Drilling.On and Drilling.Type == 'Drill' and SetCurrMachiningAndTool( Drilling.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
+ local dTMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
+ local sMyHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
+ if nMchType == MCH_MY.DRILLING and
+ dTDiam < dDiam + 10 * GEO.EPS_SMALL and dTDiam > dDiam - WD.DRILL_TOL - 10 * GEO.EPS_SMALL and
+ ( not dDepth or dTMaxMat > dDepth - GEO.EPS_SMALL) and
+ (( not sHead and sMyHead ~= 'H5' and sMyHead ~= 'H6') or sHead == sMyHead) then
+ return Drilling.Name, Drilling.Type, dTMaxMat
+ end
+ end
+ end
+ end
+ -- ricerca sulle svuotature, dal diametro maggiore al minore
+ for i = #Drillings, 1, -1 do
+ local Drilling = Drillings[i]
+ if Drilling.On and Drilling.Type == 'Pocket' and SetCurrMachiningAndTool( Drilling.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
+ local dTMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth())
+ local sMyHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
+ if nMchType == MCH_MY.POCKETING and
+ dTDiam < dDiam - 10 * GEO.EPS_SMALL and
+ ( not dDepth or dTMaxDepth > dDepth - GEO.EPS_SMALL) and
+ ( ( not sHead and sMyHead ~= 'H5' and sMyHead ~= 'H6') or sHead == sMyHead) then
+ return Drilling.Name, Drilling.Type, dTMaxDepth
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+function WMachiningLib.FindSurfacing( sType)
+ if not Surfacings then return end
+ for i = 1, #Surfacings do
+ local Surfacing = Surfacings[i]
+ if Surfacing.On and Surfacing.Type == sType and SetCurrMachiningAndTool( Surfacing.Name) then
+ local nMchType = EgtMdbGetCurrMachiningParam( MCH_MP.TYPE)
+ if nMchType == MCH_MY.SURFFINISHING then
+ return Surfacing.Name
+ end
+ end
+ end
+end
+
+-------------------------------------------------------------------------------------------------------------
+return WMachiningLib
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessCut.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessCut.lua
new file mode 100644
index 0000000..3523ea7
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessCut.lua
@@ -0,0 +1,74 @@
+-- WProcessCut.lua by Egaltech s.r.l. 2020/11/13
+-- Gestione calcolo taglio di testa o longitudinale per Pareti
+
+-- Tabella per definizione modulo
+local WPC = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+local FreeContour = require( 'WProcessFreeContour')
+
+EgtOutLog( ' WProcessCut started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPC.Identify( Proc)
+ return ( (( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10) or
+ (( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 10))
+end
+
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPC.Classify( Proc, b3Raw)
+ -- verifico abbia una sola faccia
+ if Proc.Fct ~= 1 then return false end
+ -- controllo la normale
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ if vtN:getZ() < - 0.5 then return false end
+ return true
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPC.FlipClassify( Proc)
+ -- verifico abbia una sola faccia
+ if Proc.Fct ~= 1 then return 0, 0 end
+ -- controllo la normale
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ local vtNZ = vtN:getZ()
+ if vtNZ > - GEO.EPS_SMALL then
+ nFlip0 = 100
+ elseif vtNZ < -0.5 then
+ nFlip0 = 0
+ else
+ nFlip0 = 50
+ end
+
+ if - vtNZ > - GEO.EPS_SMALL then
+ nFlip1 = 100
+ elseif - vtNZ < -0.5 then
+ nFlip1 = 0
+ else
+ nFlip1 = 50
+ end
+
+ --nFlip0 = EgtIf( vtN:getZ() < -0.5, 0, 100)
+ --nFlip1 = EgtIf( - vtN:getZ() < -0.5, 0, 100)
+ return nFlip0, nFlip1
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPC.Make( Proc, nRawId, b3Raw)
+ return FreeContour.Make( Proc, nRawId, b3Raw)
+end
+
+---------------------------------------------------------------------
+return WPC
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessDoubleCut.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessDoubleCut.lua
new file mode 100644
index 0000000..74a0bc4
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessDoubleCut.lua
@@ -0,0 +1,65 @@
+-- WProcessDoubleCut.lua by Egaltech s.r.l. 2021/04/28
+-- Gestione calcolo doppi tagli di lama per Pareti
+
+-- Tabella per definizione modulo
+local WPDC = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+local Cut = require( 'WProcessCut')
+local LapJoint = require( 'WProcessLapJoint')
+
+EgtOutLog( ' WProcessDoubleCut started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local ML = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPDC.Identify( Proc)
+ return ( (( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 11) or
+ ( Proc.Grp == 0 and Proc.Prc == 12))
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPDC.Classify( Proc, b3Raw)
+ -- se una faccia, uso la classificazione dei tagli singoli
+ if Proc.Fct == 1 then return Cut.Classify( Proc, b3Raw) end
+ -- se più di due facce non si fa
+ if Proc.Fct > 2 then return false end
+ -- dati delle facce
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+ -- verifico se è lavorabile da sopra o di fianco
+ return ( vtN[1]:getZ() >= - 0.01 or vtN[2]:getZ() >= - 0.01)
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPDC.FlipClassify( Proc)
+
+ -- se una faccia, uso la classificazione dei tagli singoli
+ if Proc.Fct == 1 then return Cut.FlipClassify( Proc) end
+ -- se due facce, uso la classificazione del lap joint a due facce
+ if Proc.Fct == 2 then return LapJoint.FlipClassify( Proc) end
+ -- se più di due facce non si fa
+ if Proc.Fct > 2 then return 0, 0 end
+
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPDC.Make( Proc, nRawId, b3Raw)
+ -- se singola faccia, passo a quella lavorazione
+ if Proc.Fct == 1 then return Cut.Make( Proc, nRawId, b3Raw) end
+ -- altrimenti due facce e passo alla LapJoint
+ return LapJoint.Make( Proc, nRawId, b3Raw)
+end
+
+---------------------------------------------------------------------
+return WPDC
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessDrill.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessDrill.lua
new file mode 100644
index 0000000..79e2295
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessDrill.lua
@@ -0,0 +1,544 @@
+-- WProcessDrill.lua by Egaltech s.r.l. 2022/03/08
+-- Gestione calcolo forature per Pareti
+-- 2021/08/29 DS Se foratura di fianco setto flag per farla dopo i tagli.
+-- 2021/12/04 DS Modifiche per forature speciali lungo Y.
+-- 2022/01/12 DS Se con fresatura richiedo che l'utensile possa lavorare di testa.
+-- 2022/01/19 DS Forature orizzontali lunghe con nome LhDrill_.
+-- 2022/01/20 DS Aggiunta gestione Q01 (flag forzatura solo contornatura).
+-- 2022/01/29 DS Corretta gestione ingombro portautensili per fori inclinati da sopra.
+-- 2022/02/22 ES Aggiunta gestione prefori.
+-- 2022/03/08 DS Vanno accettati fori orizzontali sul bordo anche senza foratori orizzontali speciali.
+
+-- Tabella per definizione modulo
+local WPD = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+
+EgtOutLog( ' WProcessDrill started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+-- Parametri Q
+local sContourOnly = 'Q01' -- 0=no, 1=si
+
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPD.Identify( Proc)
+ return ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 40)
+end
+
+---------------------------------------------------------------------
+-- Recupero dati foro e adattamento se speciale
+function WPD.GetData( Proc)
+ -- verifico se foro da adattare
+ if EgtExistsInfo( Proc.Id, 'DiamUser') then
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if AuxId and EgtGetType( AuxId) == GDB_TY.CRV_ARC and WD.USER_HOLE_DIAM and WD.USER_HOLE_DIAM > 1 then
+ EgtModifyArcRadius( AuxId, WD.USER_HOLE_DIAM / 2)
+ EgtSetInfo( Proc.Id, 'P12', WD.USER_HOLE_DIAM)
+ end
+ end
+ -- recupero diametro
+ local dDiam = EgtGetInfo( Proc.Id, 'P12', 'd') or 0
+ -- recupero faccia di entrata e uscita
+ local nFcs = EgtGetInfo( Proc.Id, 'FCS', 'i') or 0
+ local nFce = EgtGetInfo( Proc.Id, 'FCE', 'i') or 0
+ return dDiam, nFcs, nFce
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPD.Classify( Proc, b3Raw)
+
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ return false
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local ptCen = EgtCP( AuxId, GDB_RT.GLOB)
+ local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0)
+ -- se inizia o finisce sulla faccia sopra
+ if ptCen:getZ() > b3Raw:getMax():getZ() - dDiam / 2 or ( bOpen and ptCen:getZ() - vtExtr:getZ() * dLen > b3Raw:getMax():getZ() - dDiam / 2) then
+ -- è lavorabile se non troppo inclinato
+ return ( abs( vtExtr:getZ()) >= WD.DRILL_VZ_MIN)
+ end
+ -- se con direzione asse Y e macchina con foratore orizzontale del giusto diametro
+ if WD.HOR_DRILL_DIAM and abs( dDiam - WD.HOR_DRILL_DIAM) < WD.DRILL_TOL and AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) then
+ return true
+ end
+ -- se foro orizzontale, verifico sia sul bordo del grezzo
+ local b3RedRaw = BBox3d( b3Raw)
+ b3RedRaw:expand( -20)
+ if ( WD.HOR_DRILL_5AX or WD.HOR_DRILL_5AX == nil) and vtExtr:getZ() > -0.05 and not EnclosesPointXY( b3RedRaw, ptCen) then
+ return true
+ end
+ -- altrimenti non lavorabile
+ return false
+end
+
+---------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPD.FlipClassify( Proc, b3Part)
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ return false
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local ptCen = EgtCP( AuxId, GDB_RT.GLOB)
+ -- se foro cieco
+ if Proc.Fcs == 0 or Proc.Fce == 0 then
+ -- se normale positiva
+ local dVtExtrZ = vtExtr:getZ()
+ -- verifico se è lavorabile da sopra
+ local nFlip0 = EgtIf( dVtExtrZ >= WD.DRILL_VZ_MIN, 100, 0)
+ -- verifico se e' lavorabile da flipped: cambio segno al versore
+ local nFlip1 = EgtIf( -dVtExtrZ >= WD.DRILL_VZ_MIN, 100, 0)
+ return nFlip0, nFlip1
+ end
+ -- altrimenti
+ return 0, 0
+end
+
+---------------------------------------------------------------------
+-- Classificazione della rotazione della feature per nesting
+-- return nRot0, nRot90, nRot180, nRot270
+function WPD.RotateClassify( Proc)
+
+ local nRot0 = -1
+ local nRot90 = -1
+ local nRot180 = -1
+ local nRot270 = -1
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ return false
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local ptCen = EgtCP( AuxId, GDB_RT.GLOB)
+ -- se foro orizzontale con punta lunga
+ if dDiam <= WD.HOR_DRILL_DIAM + WD.DRILL_TOL and dDiam >= WD.HOR_DRILL_DIAM - WD.DRILL_TOL and vtExtr:getZ() > -0.1 and vtExtr:getZ() < 0.1 then
+ -- se orientato perpendicolare ad X
+ if AreSameOrOppositeVectorApprox( vtExtr, X_AX()) then
+ nRot0 = 0
+ nRot90 = 100
+ nRot180 = 0
+ nRot270 = 100
+ return nRot0, nRot90, nRot180, nRot270
+ elseif AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) then
+ nRot0 = 100
+ nRot90 = 0
+ nRot180 = 100
+ nRot270 = 0
+ return nRot0, nRot90, nRot180, nRot270
+ end
+ end
+end
+
+---------------------------------------------------------------------
+local function IsHorizLongDrill( Proc)
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ return false
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ return dDiam <= WD.HOR_DRILL_DIAM + WD.DRILL_TOL and dDiam >= WD.HOR_DRILL_DIAM - WD.DRILL_TOL and vtExtr:getZ() > -0.1 and vtExtr:getZ() < 0.1
+end
+
+---------------------------------------------------------------------
+function WPD.UseMinYForLongDrill( Proc)
+ if IsHorizLongDrill( Proc) then
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ return false
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local ptCen = EgtCP( AuxId, GDB_RT.GLOB)
+ local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0)
+ -- se foro lungo orizzontale e piu' lungo della punta o orientato in Y-
+ if dDiam <= WD.HOR_DRILL_DIAM + WD.DRILL_TOL and dDiam >= WD.HOR_DRILL_DIAM - WD.DRILL_TOL and vtExtr:getZ() > -0.1 and vtExtr:getZ() < 0.1 and
+ ( (bOpen and dLen > WD.HOR_DRILL_LEN) or ( not bOpen and vtExtr:getY() < 0)) then
+ return true
+ end
+ end
+ return false
+end
+
+---------------------------------------------------------------------
+-- Verifica se da lavorare in due metà
+function WPD.Split( Proc, b3Raw)
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ return false
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0)
+ -- verifico se foro orizzontale in Y da lavorare in due metà
+ if WD.HOR_DRILL_Y_SPLIT and bOpen and AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) and
+ Proc.Box:getMin():getY() < WD.HOR_DRILL_Y_SPLIT - 10 and Proc.Box:getMax():getY() > WD.HOR_DRILL_Y_SPLIT + 10 then
+ return true
+ else
+ return false
+ end
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPD.Make( Proc, nRawId, b3Raw)
+ -- recupero e verifico l'entità foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then
+ local sErr = 'Error : missing drill geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati del foro
+ local dDiam = 2 * EgtArcRadius( AuxId)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local ptCen = EgtCP( AuxId, GDB_RT.GLOB)
+ local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0)
+ -- verifico che il foro non sia fattibile solo da sotto
+ local bToInvert = ( vtExtr:getZ() < -0.1)
+ if bToInvert and ( not bOpen or Proc.Flg ~= 1) then
+ local sErr = 'Error : drilling from bottom impossible'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se foro da fare dall'altra parte forzo inversione
+ if Proc.Flg == -2 then bToInvert = true end
+ -- se foro chiuso sulla partenza forzo inversione
+ if Proc.Fcs == 0 then bToInvert = true end
+ -- se richiesta inversione, inverto versore di riferimento
+ if bToInvert then vtExtr = - vtExtr end
+ -- recupero la lavorazione (foratura/svuotatura)
+ local sHead
+ if WD.HOR_DRILL_Y_SPLIT and AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) then
+ local dExtrY = vtExtr:getY()
+ if not bOpen or abs( Proc.Flg) == 2 then
+ sHead = EgtIf( dExtrY > 0, 'H5', 'H6')
+ else
+ if Proc.Box:getMax():getY() > WD.HOR_DRILL_Y_SPLIT + 10 then
+ sHead = 'H5'
+ if vtExtr:getY() < 0 then bToInvert = true end
+ else
+ sHead = 'H6'
+ if vtExtr:getY() > 0 then bToInvert = true end
+ end
+ end
+ end
+ local sDrilling, nType = WM.FindDrilling( dDiam, dLen, sHead)
+ if not sDrilling then
+ sDrilling, nType = WM.FindDrilling( dDiam, nil, sHead)
+ end
+ if sHead and not sDrilling then
+ sDrilling, nType = WM.FindDrilling( dDiam, dLen)
+ if not sDrilling then
+ sDrilling, nType = WM.FindDrilling( dDiam)
+ end
+ if sDrilling then sHead = '' end
+ end
+ local bAngledContourDrill = false
+ local nAngledContourDrillId = GDB_ID.NULL
+ local dReduceDepth = 0
+ -- se trovata svuotatura, verifico se richiesta invece contornatura
+ if nType == 'Pocket' then
+ -- recupero eventuale flag per fare sola contornatura
+ local nContourOnly = ( EgtGetInfo( Proc.Id, sContourOnly, 'i') or 0)
+ if nContourOnly == 1 then
+ -- imposto riduzione profondita' per evitare distacco pezzo interno
+ dReduceDepth = 5
+ -- se inclinato e passante
+ if abs( vtExtr:getZ()) >= WD.DRILL_VZ_MIN and abs( vtExtr:getZ()) < 0.999 and Proc.Fcs > 0 and Proc.Fce > 0 then
+ -- gruppo ausiliario per preforo
+ local nAddGrpId = WL.GetAddGroup( Proc.PartId)
+ -- ricavo contorno inferiore della superficie
+ local nAngledCircleId, nAngledCircleCnt = EgtExtractSurfTmLoops( Proc.Id, nAddGrpId)
+ local dMinZ = 10000
+ local nMinCircleId = GDB_ID.NULL
+ for Circleindex = 1, nAngledCircleCnt do
+ local b3Circle = EgtGetBBoxGlob( nAngledCircleId + Circleindex -1, GDB_BB.EXACT)
+ if b3Circle:getMin():getZ() < dMinZ then
+ nMinCircleId = nAngledCircleId + Circleindex -1
+ end
+ end
+ -- estrudo
+ EgtModifyCurveExtrusion( nMinCircleId, vtExtr, GDB_RT.GLOB)
+ EgtModifyCurveThickness( nMinCircleId, dLen)
+ bAngledContourDrill = true
+ nAngledContourDrillId = nMinCircleId
+ end
+ sDrilling = WM.FindMilling( 'FreeContour', dLen, nil, nil, nil, nil, true)
+ if sDrilling then
+ nType = 'Mill'
+ sHead = ''
+ end
+ end
+ end
+ if not sDrilling then
+ local sErr = 'Error : drilling not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- controllo posizione Y inizio foro con testa H6
+ if WD.HOR_DRILL_YNEG_MAXMIN and sHead == 'H6' then
+ if b3Raw:getMin():getY() > WD.HOR_DRILL_YNEG_MAXMIN then
+ local sErr = 'Error : horizontal hole with Drilling2 starting too far'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ end
+ -- recupero i dati dell'utensile
+ local dMaxDepth = 20
+ local dFreeLen = 20
+ local dDiamTh = 35
+ local dDiamT = 35
+ if EgtMdbSetCurrMachining( sDrilling) then
+ local bIsDrilling = ( EgtMdbGetCurrMachiningParam( MCH_MP.TYPE) == MCH_MY.DRILLING)
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ if bIsDrilling then
+ dFreeLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) - EgtTdbGetCurrToolThLength() - EgtMdbGetGeneralParam( MCH_GP.MAXDEPTHSAFE)
+ dMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth
+ else
+ dFreeLen = EgtTdbGetCurrToolMaxDepth() or dFreeLen
+ dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth, dFreeLen)
+ end
+ dDiamTh = EgtTdbGetCurrToolThDiam()
+ dDiamT = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dDiamT
+ end
+ end
+ -- calcolo riduzione lunghezza aggiuntiva per inclinazione utensile
+ if bAngledContourDrill then
+ local dToolAngleReduce = ( dDiamT / 2) * sqrt( 1 - vtExtr:getZ() * vtExtr:getZ()) / vtExtr:getZ()
+ dReduceDepth = ( dToolAngleReduce) + ( 5 / vtExtr:getZ())
+ end
+ -- aggiusto massimo affondamento per fori lungo Y con teste speciali
+ if sHead == 'H5' then
+ local dMaxY = WD.HOR_DRILL_Y_SPLIT + WD.HOR_DRILL_Y_TABLE / 2
+ local dDeltaY = dMaxY - Proc.Box:getMax():getY()
+ if dDeltaY > 0 then
+ dMaxDepth = dMaxDepth - dDeltaY
+ end
+ elseif sHead == 'H6' then
+ local dMinY = WD.HOR_DRILL_Y_SPLIT - WD.HOR_DRILL_Y_TABLE / 2
+ local dDeltaY = Proc.Box:getMin():getY() - dMinY
+ if dDeltaY > 0 then
+ dMaxDepth = dMaxDepth - dDeltaY
+ end
+ end
+ -- se foro faccia sopra, limito il massimo affondamento secondo inclinazione
+ if ptCen:getZ() > b3Raw:getMax():getZ() - dDiam / 2 then
+ local SinA = abs( vtExtr:getZ())
+ if SinA >= WD.DRILL_VZ_MIN then
+ local CosA = sqrt( 1 - SinA * SinA)
+ local dSlantFreeLen = dFreeLen - ( dDiamTh / 2 * CosA / SinA)
+ dMaxDepth = min( dMaxDepth, dSlantFreeLen)
+ else
+ dMaxDepth = 0
+ end
+ end
+ -- inserisco la lavorazione
+ local sName = EgtIf( sHead == 'H5' or sHead == 'H6', 'LhDrill_', 'Drill_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchId = EgtAddMachining( sName, sDrilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sDrilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- se foratura di fianco setto la nota per spostarla dopo i tagli di lama
+ if vtExtr:getZ() < WD.NZ_MINA and not sHead then
+ EgtSetInfo( nMchId, 'MOVE_AFTER', 1)
+ end
+ -- aggiungo geometria
+ if bAngledContourDrill then
+ EgtSetMachiningGeometry( nAngledContourDrillId)
+ else
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ end
+ -- eventuale inversione
+ if nType == 'Drill' then
+ EgtSetMachiningParam( MCH_MP.INVERT, bToInvert)
+ else
+ EgtSetMachiningParam( MCH_MP.TOOLINVERT, bToInvert)
+ end
+ -- se fresatura gestisco il lato di lavoro
+ if bAngledContourDrill then
+ local nWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE)
+ if nWorkSide == MCH_MILL_WS.CENTER then
+ nWorkSide = MCH_MILL_WS.RIGHT
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ EgtSetMachiningParam( MCH_MP.INVERT, nWorkSide == MCH_MILL_WS.LEFT)
+ elseif nType == 'Mill' then
+ local frRef = EgtGetGlobFrame( AuxId)
+ local vtNa, _, dArea = EgtCurveArea( AuxId)
+ vtNa:toGlob( frRef)
+ if vtNa:getZ() * dArea > 0 then
+ EgtSetMachiningParam( MCH_MP.INVERT, true)
+ else
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ end
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ -- per fori lungo Y con teste speciali aggiusto eventuale parte prima del foro ma nel grezzo
+ if sHead == 'H5' then
+ local dSafeStart = b3Raw:getMax():getY() - Proc.Box:getMax():getY() + 10
+ if dSafeStart > 20 then
+ EgtSetMachiningParam( MCH_MP.STARTPOS, dSafeStart)
+ end
+ elseif sHead == 'H6' then
+ local dSafeStart = Proc.Box:getMin():getY() - b3Raw:getMin():getY() + 10
+ if dSafeStart > 20 then
+ EgtSetMachiningParam( MCH_MP.STARTPOS, dSafeStart)
+ end
+ end
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then
+ nSCC = MCH_SCC.ADIR_YP
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- aggiusto l'affondamento
+ local sMyWarn
+ local dDepth = dLen - dReduceDepth
+ if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then
+ dDepth = dMaxDepth
+ if abs( Proc.Flg) ~= 2 then
+ sMyWarn = 'Warning in drill : depth (' .. EgtNumToString( dLen, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')'
+ EgtOutLog( sMyWarn .. ' (process ' .. tostring( Proc.Id) .. ')')
+ end
+ end
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- Note utente
+ local sUserNotes = ''
+ -- se foratura o svuotatura, dichiarazione nessuna generazione sfridi per Vmill
+ if nType == 'Drill' or nType == 'Pocket' then
+ sUserNotes = 'VMRS=0;'
+ end
+ -- se foratura
+ if nType == 'Drill' then
+ -- aggiungo alle note massima elevazione (coincide con affondamento)
+ sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dDepth, 1) .. ';'
+ -- se foro passante, aggiungo questa qualifica alle note
+ if bOpen then
+ sUserNotes = sUserNotes .. 'Open=1;'
+ end
+ end
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ else
+ local _, sWarn = EgtGetMachMgrWarning( 0)
+ if EgtIsMachiningEmpty() then
+ EgtSetOperationMode( nMchId, false)
+ return false, sWarn
+ else
+ sMyWarn = (sMyWarn or sWarn)
+ end
+ end
+ -- se preforo inclinato impostato, inclinazione oltre limite impostato e foro non orizzontale
+ if WD.PREDRILL_DIAM and WD.PREDRILL_DIAM > 0 and vtExtr:getZ() < ( WD.PREDRILL_MINANGLE or 0.707) and vtExtr:getZ() > 0.1 then
+ -- gruppo ausiliario per preforo
+ local nAddGrpId = WL.GetAddGroup( Proc.PartId)
+ -- calcolo profondita' foro
+ local dLen = ( WD.PREDRILL_DIAM / 2) * sqrt( 1 - vtExtr:getZ() * vtExtr:getZ()) / vtExtr:getZ()
+ -- copio foro originale
+ local nPreHoleId = EgtCopyGlob( AuxId, nAddGrpId)
+ EgtModifyArcRadius( nPreHoleId, WD.PREDRILL_DIAM / 2)
+ EgtModifyCurveThickness( nPreHoleId, -dLen) --dLen = 10
+
+ -- se da invertire
+ if bToInvert then
+ -- lo sposto della lunghezza d'estrusione e ne inverto il versore
+ local dThickness = EgtCurveThickness( AuxId)
+ EgtMove( nPreHoleId, abs( dThickness) * vtExtr, GDB_RT.GLOB)
+ EgtModifyCurveExtrusion( nPreHoleId, vtExtr, GDB_RT.GLOB)
+ end
+ -- recupero lavorazione di pocket
+ local sDrilling = WM.FindDrilling( WD.PREDRILL_DIAM, dLen, nil, true) --dLen = 10
+
+ if not sDrilling then
+ local sErr = 'Error : prehole pocket not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+
+ -- inserisco la lavorazione
+ local sName = 'PreDrill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchId = EgtAddMachining( sName, sDrilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sDrilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- setto la nota per spostarla prima della foratura
+ EgtSetInfo( nMchId, 'MOVE_BEFORE', 1)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ nPreHoleId, -1}})
+
+ -- note utente, dichiarazione nessuna generazione sfridi per Vmill
+ local sUserNotes = 'VMRS=0;'
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ else
+ local _, sWarn = EgtGetMachMgrWarning( 0)
+ if EgtIsMachiningEmpty() then
+ EgtSetOperationMode( nMchId, false)
+ return false, sWarn
+ else
+ sMyWarn = (sMyWarn or sWarn)
+ end
+ end
+ end
+
+ return true, sMyWarn
+
+end
+
+---------------------------------------------------------------------
+return WPD
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessDtMortise.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessDtMortise.lua
new file mode 100644
index 0000000..811e74a
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessDtMortise.lua
@@ -0,0 +1,220 @@
+-- WProcessDtMortise.lua by Egaltech s.r.l. 2021/04/20
+-- Gestione calcolo mortase a coda di rondine per Pareti
+
+-- Tabella per definizione modulo
+local WPDM= {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+
+EgtOutLog( ' WProcessDtMortise started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+-- settaggi interni ( poi andrà utilizzato parametro ACTIVE_AS proveniente da parametri utente di TechnoEssetre)
+local bMakeAntiSplitPath = true
+local bMakeAsByArc = true
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPDM.Identify( Proc)
+ return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 55))
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPDM.Classify( Proc, b3Raw)
+ -- recupero i dati della curva di contorno della faccia di fondo
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if not AuxId then return false end
+ AuxId = AuxId + Proc.Id
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ -- verifico se la mortasa è lavorabile
+ return ( vtExtr:getZ() > WD.NZ_MINA)
+end
+
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPDM.FlipClassify( Proc)
+ -- recupero i dati della curva di contorno della faccia di fondo
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if not AuxId then return false end
+ AuxId = AuxId + Proc.Id
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ -- verifico se la mortasa è lavorabile
+ nFlip0 = EgtIf( vtExtr:getZ() > WD.NZ_MINA, 100, 0)
+ nFlip1 = EgtIf( - vtExtr:getZ() > WD.NZ_MINA, 100, 0)
+
+ return nFlip0, nFlip1
+
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPDM.Make( Proc, nRawId, b3Raw)
+ -- recupero e verifico l'entità curva
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Missing profile geometry : Error on DtMortise ' .. tostring( Proc.Id)
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati della curva
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local ptBC = EgtGP( AuxId, GDB_RT.GLOB)
+ -- verifico che la mortasa non sia orientata verso il basso (-5 deg) o che ci sia una testa da sotto
+ local bFaceDown = ( vtExtr:getZ() < - 0.1)
+ if bFaceDown then
+ local sErr = 'Machining from bottom impossible : Error on DtMortise ' .. tostring( Proc.Id)
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- determino l'altezza della mortasa (0=faccia di fondo)
+ local rfDtMrt = Frame3d( ptBC, vtExtr)
+ local b3DtMrt = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfDtMrt)
+ local dAltMort = b3DtMrt:getDimZ()
+ -- verifico se di tipo pocket
+ local bPocket = ( EgtGetInfo( Proc.Id, 'P05', 'i') == 1)
+ if bPocket then bMakeAntiSplitPath = false end
+ -- recupero il raggio minimo della mortasa
+ local dMinRad = 1000
+ local nSt, nEnd = EgtCurveDomain( AuxId)
+ for i = nSt, nEnd - 1 do
+ local dRad = EgtCurveCompoRadius( AuxId, i)
+ if dRad > 0 and dRad < dMinRad then
+ dMinRad = dRad
+ end
+ end
+ -- recupero la lavorazione
+ local sMillType = 'DtMortise'
+ -- recupero la lavorazione : prima ricerca per sola tipologia
+ local sMilling = WM.FindMilling( sMillType)
+ if not sMilling then
+ local sErr = 'Milling not found in library : Error on DtMortise ' .. tostring( Proc.Id)
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero la lavorazione : seconda ricerca con tipologia e diametro massimo
+ sMilling = WM.FindMilling( sMillType, nil, nil, nil, 2 * dMinRad)
+ if not sMilling then
+ local sErr = 'Radius too small : Error on DtMortise ' .. tostring( Proc.Id)
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero il diametro dell'utensile e l'angolo di spoglia
+ local dToolDiam = 100
+ local dMaxMat = 30
+ local dSideAng = 0
+ local bCW = true
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam
+ dToolDiam = max( dToolDiam, 10)
+ dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat
+ dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or dSideAng
+ local dSpeed = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) or 0
+ bCW = ( dSpeed >= 0)
+ end
+ end
+ -- verifico che la profondità non superi il massimo materiale dell'utensile
+ if dAltMort > dMaxMat + 10 * GEO.EPS_SMALL then
+ local sErr = 'Error : DtMortise Depth bigger than Tool Cutting edge'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se con tasca, la lavoro
+ if bPocket then
+ -- recupero il contorno della tasca (seconda curva ausiliaria)
+ local sVal = EgtGetInfo( Proc.Id, 'AUXID')
+ local vsAuxId = EgtSplitString( sVal)
+ local Aux2Id
+ if vsAuxId and #vsAuxId >=2 then
+ Aux2Id = tonumber( vsAuxId[2])
+ end
+ if Aux2Id then Aux2Id = Aux2Id + Proc.Id end
+ if not Aux2Id or ( EgtGetType( Aux2Id) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Missing pocket geometry : Error on DtMortise ' .. tostring( Proc.Id)
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero la lavorazione
+ local sPocketing
+ if Proc.Prc ~= 53 then
+ sPocketing = WM.FindPocketing( 'Mortise', dToolDiam)
+ end
+ if not sPocketing then
+ sPocketing = WM.FindPocketing( 'Pocket', dToolDiam)
+ end
+ if not sPocketing then
+ local sErr = 'Error : Mortise or Pocket not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione di svuotatura
+ local sName = 'DtMtPck_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sPocketing)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Aux2Id, -1}})
+ -- dichiaro non si generano sfridi per VMill
+ local sUserNotes = 'MaxElev='.. EgtNumToString( dMaxMat - 0.1, 1) .. '; VMRS=0;'
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ end
+ -- verifico se necessarie più passate (distanza all'imbocco ortogonale all'asse)
+ local vtDiff = EgtEP( AuxId, GDB_RT.GLOB) - EgtSP( AuxId, GDB_RT.GLOB)
+ local vtAx = EgtEV( AuxId, GDB_RT.GLOB) - EgtSV( AuxId, GDB_RT.GLOB)
+ vtAx:normalize()
+ local vtOrtDiff = vtDiff - vtDiff * vtAx * vtAx
+ local dDist = vtOrtDiff:len()
+ -- calcolo le passate
+ local nPass = ceil( dDist / ( 1.9 * dToolDiam))
+ local dStep = ( dDist - 0.95 * dToolDiam) / ( 2 * nPass)
+ for i = nPass, 1, -1 do
+ -- inserisco la lavorazione di contornatura
+ local sNameF = 'DtMt_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nPass)
+ local nMchFId = EgtAddMachining( sNameF, sMilling)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- imposto offset
+ local dOffs = ( i - 1) * dStep
+ EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
+ -- sistemo il lato e la direzione di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT))
+ EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bCW, false, true))
+ -- dichiaro non si generano sfridi per VMill
+ local sUserNotes = 'MaxElev='.. EgtNumToString( dMaxMat - 0.1, 1) .. '; VMRS=0;'
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+return WPDM
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessFreeContour.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessFreeContour.lua
new file mode 100644
index 0000000..dd671b8
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessFreeContour.lua
@@ -0,0 +1,2432 @@
+-- ProcessFreeContour.lua by Egaltech s.r.l. 2022/03/16
+-- Gestione calcolo profilo libero per Pareti
+-- 2021/11/15 Penna e chiodature sono sempre riportate sulla faccia sopra anche se nel progetto sono sotto.
+-- 2021/12/10 In taglio con lama aggiunta gestione SCC per testa Gearbox.
+-- 2022/01/13 Aggiunta gestione massimo affondamento in Z anche per pulizia spigoli con fresa 60deg (WD.MAX_CLEAN_CRN60).
+-- 2022/02/03 Corretto controllo massimo affondamento nella tavola.
+-- 2022/02/21 Corretti allungamenti/accorciamenti tagli inclinati con fresa. Migliorata gestione tagli trasversali per macchine travi.
+-- 2022/03/14 Corretto riconoscimento lato esterno per percorsi aperti.
+-- 2022/03/16 Ulteriore modifica per riconoscimento lato esterno (aggiunto uso vExtr a GetFacesExternalSide).
+
+-- Tabella per definizione modulo
+local WPF = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+
+EgtOutLog( ' WProcessFreeContour started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+if WD.CHECK_MIN_Z_SAW == nil then WD.CHECK_MIN_Z_SAW = true end
+if not WD.MIN_Z_SAW then WD.MIN_Z_SAW = 0 end
+if not WD.MAX_CLEAN_CRN60 then WD.MAX_CLEAN_CRN60 = 150 end
+local WHISK_OFFS = 0.1
+local WHISK_SAFE = 5
+local MIN_LEN_CUT = 250
+
+-- variabili assegnazione parametri Q
+local sTypeCornerCut = 'Q05' -- i
+-- variabile settaggio doppia lavorazione su angoo > 90
+local bMakeTwinCut = true
+-- variabile per valore sfondamento spigolo
+local dExtraCorner = 1
+-- angolo sottosquadra ammesso per fresa cono 30°
+local dAngleSmall = 70
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPF.Identify( Proc)
+ return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and ( Proc.Prc == 250 or Proc.Prc == 251 or Proc.Prc == 252))
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPF.Classify( Proc, b3Raw)
+ -- verifico se di tipo pocket
+ local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
+ -- recupero la curva associata
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if not AuxId then return false end
+ AuxId = AuxId + Proc.Id
+ local vtN = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ -- recupero il tipo di lavorazione
+ local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0
+ -- se tasca
+ if bPocket then
+ local bDown = ( vtN:getZ() < - 0.5)
+ return not bDown
+ -- se altrimenti profilo orizzontale
+ elseif abs( vtN:getZ()) < 0.5 then
+ return false
+ -- se penna o chiodatura va sempre bene (vengono sempre riportati sopra)
+ elseif nCntType == 10 or nCntType == 20 then
+ return true
+ -- se altrimenti profilo verticale che non interessa tutta la sezione
+ elseif Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 2 then
+ return false
+ -- altrimenti è profilo verticale che interessa tutta la sezione
+ else
+ return true
+ end
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPF.FlipClassify( Proc, b3Raw)
+ local nFlip0 = 0
+ local nFlip1 = 0
+
+ -- verifico se di tipo pocket
+ local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
+ -- recupero la curva associata se esiste
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if not AuxId then return false end
+ AuxId = AuxId + Proc.Id
+ local vtN = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local dVtNZ = vtN:getZ()
+ -- se tasca
+ if bPocket then
+ -- verifico se è lavorabile da sopra
+ nFlip0 = EgtIf( dVtNZ < -0.5, 0, 100)
+ -- verifico se e' lavorabile da fliped: cambio segno al versore
+ nFlip1 = EgtIf( -dVtNZ < -0.5, 0, 100)
+
+ -- se altrimenti profilo orizzontale
+ elseif abs( dVtNZ) < WD.NZ_MINA then
+ return 0, 0
+ -- se altrimenti profilo verticale che non interessa tutta la sezione
+ elseif Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 2 then
+ return 0 , 0
+ -- altrimenti è profilo verticale che interessa tutta la sezione
+ else
+ local dVtNZMedia = 0
+ for i = 1, Proc.Fct do
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT)
+ dVtNZMedia = dVtNZMedia + vtN:getZ()
+ end
+ dVtNZMedia = dVtNZMedia / Proc.Fct
+ if abs( dVtNZMedia) <= GEO.EPS_SMALL then
+ nFlip0 = 100
+ nFlip1 = 100
+ elseif dVtNZMedia >= 0 + GEO.EPS_SMALL then
+ nFlip0 = 75
+ nFlip1 = 50
+ else
+ nFlip0 = 50
+ nFlip1 = 75
+ end
+ end
+ return nFlip0, nFlip1
+end
+
+---------------------------------------------------------------------
+local function TestElleShape3( nIdGeom, nNumFacet)
+ -- valida solo nel caso di tre facce
+ if nNumFacet ~= 3 then return false end
+ -- determino se L con una faccia terminale o U con tre facce
+ local bIsL = true
+ for i = 1, 3 do
+ local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1]
+ -- le conto
+ local nCount = 0
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ nCount = nCount + 1
+ end
+ end
+ if nCount == 1 then
+ bIsL = false
+ break
+ end
+ end
+ return bIsL
+end
+
+---------------------------------------------------------------------
+local function TestElleShape4( nIdGeom, nNumFacet)
+ -- valida solo nel caso di quattro facce
+ if nNumFacet ~= 4 then return false end
+ -- determino se L con due facce terminali o O
+ local nFac3Adj = 0
+ local dMinArea3 = GEO.INFINITO * GEO.INFINITO
+ local dMaxArea2 = 0
+ for i = 1, 4 do
+ local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1]
+ -- le conto
+ local nCount = 0
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ nCount = nCount + 1
+ end
+ end
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nIdGeom, i - 1, GDB_ID.ROOT)
+ local dArea = dH * dV
+ if nCount == 2 then
+ dMaxArea2 = max( dMaxArea2, dArea)
+ elseif nCount == 3 then
+ dMinArea3 = min( dMinArea3, dArea)
+ nFac3Adj = nFac3Adj + 1
+ end
+ end
+ if nFac3Adj ~= 2 then return false end
+ -- verifico se L profonda oppure lunga
+ if dMinArea3 < dMaxArea2 then
+ return 1
+ else
+ return 2
+ end
+end
+
+---------------------------------------------------------------------
+local function VerifyCornerType( Proc)
+ -- Verifico il tipo di lavorazione su angolo :
+ -- 0 : niente
+ -- 1 : ripresa corner dopo pausa per rimozione sfridi (fresa 60deg)
+ -- 2 : ripresa corner senza pausa (fresa 30 deg)
+ -- 3 : scarico corner (tipo foro).
+ local nVal = EgtGetInfo( Proc.Id, sTypeCornerCut, 'i')
+ return ( nVal or 0)
+end
+
+---------------------------------------------------------------------
+local function IsPointOnRawLongEdges( ptCen, b3Raw)
+ return ( abs( ptCen:getY() - b3Raw:getMin():getY()) < 0.1 or abs( ptCen:getY() - b3Raw:getMax():getY()) < 0.1)
+end
+
+---------------------------------------------------------------------
+local function GetOtherRegions( nPartId)
+ local vOthers = {}
+ -- ciclo sui pezzi
+ local nOtherId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL)
+ while nOtherId do
+ -- cerco le regioni marcate
+ local nCount = 0
+ local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL)
+ while nRegId do
+ local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT)
+ if EgtExistsInfo( nRegId, 'REGION') and vtN and AreSameVectorApprox( vtN, Z_AX()) then
+ local b3Reg = EgtGetBBoxGlob( nRegId, GDB_BB.STANDARD)
+ if b3Reg then
+ nCount = nCount + 1
+ table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg})
+ end
+ end
+ nRegId = EgtGetNext( nRegId)
+ end
+ -- se non trovate regioni marcate, cerco regioni con la normale corretta
+ if nCount == 0 then
+ local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL)
+ while nRegId do
+ local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT)
+ if EgtGetType( nRegId) == GDB_TY.SRF_FRGN and vtN and AreSameVectorApprox( vtN, Z_AX()) then
+ local b3Reg = EgtGetBBoxGlob( nRegId, GDB_BB.STANDARD)
+ if b3Reg then
+ table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg})
+ end
+ end
+ nRegId = EgtGetNext( nRegId)
+ end
+ end
+ -- passo al pezzo successivo
+ nOtherId = EgtGetNextPartInRawPart( nOtherId)
+ end
+ return vOthers
+end
+
+---------------------------------------------------------------------
+local function ReorderFaces( nIdSurf, nNumFacet)
+ -- recupero le adiacenze di tutte le facce
+ local vAdj = {}
+ for i = 1, nNumFacet do
+ -- recupero le adiacenze della faccia
+ local vFacAdj = EgtSurfTmFacetAdjacencies( nIdSurf, i - 1)[1]
+ -- le conto
+ local nCount = 0
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ nCount = nCount + 1
+ end
+ end
+ vAdj[i] = nCount
+ end
+ -- sposto le facce isolate alla fine
+ for i = #vAdj, 1, -1 do
+ if vAdj[i] == 0 then
+ if vAdj[#vAdj] == 0 then
+ table.remove( vAdj, i)
+ end
+ EgtSurfTmSwapFacets( nIdSurf, i - 1, #vAdj)
+ end
+ end
+ -- se facce tutte isolate, esco
+ if #vAdj == 0 then return end
+ -- cerco la faccia non isolata con il minor numero di adiacenze
+ local nIdFace
+ local nAdjMin = 1000
+ for i = 1, #vAdj do
+ if vAdj[i] < nAdjMin then
+ nAdjMin = vAdj[i]
+ nIdFace = i
+ end
+ end
+ -- se la faccia non isolata con minori adiacenze non è in prima posizione, eseguo scambio
+ if nIdFace and nIdFace ~= 1 and nAdjMin == 1 then
+ EgtSurfTmSwapFacets( nIdSurf, nIdFace-1, 0)
+ end
+ -- ordino le facce in modo da avere una sequenza di facce concatenate
+ for i = 1, #vAdj - 1 do
+ -- recupero l'angolo con la faccia precedente
+ local bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, i, GDB_ID.ROOT)
+ -- se non ho adiacenza
+ if not bAdj then
+ for j = i+1, #vAdj do
+ bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, j-1, GDB_ID.ROOT)
+ -- se ho adiacenza scambio le facce
+ if bAdj then
+ EgtSurfTmSwapFacets( nIdSurf, i, (j-1))
+ break
+ end
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+local function RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFaceToDel)
+ -- copio la superfice nel gruppo ausiliario
+ local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
+ EgtSurfTmRemoveFacet( nNewProc, nFaceToDel)
+ local nNumFacet = EgtSurfTmFacetCount( nNewProc)
+ ReorderFaces( nNewProc, nNumFacet)
+ return nNewProc, nNumFacet
+end
+
+
+---------------------------------------------------------------------
+local function GetFacesExternalSide( Proc, vtExtr)
+ -- 3=sinistra, 4=destra
+ -- se meno di due facce considero esterno come dichiarato dal gruppo
+ local nNumFacet = EgtSurfTmFacetCount( Proc.Id)
+ if nNumFacet < 2 then return Proc.Grp end
+ -- se facce isolate, considero esterno come dichiarato dal gruppo
+ local bAdj, ptV1, ptV2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
+ if not bAdj then return Proc.Grp end
+ -- calcolo dell'esterno rispetto all'avanzamento
+ local ptC1, vtN1 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ local ptV = ( ptV1 + ptV2) / 2
+ local vtDir1 = ptV - ptC1
+ if ( vtN1 ^ vtDir1) * vtExtr > 0 then
+ return 4
+ else
+ return 3
+ end
+end
+
+---------------------------------------------------------------------
+local function GetFacesData( Proc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, b3Raw, nMasterNewProc)
+ --se richiesto, copio la superficie nel gruppo ausiliario
+ local nNewProc
+ if nMasterNewProc then
+ nNewProc = nMasterNewProc
+ else
+ nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
+ end
+ -- recupero i dati di tutte le facce
+ local vFace = {}
+ local nNumFacet = EgtSurfTmFacetCount( nNewProc)
+ for i = 1, nNumFacet do
+ -- indice faccia corrente e precedente
+ local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1)
+ local nPrecFac
+ if bOpposite then
+ if nNumFacet > 2 then
+ nPrecFac = EgtIf( i == 1, 0, nFac + 1)
+ else
+ nPrecFac = EgtIf( i == 1, -1, nFac + 1)
+ end
+ else
+ if nNumFacet > 2 then
+ nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2)
+ else
+ nPrecFac = EgtIf( i == 1, - 1, i - 2)
+ end
+ end
+ -- recupero centro e normale della faccia
+ local ptCen, vtN = EgtSurfTmFacetCenter( nNewProc, nFac, GDB_ID.ROOT)
+ -- recupero le dimensioni della faccia
+ local _, dLen, dWidth = WL.GetFaceHvRefDim( nNewProc, nFac)
+ -- recupero l'angolo con la faccia precedente
+ local bAdj, ptLocP1, ptLocP2, dAng = EgtSurfTmFacetsContact( nNewProc, nPrecFac, nFac, GDB_ID.ROOT)
+ local dPrevAng = EgtIf( bAdj, dAng, 0)
+ -- se angolo con faccia precedente negativo, calcolo anche angolo tra le facce nel piano
+ local dPlanePrevAng = 0
+ if dPrevAng < 0 then
+ local vtPrevN = EgtSurfTmFacetNormVersor( nNewProc, nPrecFac, GDB_ID.ROOT)
+ local dCosA = ( Z_AX() ^ vtPrevN) * ( Z_AX() ^ vtN)
+ dPlanePrevAng = -acos( dCosA)
+ end
+ -- calcolo l'angolo di inclinazione (dalla verticale)
+ local dSideAng = asin( vtN:getZ())
+ -- salvo i dati
+ vFace[i] = { Fac = nFac, Cen = ptCen, Norm = vtN, Len = dLen, Width = dWidth, PrevAng = dPrevAng, PlPrevAng = dPlanePrevAng, SideAng = dSideAng}
+ if bAdj then
+ if ptLocP1:getZ() < ptLocP2:getZ() then
+ vFace[i].PPrev = ptLocP1
+ else
+ vFace[i].PPrev = ptLocP2
+ end
+ end
+ end
+ -- analizzo le facce
+ local dMaxWidth = 0
+ for i = 1, #vFace do
+ -- aggiorno la massima larghezza
+ if vFace[i].Width > dMaxWidth then
+ dMaxWidth = vFace[i].Width
+ end
+ -- verifico l'affondamento
+ local dDepth = WD.CUT_EXTRA
+ if vFace[i].Width + WD.CUT_EXTRA > dToolMaxDepth then
+ dDepth = dToolMaxDepth - vFace[i].Width
+ end
+ -- lunghezza baffo
+ local dElev = vFace[i].Width + dDepth
+ local dWhisk = EgtIf( bCalclForBlade, ( dElev * sqrt( dToolDiam / dElev - 1) + WHISK_SAFE) , (dToolDiam/2) + WHISK_SAFE)
+ -- determino la lunghezza del taglio passante e il tipo di attacco e uscita
+ local dLen = vFace[i].Len
+ local dLenY = dLen * abs( vFace[i].Norm:getX()) / sqrt( 1 - vFace[i].Norm:getZ() * vFace[i].Norm:getZ())
+ local nType = 0
+ if vFace[i].PrevAng < -0.1 or
+ ( WD.BEAM_MACHINE and not IsPointOnRawLongEdges( vFace[i].Cen, b3Raw) and ( dLen > 0.5 * WD.CUT_MAX_LENGTH or dLenY > 0.4 * b3Raw:getDimY())) then
+ dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0)
+ nType = nType + 1
+ end
+ if vFace[EgtIf( i < nNumFacet, i + 1, 1)].PrevAng < -0.1 or
+ ( WD.BEAM_MACHINE and not IsPointOnRawLongEdges( vFace[i].Cen, b3Raw) and ( dLen > 0.5 * WD.CUT_MAX_LENGTH or dLenY > 0.4 * b3Raw:getDimY())) then
+ dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0)
+ nType = nType + 2
+ end
+ -- se lunghezza non significativa, non va inserito il taglio
+ if dLen < MIN_LEN_CUT then
+ nType = 4
+ end
+ -- numero dei lati
+ local nEdges = #(EgtSurfTmFacetAdjacencies( nNewProc, i - 1)[1])
+ -- assegno i nuovi dati
+ vFace[i].Depth = dDepth
+ vFace[i].Whisk = dWhisk
+ vFace[i].Type = nType
+ vFace[i].Edges = nEdges
+ end
+ -- recupero le regioni degli altri pezzi
+ local vOthers = GetOtherRegions( Proc.PartId)
+ -- verifico i baffi sporgenti dei tagli rispetto alle altre regioni
+ for i = 1, #vFace do
+ -- verifico il baffo iniziale
+ if vFace[i].Type ~= 4 and ( vFace[i].Type & 1) == 0 then
+ -- creo il rettangolo del baffo
+ local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize()
+ local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), -90)
+ local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, -90)
+ local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt
+ local ptDir = ptIni + ( vFace[i].Whisk - WHISK_OFFS) * vtDir
+ local ptCross = ptDir + ( dToolThick - WHISK_OFFS) * vtOrt
+ local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB)
+ local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD)
+ -- verifico se interferisce con gli altri pezzi
+ for j = 1, #vOthers do
+ if OverlapsXY( b3Wh, vOthers[j].Box) then
+ local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0)
+ if nClass ~= GDB_RC.OUT then
+ local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 2) ~= 0, -vFace[i].Whisk, 0)
+ if dLen >= MIN_LEN_CUT then
+ vFace[i].Type = vFace[i].Type + 1
+ else
+ vFace[i].Type = 4
+ end
+ break
+ end
+ end
+ end
+ EgtErase( WhId)
+ end
+ -- verifico il baffo finale
+ if vFace[i].Type ~= 4 and ( vFace[i].Type & 2) == 0 then
+ -- creo il rettangolo del baffo
+ local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize()
+ local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), 90)
+ local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, 90)
+ local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt
+ local ptDir = ptIni + ( vFace[i].Whisk - WHISK_OFFS) * vtDir
+ local ptCross = ptDir + ( dToolThick - WHISK_OFFS) * vtOrt
+ local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB)
+ local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD)
+ -- verifico se interferisce con gli altri pezzi
+ for j = 1, #vOthers do
+ if OverlapsXY( b3Wh, vOthers[j].Box) then
+ local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0)
+ if nClass ~= GDB_RC.OUT then
+ local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 1) ~= 0, -vFace[i].Whisk, 0)
+ if dLen >= MIN_LEN_CUT then
+ vFace[i].Type = vFace[i].Type + 2
+ else
+ vFace[i].Type = 4
+ end
+ break
+ end
+ end
+ end
+ EgtErase( WhId)
+ end
+ end
+ -- se ciclo chiuso
+ if abs( vFace[1].PrevAng) > 0.1 then
+ -- verifico se c'è un solo tipo 3 e nessun tipo 0, 1 o 2
+ local nInd3
+ local nTot3 = 0
+ local nTot012 = 0
+ for i = 1, #vFace do
+ local Face = vFace[i]
+ if Face.Type == 0 or Face.Type == 1 or Face.Type == 2 then
+ nTot012 = nTot012 + 1
+ elseif Face.Type == 3 then
+ nTot3 = nTot3 + 1
+ nInd3 = i
+ end
+ end
+ -- se trovato il caso, trasformo il 3 in 4 (per evitare problemi con fresature con la stessa faccia a inizio e fine)
+ if nTot3 == 1 and nTot012 == 0 then
+ vFace[nInd3].Type = 4
+ end
+ end
+
+ -- eventuali stampe
+ for i = 1, #vFace do
+ local Face = vFace[i]
+ local sOut = 'Face '..tostring( Face.Fac)..' C'..tostring( Face.Cen)..' N'..tostring( Face.Norm)..
+ ' L='..EgtNumToString( Face.Len, 1)..' W='..EgtNumToString( Face.Width, 1)..' Ap='..EgtNumToString( Face.PrevAng, 1)..
+ ' App='..EgtNumToString( Face.PlPrevAng, 1)..' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..
+ ' As='..EgtNumToString( Face.SideAng, 1)..' T='..tostring( Face.Type)..' E='..tostring( Face.Edges)
+ EgtOutLog( sOut)
+ end
+
+ return vFace, dMaxWidth, nNewProc
+end
+
+---------------------------------------------------------------------
+local function GetTunnelDimension( nId, nPartId, nAddGrpId)
+ -- ottengo i versori delle 4 facce e ottengo l'orientamento del tunnel
+ -- recupero il numero di facce
+ local nFacCnt = EgtSurfTmFacetCount( nId)
+ -- recupero l'ingombro della trave
+ local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
+ -- variabili dimensioni fessura e id faccia lunga
+ local dDimMin
+ local dDimMax
+ local nLongIdFace = 0
+ local bNegFace
+ local bOppoFace = false
+ -- ottengo il versore ortogonale
+ local ptN1, vtN1 = EgtSurfTmFacetCenter( nId, 0, GDB_ID.ROOT)
+ local _, vtN2 = EgtSurfTmFacetCenter( nId, 1, GDB_ID.ROOT)
+ local vtOrtho = vtN1 ^ vtN2
+ if vtOrtho:isSmall() then
+ _, vtN2 = EgtSurfTmFacetCenter( nId, 2, GDB_ID.ROOT)
+ vtOrtho = vtN1 ^ vtN2
+ bOppoFace = true
+ end
+ vtOrtho:normalize()
+ if vtOrtho:getZ() < -0.5 then
+ vtOrtho = -vtOrtho
+ bNegFace = true
+ end
+ -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta la profondità della fessura
+ local frFc = Frame3d( ptN1, vtOrtho) ;
+ local bBoxLoc = EgtGetBBoxRef( nId, GDB_BB.STANDARD, frFc)
+ local dDepth = bBoxLoc:getDimZ()
+ -- mi assicuro che la Z del punto utilizzato per creare la superficie sia alla Z inferiore del bounding box locale
+ local ptN2 = Point3d(ptN1)
+ ptN2:toLoc(frFc)
+ ptN2 = Point3d( ptN2:getX(), ptN2:getY(), bBoxLoc:getMin():getZ() + 2*GEO.EPS_SMALL)
+ ptN2:toGlob(frFc)
+ -- creo superficie intermedia
+ local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptN2, vtOrtho, b3Solid, GDB_ID.ROOT)
+ if not nSurfInt then return end
+ -- ritaglio la superficie con le facce della fessura
+ for i = 1, nFacCnt do
+ local ptN, vtN = EgtSurfTmFacetCenter( nId, i - 1, GDB_ID.ROOT)
+ EgtCutSurfTmPlane( nSurfInt, ptN, -vtN, false, GDB_ID.ROOT)
+ end
+ -- sposto la geometria trovata sulla Z minima (era su di 2 * GEO.EPS_SMALL)
+ EgtMove( nSurfInt, Point3d(0,0,-2*GEO.EPS_SMALL) - ORIG(), GDB_RT.GLOB)
+ -- mi faccio dare il contorno della superfice e la ricreo in modo più corretto
+ local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId)
+ if not nIdCont then return end
+ -- elimino le entità allineate dello stesso tipo
+ EgtMergeCurvesInCurveCompo( nIdCont, 2*GEO.EPS_SMALL)
+ EgtErase(nSurfInt)
+ nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2*GEO.EPS_SMALL)
+ -- elimino il contorno
+ EgtErase(nIdCont)
+ -- se normale negativa inverto
+ _, vtN1 = EgtSurfTmFacetCenter( nSurfInt, 0, GDB_ID.ROOT)
+ if vtN1:getZ() < -0.5 then EgtInvertSurf( nSurfInt) end
+ local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT)
+ dDimMin = min( DimH, DimV)
+ dDimMax = max( DimH, DimV)
+ _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFacCnt-1, GDB_ID.ROOT)
+ -- se faccia pari alla larghezza fessura
+ if abs(DimH - dDimMax) < GEO.EPS_SMALL or abs(DimV - dDimMax) < GEO.EPS_SMALL then
+ nLongIdFace = nFacCnt-1
+ -- altrimenti verifico anche con la faccia precedente
+ else
+ local nFaceToCheck = EgtIf( bOppoFace, nFacCnt-3, nFacCnt-2)
+ -- prendo le dimensioni della faccia e poi confronto con il minimo
+ _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFaceToCheck, GDB_ID.ROOT)
+ -- se trovato con il minimo, questa seconda faccia non è la più lunga
+ if abs(DimH - dDimMin) < GEO.EPS_SMALL or abs(DimV - dDimMin) < GEO.EPS_SMALL then
+ nLongIdFace = nFacCnt-1
+ else
+ nLongIdFace = nFaceToCheck
+ end
+ end
+ if not dDimMax then
+ return dDimMin, dDimMax, dDepth, nil, nil
+ end
+ return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt
+end
+
+---------------------------------------------------------------------
+local function ReorderFacesFromTab( nIdSurf, vFace)
+
+ local nFacCnt = EgtSurfTmFacetCount( nIdSurf)
+ for i = 1, #vFace do
+ for j = 1, nFacCnt do
+ -- ottengo punto iniziale e versore della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( nIdSurf, (j-1), GDB_ID.ROOT)
+ -- se versore e posizione coincidono e non corrispondono al numero faccia, faccio lo swap
+ if AreSameVectorExact( vFace[i].Norm, vtN) and AreSamePointEpsilon( vFace[i].Cen, ptC, 50*GEO.EPS_SMALL) then
+ if (j-1) ~= vFace[i].Fac then
+ EgtSurfTmSwapFacets( nIdSurf, vFace[i].Fac, (j-1))
+ end
+ break
+ end
+ end
+ end
+ return nIdSurf
+end
+
+---------------------------------------------------------------------
+local function MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick, bClosed)
+
+ local nPath = {}
+ local nPathData = {}
+
+ for i = 1, #vGeom do
+ local dAng
+ -- ottengo curva inferiore 1
+ local ptP1, ptP2, ptP3, vtV1, vtV2, dDim1, dDim2 = EgtSurfTmFacetOppositeSide( vGeom[i][1], vGeom[i][2], Z_AX() , GDB_ID.ROOT)
+ if i < #vGeom then
+ -- ricavo i punti e l'angolo interno
+ _, _, _, dAng = EgtSurfTmFacetsContact( vGeom[i][1], vGeom[i][2], vGeom[i+1][2], GDB_ID.ROOT)
+ elseif i == #vGeom and nConeCut == 3 and bClosed then
+ -- ricavo i punti e l'angolo interno
+ _, _, _, dAng = EgtSurfTmFacetsContact( vGeom[i][1], vGeom[i][2], vGeom[1][2], GDB_ID.ROOT)
+ else
+ dAng = 0
+ end
+ -- creo linea
+ local nId1 = EgtLine( nAddGrpId, ptP1, ptP3, GDB_RT.GLOB)
+ table.insert( nPath, nId1)
+ table.insert( nPathData, {nId1, dAng})
+ end
+
+ -- creo il percorso e poi lo offsetto del raggio utensile
+ local AuxId = EgtCurveCompo( nAddGrpId, nPath, true)
+ EgtOffsetCurve( AuxId, dMillDiam / 2, GDB_OT.EXTEND)
+ -- spezzo il percorso nelle entità componenti
+ local nId1st, nIdCount = EgtExplodeCurveCompo( AuxId)
+ -- se il numero entità è diverso da quelle iniziali esco con errore
+ if nIdCount ~= #vGeom then
+ local sErr = 'Error : cannot make offset path'
+ return 0, sErr
+ end
+ -- resetto la tabella
+ nPath = {}
+ AuxId = nil
+ -- in base al tipo di ripresa spigolo modifico il percorso
+ if nConeCut == 2 then
+ -- acquisisco la lunghezza utensile
+ sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner30')
+ if not sMilling then
+ local sErr = 'Error : CleanCorner 30 not found in library'
+ return 0, sErr
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMillLength = 0
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMillLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLength
+ end
+ end
+ -- calcolo la lunghezza della linea da inserire in base all'angolo e alla lunghezza utensile
+ local dLenAdd = abs(( dMillLength * sin(33)) - ( dMillDiam / 2))
+ -- per ogni entità compongo la nuova lista per creare percorso
+ for i = 1, nIdCount do
+ -- aggiungo linea precedente
+ table.insert( nPath, ( nId1st + i - 1))
+ -- se non è la linea finale e l'angolo tra le due facce è ammesso
+ if i < nIdCount and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL) and nPathData[i][2] < 0 and
+ nPathData[i][2] > -(180-dAngleSmall + 10 * GEO.EPS_SMALL) then
+ -- aggiungo una retta sulla bisettrice
+ local _, vtN2 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[i][2], GDB_ID.ROOT)
+ local _, vtN3 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[i+1][2], GDB_ID.ROOT)
+ local ptP1 = EgtEP( ( nId1st + i - 1), GDB_ID.ROOT)
+ -- sommo i tre versori per avere una direzione media
+ local vtExtrExit = vtN2 + vtN3
+ vtExtrExit:normalize()
+ -- linea intermedia (componente lunghezza utensile in direzione bisettrice)
+ local pEnd = ptP1 + ( dLenAdd * vtExtrExit)
+ nAuxId = EgtLine( nAddGrpId, ptP1, pEnd, GDB_RT.GLOB)
+ table.insert( nPath, nAuxId)
+ -- linea di ritorno
+ nAuxId = EgtLine( nAddGrpId, pEnd, ptP1, GDB_RT.GLOB)
+ table.insert( nPath, nAuxId)
+ end
+ end
+ -- ricreo il percorso
+ AuxId = EgtCurveCompo( nAddGrpId, nPath, true)
+ -- altrimenti sfondo spigolo
+ elseif nConeCut == 3 then
+ -- per ogni entità compongo la nuova lista per creare percorso
+ for i = 1, nIdCount do
+ -- aggiungo linea precedente
+ table.insert( nPath, ( nId1st + i - 1))
+ -- se non è la linea finale e l'angolo tra le due facce è ammesso
+ if ( i < nIdCount and nPathData[i][2] < 0) or ( i == nIdCount and bClosed and nPathData[i][2] < 0) then
+ -- aggiungo una retta sulla bisettrice
+ local _, vtN2 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[i][2], GDB_ID.ROOT)
+ local _, vtN3 = EgtSurfTmFacetCenter( vGeom[i][1], vGeom[ EgtIf( i == nIdCount and bClosed, 1, i+1)][2], GDB_ID.ROOT)
+ local ptP1 = EgtEP( ( nId1st + i - 1), GDB_ID.ROOT)
+ -- sommo i tre versori per avere una direzione media
+ local vtExtrExit = vtN2 + vtN3
+ vtExtrExit:normalize()
+ vtExtrExit = -vtExtrExit
+ -- calcolo di quanto entrare
+ local dLenAdd = abs( (dMillDiam/2) / cos( nPathData[i][2]/2)) + dExtraCorner - (dMillDiam/2)
+ -- linea intermedia (componente lunghezza utensile in direzione bisettrice)
+ local pEnd = ptP1 + ( dLenAdd * vtExtrExit)
+ nAuxId = EgtLine( nAddGrpId, ptP1, pEnd, GDB_RT.GLOB)
+ table.insert( nPath, nAuxId)
+ -- linea di ritorno
+ nAuxId = EgtLine( nAddGrpId, pEnd, ptP1, GDB_RT.GLOB)
+ table.insert( nPath, nAuxId)
+ end
+ end
+ -- ricreo il percorso
+ AuxId = EgtCurveCompo( nAddGrpId, nPath, true)
+ end
+ if not AuxId then
+ local sErr = 'Error : Impossibe make custom machining path'
+ return 0, sErr
+ end
+
+ return AuxId
+end
+
+---------------------------------------------------------------------
+local function CalcInterference( nNewProc, vtExtr, ptCentr, dDiam1, dDiam2,
+ dTall1, dTall2, dDiam3, dTall3)
+
+ local ptCentrGrid1 = ptCentr + ( vtExtr * 0.01)
+ local frOriTool = Frame3d( ptCentrGrid1, vtExtr)
+ local bColl1 = EgtCDeConeSolid( frOriTool, dDiam1/2, dDiam2/2, dTall1, nNewProc, 0, GDB_RT.GLOB)
+ if bColl1 then return true end
+ local ptCentrGrid2 = ptCentr + ( vtExtr * ( dTall1 + 0.01))
+ frOriTool = Frame3d( ptCentrGrid2, vtExtr)
+ local bColl2 = EgtCDeCylSolid( frOriTool, dDiam2/2, (dTall2-dTall1), nNewProc, 0, GDB_RT.GLOB)
+ if bColl2 then return true end
+ local ptCentrGrid3 = ptCentr + ( vtExtr * ( dTall2 + 0.01))
+ frOriTool = Frame3d( ptCentrGrid3, vtExtr)
+ local bColl3 = EgtCDeCylSolid( frOriTool, dDiam3/2, (dTall3-dTall2), nNewProc, 0, GDB_RT.GLOB)
+ if bColl3 then return true end
+ -- restituisco risultato controllo collisioni
+ return false
+end
+
+---------------------------------------------------------------------
+local function MakeLocalSurf( ptP1, ptP2, ptP3, nAddGrpId)
+
+ if not ptP1 or not ptP2 or not ptP3 then
+ return nil
+ end
+
+ local pAuxId = {}
+ local nAuxId, AuxId
+ nAuxId = EgtLine( nAddGrpId, ptP1, ptP2, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ nAuxId = EgtLine( nAddGrpId, ptP2, ptP3, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ nAuxId = EgtLine( nAddGrpId, ptP3, ptP1, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ -- trasformo in percorso
+ if #pAuxId ~= 3 then
+ return nil
+ end
+ AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true)
+ -- se non c'é il percorso esco
+ if not AuxId then
+ return nil
+ end
+ -- creo la superfice piana
+ local nidFace = EgtSurfTmByFlatContour( nAddGrpId, AuxId, 0.01)
+ if not nidFace then
+ EgtErase(AuxId)
+ return nil
+ end
+ -- se normale negativa inverto
+ local _, vtN1 = EgtSurfTmFacetCenter( nidFace, 0, GDB_ID.ROOT)
+ if vtN1:getZ() < -0.5 then EgtInvertSurf( nidFace) end
+
+ EgtErase(AuxId)
+ return nidFace
+end
+
+---------------------------------------------------------------------
+local function AddMillCornerMachining( nPartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, dOffsAng, dDepthMach,
+ bThruThick, dThSurf, dDiam1, dDiam2, dTall1,
+ dTall2, dDiam3, dTall3, bMakeLocSurf, vFace)
+ -- variabili costruzione geometria
+ local pAuxId = {}
+ local nAuxId
+ local ptApPoint
+ local AuxId
+ local nNewProcLoc
+ -- se devo creare superfice locale
+ if bMakeLocSurf then
+ -- creo superfice locale o esco
+ local nSurfToAdd = MakeLocalSurf( tFacAdj[1][7], tFacAdj[1][8], tFacAdj[1][9], nAddGrpId)
+ if nSurfToAdd then
+ local nFacCntPre = EgtSurfTmFacetCount( nNewProc)
+ -- creo copia del percorso principale e gli aggiungo la nuova faccia
+ nNewProcLoc = EgtCopyGlob( nNewProc, nAddGrpId)
+ nNewProcLoc = EgtSurfTmBySewing( nAddGrpId, {nNewProcLoc,nSurfToAdd} , true)
+ -- riordino le facce
+ ReorderFacesFromTab( nNewProcLoc, vFace)
+ -- acquisisco il numero della faccia
+ nFacCnt = EgtSurfTmFacetCount( nNewProcLoc)
+ nFacInd = nFacCnt - 1
+ else
+ return true, ''
+ end
+ else
+ nNewProcLoc = nNewProc
+ end
+ -- prendo il primo versore
+ local _, vtN1 = EgtSurfTmFacetCenter( nNewProcLoc, nFacInd, GDB_ID.ROOT)
+ local _, vtN2 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[1][1], GDB_ID.ROOT)
+ local _, vtN3 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[1][2], GDB_ID.ROOT)
+ -- trovo il punto sulla superfice di riferimento
+ local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1][1], GDB_ID.ROOT)
+ local _, ptLocP3, ptLocP4, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1][2], GDB_ID.ROOT)
+ -- se ho creato faccia locale su copia superficie, cancella la copia
+ if bMakeLocSurf then
+ EgtErase( nNewProcLoc)
+ end
+ local nIdIniPoint
+ local nIdEndPoint
+ if ptLocP1 and ptLocP2 then
+ if ( dist( ptLocP1, tFacAdj[1][4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][4]) < GEO.EPS_SMALL) then
+ nIdEndPoint = 4
+ nIdIniPoint = 5
+ elseif ( dist( ptLocP1, tFacAdj[1][5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][5]) < GEO.EPS_SMALL) then
+ nIdEndPoint = 5
+ nIdIniPoint = 4
+ end
+ end
+ -- versore direzione
+ local vtExtr = tFacAdj[1][nIdIniPoint] - tFacAdj[1][nIdEndPoint]
+ vtExtr:normalize()
+ -- versore direzione di uscita
+ local vtExtrExit
+ -- inserisco le prime tre linee
+ if nIdIniPoint and nIdEndPoint then
+ -- se fresatura da sotto salto la lavorazione
+ if vtExtr:getZ() < WD.DRILL_VZ_MIN then
+ local sErr = 'Error : Impossible insert clean corner from bottom'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- sommo i tre versori per avere una direzione media
+ vtExtrExit = vtN2 + vtN3
+ vtExtrExit:normalize()
+ -- se tipo 1 calcolo angolo tilt di 45°
+ if nTypeConeCut == 1 then
+ vtExtr = vtExtrExit + Z_AX()
+ -- altrimenti tipo 2, calcolo angolo tilt di 33° (dalla verticale)
+ else
+ vtExtr = vtExtrExit + Vector3d(0,0,1.539865)
+ end
+ vtExtr:normalize()
+ local vtCheck = Vector3d(vtExtr)
+ -- se ho un offset angolare ruoto il percorso
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ vtCheck:rotate( Z_AX(), dOffsAng)
+ end
+ -- controllo se c'è collisione con le facce della superfice
+ if nTypeConeCut == 1 and CalcInterference( nNewProc, vtCheck, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), dDiam1, dDiam2,
+ dTall1, dTall2, dDiam3, dTall3) then
+ local sErr = 'Collision detect from clean corner tool and surface'
+ EgtOutLog( sErr)
+ return true, ''
+ end
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdIniPoint], tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ -- se uso utensile cono 60°
+ if nTypeConeCut == 1 then
+ -- se offset angolare valido e/o negativo creo il baffo precedente
+ if dOffsAng < ( 100 * GEO.EPS_SMALL) then
+ -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
+ if dist( tFacAdj[1][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
+ ptApPoint = ptLocP2
+ else
+ ptApPoint = ptLocP1
+ end
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.2)
+ -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta
+ if dLenTrimExt > 10 * GEO.EPS_SMALL then
+ EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ -- prendo il nuovo punto finale
+ ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach)
+ else
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ end
+ table.insert( pAuxId, nAuxId)
+ -- creo linea di ritorno
+ nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ end
+ end
+ end
+ -- inserisco le ultime tre linee
+ -- trovo il secondo punto sulla superfice di riferimento
+ ptLocP1, ptLocP2 = ptLocP3, ptLocP4
+ if ptLocP1 and ptLocP2 then
+ -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
+ if dist( tFacAdj[1][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
+ ptApPoint = ptLocP2
+ else
+ ptApPoint = ptLocP1
+ end
+ -- se uso utensile cono 60°
+ if nTypeConeCut == 1 then
+ -- se offset angolare valido e/o negativo creo il baffo precedente
+ if dOffsAng > -( 100 * GEO.EPS_SMALL) then
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.2)
+ -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta
+ if dLenTrimExt > 10 * GEO.EPS_SMALL then
+ EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ -- prendo il nuovo punto finale
+ ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach)
+ else
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ end
+ table.insert( pAuxId, nAuxId)
+ -- creo linea di ritorno
+ nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ end
+ -- ultima linea di distacco (5mm in direzione utensile)
+ local pEnd = tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr)
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ else
+ -- linea di distacco (2mm in direzione utensile)
+ local pEnd = tFacAdj[1][nIdEndPoint] + ( 2 * vtExtr)
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint], pEnd, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ -- ultima linea di risalita in Z
+ local pIni = pEnd
+ pEnd = pIni + ( dThick * Z_AX())
+ nAuxId = EgtLine( nAddGrpId, pIni, pEnd, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ end
+ end
+ -- trasformo in percorso
+ if #pAuxId > 0 then
+ AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true)
+ end
+ -- se non c'é il percorso do errore
+ if not AuxId then
+ local sErr = 'Error : impossible make clean corner path'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- modifico versore direzione
+ EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB)
+ -- se ho un offset angolare ruoto il percorso
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( AuxId, tFacAdj[1][nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB)
+ end
+ -- inserisco la lavorazione
+ local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc))
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', nPartId)
+ -- se flag lavorazione spessore passante setto la nota per spostarla dopo i tagli di lama
+ if bThruThick and nTypeConeCut == 1 then
+ EgtSetInfo( nMchId, 'MOVE_AFTER', 1)
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_YM
+ if vtExtr:getY() > 100 * GEO.EPS_ZERO then
+ nSCC = MCH_SCC.ADIR_YP
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, 0)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 4)
+ -- allungo inizio e fine di 10mm
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10)
+ -- setto affondamento 0
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ -- Note utente con dichiarazione nessuna generazione sfridi per Vmill
+ local sUserNotes = 'VMRS=0;'
+ -- aggiungo alle note massima elevazione
+-- sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dMaxDepth, 1) .. ';'
+ sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( 0.0, 1) .. ';'
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ else
+ local _, sWarn = EgtGetMachMgrWarning( 0)
+ if EgtIsMachiningEmpty() then
+ EgtSetOperationMode( nMchId, false)
+ return false, sWarn
+ end
+ end
+
+ return true, ''
+end
+
+---------------------------------------------------------------------
+local function AddMillCorner( nTypeConeCut, vFace, Proc, nRawId, b3Raw,
+ dToolDiam, nAddGrpId, dThick, nMasterNewProc, dDepthMach,
+ bThruThick)
+
+ local sMilling, dMaxDepth
+ -- se ripresa angolo con fresa cono 60° con ripresa
+ if nTypeConeCut == 1 then
+ -- recupero la lavorazione di fresatura
+ sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner60')
+ if not sMilling then
+ local sErr = 'Error : CleanCorner 60 not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se ripresa angolo con fresa cono piccola senza ripresa
+ else
+ sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner30')
+ if not sMilling then
+ local sErr = 'Error : CleanCorner 30 not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMillTotDiam = 20
+ local dMillDiamTh = 20
+ local dToolLength = 20
+ local dThickTool = 20
+ local dSideAng = 0
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh
+ dMillTotDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) or dMillTotDiam
+ dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or dSideAng
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dThickTool = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dThickTool
+ dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength
+ dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth -- qui è la distanza dal portautensile
+ -- calcolo il secondo diametro del cono
+ dMillTotDiam = dMillDiam + ( abs(dThickTool) * tan(dSideAng)) * 2
+ end
+ end
+ -- copio la feature nel layer di appoggio
+ local nNewProc
+ if nMasterNewProc then
+ nNewProc = nMasterNewProc
+ else
+ nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
+ end
+ local nFacCnt = EgtSurfTmFacetCount( nNewProc)
+ local nFacInd, dDimMin, dDimMax, dDepth, nSurfInt
+ local bMakeLocSurf
+ if nFacCnt <= 4 then
+ -- ottengo le dimensioni apertura, la normale e la faccia inferiore
+ dDimMin, dDimMax, dDepth, _, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId)
+ if nSurfInt then
+ -- uso la dimensione minima anche nel caso che la cava sborda perchè la lavorazione potrebbe collidere con un pezzo limitrofo
+ local dMinWidth = dDimMin
+ nNewProc = EgtSurfTmBySewing( nAddGrpId, {nNewProc,nSurfInt} , true)
+ -- riordino le facce
+ ReorderFacesFromTab( nNewProc, vFace)
+ -- acquisisco il numero della faccia
+ nFacCnt = EgtSurfTmFacetCount( nNewProc)
+ nFacInd = nFacCnt - 1
+ else
+ return true
+ --local sErr = 'Error : cannot create base surface'
+ --EgtOutLog( sErr)
+ --return false, sErr
+ end
+ else
+ bMakeLocSurf = true
+ end
+ -- verifico se ciclo chiuso
+ local bClosed = ( abs( vFace[1].PrevAng) > 0.1)
+ -- ciclo di inserimento delle fresate sulle facce del contorno in esame
+ local i = 1
+ -- se faccia finale con fine non lavorato, forzo partenza da prima faccia non tutta saltata (tipo 4)
+ if bClosed and ( vFace[#vFace].Type == 4 or ( vFace[#vFace].Type & 2) ~= 0) then
+ while i <= #vFace and vFace[i].Type == 4 do
+ i = i + 1
+ end
+ end
+ -- se facce tutte da saltare, parto dall'inizio
+ local bAllType4 = ( i > #vFace)
+ if bAllType4 or bClosed then i = 1 end
+ while i <= #vFace do
+ -- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura
+ if ( vFace[i].Type & 2) ~= 0 or vFace[i].Type == 4 then
+ -- variabili costruzione geometria
+ local tFacAdj = {}
+ local nFace1 = vFace[i].Fac
+ local nFace2
+ -- ricavo i tre punti per eventuale superficie locale
+ local ptLoc1, ptLoc2, ptLoc3
+ -- punto precedente (punto precedente della faccia [i])
+ ptLoc3 = vFace[i].PPrev
+ -- aggiungo geometria
+ i = i + 1
+ local j = EgtIf( i <= #vFace, i, EgtIf( bClosed, 1, nil))
+ if not j then
+ return true
+ end
+ nFace2 = vFace[j].Fac
+ -- punto in comune tra le due facce (punto precedente della faccia [j])
+ ptLoc1 = vFace[j].PPrev
+ -- punto successivo ( precedente della faccia successiva)
+ j = j + 1
+ local k = EgtIf( j <= #vFace, j, EgtIf( bClosed, 1, nil))
+ -- se è un percorso aperto prendo il punto medio della seconda faccia come punto locale 2
+ if not k then
+ ptLoc2 = Point3d( vFace[j-1].Cen:getX(), vFace[j-1].Cen:getY(), ptLoc1:getZ())
+ else
+ ptLoc2 = vFace[k].PPrev
+ end
+ -- ricavo i punti e l'angolo interno
+ local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( nNewProc, nFace1, nFace2, GDB_ID.ROOT)
+ -- se punti validi e angolo è interno e non è quasi piatto e >= 90 creo istanza
+ if ptP1 and ptP2 and dAng < 0 and dAng < -6 and dAng > EgtIf( nTypeConeCut == 1, -(90 + 10 * GEO.EPS_SMALL), -(180-dAngleSmall + 10 * GEO.EPS_SMALL)) then
+ local dLen = dist( ptP1, ptP2)
+ table.insert( tFacAdj, { nFace1, nFace2, dLen, ptP1, ptP2, dAng, ptLoc1, ptLoc2, ptLoc3})
+ end
+ -- se ho un elemento creo percorso o percorsi in base al tipo di cono e all'apertura dall'angolo rispetto ai 90°
+ -- con una tolleranza di 2 gradi
+ if #tFacAdj > 0 then
+ if nTypeConeCut == 1 and bMakeTwinCut and (dAng + 90) > 2 then
+ local dAngOffs = (dAng + 90) / 2
+ -- primo taglio
+ local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, -dAngOffs, dDepthMach,
+ bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
+ dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
+ if not bOk then return bOk, sErr end
+ -- secondo taglio
+ bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, dAngOffs, dDepthMach,
+ bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
+ dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
+ if not bOk then return bOk, sErr end
+ -- altrimenti ho un solo percorso
+ else
+ local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, 0, dDepthMach,
+ bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
+ dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
+ if not bOk then return bOk, sErr end
+ end
+ end
+ else
+ i = i + 1
+ end
+ end
+ -- cancello la copia della superfice
+ if nNewProc then
+ EgtErase( nNewProc)
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
+ local CosA = abs( vtNz)
+ if CosA >= 0.05 then
+ local SinA = sqrt( 1 - CosA * CosA)
+ local dRad = dDiamTh / 2 + dMillDiam / 2 * EgtIf( vtNz > 0, -1, 1)
+ local dSlantFreeLen = dFreeLen - ( dRad * CosA / SinA)
+ return min( dMaxDepth, dSlantFreeLen)
+ else
+ return dMaxDepth
+ end
+end
+
+---------------------------------------------------------------------
+local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId)
+ -- flag per fresature non passanti
+ local bNotThrou
+ local dThick
+ local dOriDepth
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMaxDepth = 0
+ local dFreeLen = 0
+ local dDiamTh = 0
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dDiamTh = EgtTdbGetCurrToolThDiam()
+ dFreeLen = EgtTdbGetCurrToolMaxDepth()
+ dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), dFreeLen) or dMaxDepth
+ end
+ end
+ -- verifico se ciclo chiuso
+ local bClosed = ( abs( vFace[1].PrevAng) > 0.1)
+ -- ciclo di inserimento delle fresate sulle facce del contorno in esame
+ local i = 1
+ -- se faccia finale con fine non lavorato, forzo partenza da prima faccia non tutta saltata (tipo 4)
+ if bClosed and ( ( vFace[#vFace].Type == 4 and vFace[#vFace].Edges > 3) or ( vFace[#vFace].Type & 2) ~= 0) then
+ while i <= #vFace and vFace[i].Type == 4 and vFace[i].Edges > 3 and abs( vFace[i].SideAng) < 0.1 do
+ i = i + 1
+ end
+ end
+ -- se facce tutte da saltare, parto dall'inizio
+ local bAllType4 = ( i > #vFace)
+ if bAllType4 then i = 1 end
+ while i <= #vFace do
+ -- se inizio faccia senza taglio e non è successiva di senza taglio, inserisco una fresatura
+ local j = EgtIf( i > 1, i - 1, EgtIf( bClosed, #vFace, nil))
+ if ( vFace[i].Type & 1) ~= 0 and ( not j or vFace[j].Type == 0 or vFace[j].Type == 1 or abs( vFace[i].SideAng) > 0.1 or abs( vFace[j].SideAng) > 0.1) then
+ -- inserisco la lavorazione
+ local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return 0, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- calcolo l'affondamento
+ local dDepth = vFace[i].Width + WD.CUT_EXTRA
+ dThick = vFace[i].Width
+ local vtNz = vFace[i].Norm:getZ()
+ if WD.CHECK_MIN_Z_SAW then
+ if vtNz >= 0 then
+ dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW)
+ else
+ dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz))
+ end
+ end
+ local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
+ -- se affondamento superiore ai limiti della fresa
+ if dDepth > dCurrMaxDepth then
+ dOriDepth = dDepth
+ -- lo limito e tolgo eventuali Tabs
+ dDepth = dCurrMaxDepth
+ EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
+ bNotThrou = true
+ end
+ -- tolgo i Tabs se devo rimuovere lo sfrido
+ if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
+ local dSal = 0
+ if #vFace == 1 then dSal = -dMillDiam / 2 end
+ -- se angolo interno prima
+ if vFace[i].PrevAng < -30 then
+ local dSinA = -sin( vFace[i].PlPrevAng + 90)
+ local dTanA = -tan( vFace[i].PlPrevAng + 90)
+ dSal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[i].Width * vFace[i].Norm:getZ() * dTanA)
+ -- se faccia precedente inclinata verso il basso
+ if j and vFace[j].Norm:getZ() < -0.017 then
+ dSal = dSal + vFace[j].Width * vFace[j].Norm:getZ()
+ end
+ -- se angolo esterno prima
+ elseif vFace[i].PrevAng > 30 then
+ -- se faccia precedente inclinata verso il basso
+ if j and vFace[j].Norm:getZ() < -0.017 then
+ dSal = dSal - vFace[j].Width * vFace[j].Norm:getZ()
+ end
+ end
+ local dEal = vFace[i].Whisk - vFace[i].Len
+ -- se angolo interno prima e faccia precedente inclinata verso l'alto oltre 16.1deg
+ if vFace[i].PrevAng < -30 and j and vFace[j].Norm:getZ() < 0.96078 and vFace[j].Norm:getZ() > 0 then
+ dEal = dEal + vFace[j].Width * vFace[j].Norm:getZ()
+ end
+ -- se angolo interno dopo e faccia successiva inclinata verso l'alto oltre 16.1deg
+ local k = EgtIf( i < #vFace, i + 1, EgtIf( bClosed, 1, nil))
+ if k and vFace[k].PrevAng < -30 and vFace[k].Norm:getZ() < 0.96078 and vFace[k].Norm:getZ() > 0 then
+ dEal = dEal + vFace[k].Width * vFace[k].Norm:getZ()
+ -- se l'inclinazione è inferiore a 46.1deg
+ if vFace[k].Norm:getZ() > 0.72055 then
+ dEal = dEal - vFace[k].Width
+ end
+ end
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno utilizzo faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if abs( vFace[i].Norm:getZ()) < GEO.EPS_SMALL then
+ nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return 0, sErr
+ end
+ end
+ -- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura
+ if ( vFace[i].Type & 2) ~= 0 or ( vFace[i].Type == 4 and vFace[i].Edges > 3) then
+ -- inserisco la lavorazione
+ local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return 0, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- calcolo l'affondamento
+ local dDepth = vFace[i].Width + WD.CUT_EXTRA
+ dThick = vFace[i].Width
+ local vtNz = vFace[i].Norm:getZ()
+ if WD.CHECK_MIN_Z_SAW then
+ if vtNz >= 0 then
+ dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW)
+ else
+ dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz))
+ end
+ end
+ local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
+ -- se affondamento superiore ai limiti della fresa
+ if dDepth > dCurrMaxDepth then
+ dOriDepth = dDepth
+ -- lo limito e tolgo eventuali Tabs
+ dDepth = dCurrMaxDepth
+ EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
+ bNotThrou = true
+ end
+ -- tolgo i Tabs se devo rimuovere lo sfrido
+ if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
+ -- aggiungo geometria
+ local vGeom = {{ Proc.Id, vFace[i].Fac}}
+ local dSal = EgtIf( ( vFace[i].Type & 2) ~= 0, vFace[i].Whisk - vFace[i].Len, 0)
+ local dEal = 0
+ local OrigI = i
+ local OrigH = j
+ local LastJ
+ i = i + 1
+ local j = EgtIf( i <= #vFace, i, EgtIf( bAllType4 or not bClosed, nil, 1))
+ while j and ( ( vFace[j].Type & 1) ~= 0 or ( vFace[j].Type == 4 and vFace[j].Edges > 3)) and abs( vFace[j].SideAng) < 0.1 and abs( vFace[OrigI].SideAng) < 0.1 do
+ table.insert( vGeom, { Proc.Id, vFace[j].Fac})
+ LastJ = j
+ dEal = EgtIf( ( vFace[j].Type & 1) ~= 0, vFace[j].Whisk - vFace[j].Len, 0)
+ if ( vFace[j].Type & 1) ~= 0 then
+ break
+ end
+ i = i + 1
+ j = EgtIf( j + 1 <= #vFace, j + 1, EgtIf( bAllType4 or not bClosed, nil, 1))
+ end
+ -- se faccia singola è da fare tutta senza oltrepassare estremi
+ if #vFace == 1 and vFace[OrigI].Type == 4 and vFace[OrigI].Edges > 3 then
+ dSal = -dMillDiam / 2
+ dEal = -dMillDiam / 2
+ -- altrimenti va verificato
+ else
+ -- se lavorazione completa su faccia iniziale
+ if vFace[OrigI].Type == 4 and vFace[OrigI].Edges > 3 then
+ -- se angolo interno prima
+ if vFace[OrigI].PrevAng < -30 then
+ local dSinA = -sin( vFace[OrigI].PlPrevAng + 90)
+ local dTanA = -tan( vFace[OrigI].PlPrevAng + 90)
+ dSal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[OrigI].Width * vFace[OrigI].Norm:getZ() * dTanA)
+ -- se faccia precedente inclinata verso il basso
+ if OrigH and vFace[OrigH].Norm:getZ() < -0.017 then
+ dSal = dSal + vFace[OrigH].Width * vFace[OrigH].Norm:getZ()
+ end
+ -- se angolo esterno prima
+ elseif vFace[OrigI].PrevAng > 30 then
+ -- se faccia precedente inclinata verso il basso
+ if OrigH and vFace[OrigH].Norm:getZ() < -0.017 then
+ dSal = dSal - vFace[OrigH].Width * vFace[OrigH].Norm:getZ()
+ end
+ end
+ end
+ -- se lavorazione completa o finale su faccia finale
+ local LastFace = ( LastJ or OrigI)
+ local OrigK = EgtIf( LastFace < #vFace, LastFace + 1, EgtIf( bClosed, 1, nil))
+ if ( vFace[LastFace].Type == 4 and vFace[LastFace].Edges > 3) or ( LastFace == OrigI and ( vFace[LastFace].Type & 2) ~= 0) then
+ -- se angolo interno dopo
+ if OrigK and vFace[OrigK].PrevAng < -30 then
+ local dSinA = -sin( vFace[OrigK].PlPrevAng + 90)
+ local dTanA = -sin( vFace[OrigK].PlPrevAng + 90)
+ dEal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[OrigI].Width * vFace[OrigI].Norm:getZ() * dTanA)
+ -- se faccia successiva inclinata verso il basso
+ if vFace[OrigK].Norm:getZ() < -0.017 then
+ dEal = dEal + vFace[OrigK].Width * vFace[OrigK].Norm:getZ()
+ end
+ -- se angolo esterno dopo
+ elseif OrigK and vFace[OrigK].PrevAng > 30 then
+ -- se faccia successiva inclinata verso il basso
+ if vFace[OrigK].Norm:getZ() < -0.017 then
+ dEal = dEal - vFace[OrigK].Width * vFace[OrigK].Norm:getZ()
+ end
+ end
+ end
+ -- per sola lavorazione finale
+ if LastFace == OrigI and ( vFace[LastFace].Type & 2) ~= 0 then
+ -- se angolo interno dopo e faccia successiva inclinata verso l'alto oltre 16.1 deg
+ if OrigK and vFace[OrigK].PrevAng < -30 and vFace[OrigK].Norm:getZ() < 0.96078 and vFace[OrigK].Norm:getZ() > 0 then
+ dSal = dSal + vFace[OrigK].Width * vFace[OrigK].Norm:getZ()
+ end
+ -- se angolo interno prima e faccia precedente inclinata verso l'alto oltre 16.1 deg
+ if vFace[OrigI].PrevAng < -30 and OrigH and vFace[OrigH].Norm:getZ() < 0.96078 and vFace[OrigH].Norm:getZ() > 0 then
+ dSal = dSal + vFace[OrigH].Width * vFace[OrigH].Norm:getZ()
+ -- se l'inclinazione è inferiore a 46.1deg
+ if vFace[OrigH].Norm:getZ() > 0.72055 then
+ dSal = dSal - vFace[OrigH].Width
+ end
+ end
+ end
+ -- se percorso chiuso e completo con fresa
+ if bClosed and bAllType4 then
+ dSal = 0
+ dEal = 0
+ end
+ -- se faccia singola non oltrepasso l'estremo finale
+ if #vFace == 1 then
+ dEal = -dMillDiam / 2
+ end
+ end
+ -- se non devo scaricare l'angolo o la faccia è inclinata
+ if nConeCut <= 1 or abs( vFace[OrigI].SideAng) > 0.1 then
+ EgtSetMachiningGeometry( vGeom)
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- tolgo i Tabs se devo rimuovere lo sfrido
+ if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno utilizzo faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- posizione braccio porta testa
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP)
+ -- posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if abs( vFace[OrigI].Norm:getZ()) < GEO.EPS_SMALL then
+ nSCC = EgtIf( abs( vFace[OrigI].Norm:getX()) > abs( vFace[OrigI].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- altrimenti se devo fare rientranza per inserimento utensile cono 30°
+ elseif nConeCut == 2 then
+ -- eseguo la costruzione del percorso
+ local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick)
+ if nPathId == 0 then return 0, sErr end
+ EgtSetMachiningGeometry({{ nPathId, -1}})
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno utilizzo faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
+ -- assegno affondamento
+-- EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ if bNotThrou then
+ EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth - dOriDepth))
+ else
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ end
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
+ -- posizione braccio porta testa
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP)
+ -- altrimenti se devo scaricare l'angolo
+ elseif nConeCut == 3 then
+ -- eseguo la costruzione del percorso
+ local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, nil, bClosed and bAllType4)
+ if nPathId == 0 then return 0, sErr end
+ EgtSetMachiningGeometry({{ nPathId, -1}})
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno affondamento
+ if bNotThrou then
+ EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth - dOriDepth))
+ else
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ end
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
+ -- posizione braccio porta testa
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return 0, sErr
+ end
+ else
+ i = i + 1
+ end
+ end
+ -- aggiungo eventuali fresature a metà faccia
+ for i =1, #vFace do
+ if vFace[i].Split then
+ -- inserisco la lavorazione
+ local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_M'
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return 0, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- calcolo l'affondamento
+ local dDepth = vFace[i].Width + WD.CUT_EXTRA
+ dThick = vFace[i].Width
+ local vtNz = vFace[i].Norm:getZ()
+ if WD.CHECK_MIN_Z_SAW then
+ if vtNz >= 0 then
+ dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW)
+ else
+ dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz))
+ end
+ end
+ local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen)
+ -- se affondamento superiore ai limiti della fresa
+ if dDepth > dCurrMaxDepth then
+ dOriDepth = dDepth
+ -- lo limito e tolgo eventuali Tabs
+ dDepth = dCurrMaxDepth
+ EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
+ bNotThrou = true
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
+ local dSal = vFace[i].Whisk - vFace[i].Len / 2
+ local dEal = vFace[i].Whisk - vFace[i].Len / 2
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno utilizzo faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if abs( vFace[i].Norm:getZ()) < GEO.EPS_SMALL then
+ nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return 0, sErr
+ end
+ end
+ end
+ -- se fresature non sono passanti
+ if bNotThrou then
+ return 2, dMillDiam, dThick
+ end
+
+ return 1, dMillDiam, dThick
+end
+
+---------------------------------------------------------------------
+local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw)
+ -- flag per tagli non passanti
+ local bNotThrou
+ local dThick
+ -- recupero i dati dell'utensile
+ local dSawDiam = 0
+ local dMaxDepth = 0
+ local dSawThick = 0
+ if EgtMdbSetCurrMachining( sSawing) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam
+ dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
+ dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
+ end
+ end
+ -- Calcolo angolo 3° asse rot (da direz. utensile)
+ local sRot3Ang = 'A1=180'
+ if WD.GetChainSawBlockedAxis then
+ sRot3Ang = WD.GetChainSawBlockedAxis( 1)
+ end
+ -- ciclo di inserimento dei tagli con sega a catena
+ for i = 1, #vFace do
+ -- se inizio faccia non tagliato completamente, inserisco un ripasso con sega a catena
+ if ( vFace[i].Type & 1) ~= 0 then
+ -- inserisco la lavorazione
+ local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
+ local nMchId = EgtAddMachining( sName, sSawing)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
+ EgtOutLog( sErr)
+ return 0, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- calcolo l'affondamento
+ local dDepth = vFace[i].Width + min( WD.CUT_EXTRA, -WD.MIN_Z_SAW)
+ dThick = vFace[i].Width
+ -- se affondamento superiore ai limiti della sega a catena
+ if dDepth > dMaxDepth then
+ dDepth = dMaxDepth
+ bNotThrou = true
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
+ local dSal = - dSawDiam / 2
+ local dEal = vFace[i].Whisk - vFace[i].Len - dSawDiam / 2
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno utilizzo faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
+ -- imposto angolo 3° asse rot
+ EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- posizione braccio porta testa
+ if vFace[i].Norm:getX() < 0.018 then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.OPPOSITE)
+ EgtSetMachiningParam( MCH_MP.OFFSR, dSawThick)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return 0, sErr
+ end
+ end
+ -- se fine faccia non tagliato completamente o faccia non tagliata completamente e abbastanza lunga, inserisco un ripasso con sega a catena
+ if ( vFace[i].Type & 2) ~= 0 or ( vFace[i].Type == 4 and vFace[i].Edges > 3 and vFace[i].Len > dSawDiam + 1) then
+ -- inserisco la lavorazione
+ local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId))
+ local nMchId = EgtAddMachining( sName, sSawing)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
+ EgtOutLog( sErr)
+ return 0, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- calcolo l'affondamento
+ local dDepth = vFace[i].Width + min( WD.CUT_EXTRA, -WD.MIN_Z_SAW)
+ dThick = vFace[i].Width
+ -- se affondamento superiore ai limiti della sega a catena
+ if dDepth > dMaxDepth then
+ dDepth = dMaxDepth
+ bNotThrou = true
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}})
+ local dSal = - dSawDiam / 2
+ local dEal = - dSawDiam / 2
+ if ( vFace[i].Type & 2) ~= 0 then
+ dSal = vFace[i].Whisk - vFace[i].Len - dSawDiam / 2
+ end
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno utilizzo faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN)
+ -- imposto angolo 3° asse rot
+ EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- posizione braccio porta testa
+ if vFace[i].Norm:getX() < 0.018 then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.OPPOSITE)
+ EgtSetMachiningParam( MCH_MP.OFFSR, dSawThick)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return 0, sErr
+ end
+ end
+ end
+ -- se fresature non sono passanti
+ if bNotThrou then
+ return 2, dSawThick, dThick
+ end
+ return 1, dSawThick, dThick
+end
+
+---------------------------------------------------------------------
+local function AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick)
+ -- ciclo di inserimento dei tagli sulle facce del contorno in esame
+ for i = 1, #vFace do
+ -- verifico se faccia da saltare, perchè macchina travi e faccia su bordo longitudinale esterno già finito
+ local bToSkip = ( WD.BEAM_MACHINE and IsPointOnRawLongEdges( vFace[i].Cen, b3Raw))
+ -- se non è faccia da saltare, inserisco il taglio di lama
+ if not bToSkip and vFace[i].Type ~= 4 then
+ -- indice del successivo
+ local j = EgtIf( i < #vFace, i + 1, 1)
+ -- inserisco la lavorazione
+ local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. tostring( i)
+ local nMchId = EgtAddMachining( sName, sCutting)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ local dSpeed = EgtGetMachiningParam( MCH_MP.SPEED)
+ local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
+ local bGearbox = EgtGetInfo( EgtGetHeadId( sHead) or GDB_ID.NULL, 'Gearbox', 'b')
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( { { Proc.Id, vFace[i].Fac}})
+ -- calcolo l'affondamento
+ local dDepth = vFace[i].Depth
+ local vtNz = vFace[i].Norm:getZ()
+ if WD.CHECK_MIN_Z_SAW then
+ if vtNz >= 0 then
+ dDepth = min( dDepth, -WD.MIN_Z_SAW)
+ else
+ dDepth = min( dDepth, -WD.MIN_Z_SAW + dSawThick * vtNz)
+ end
+ end
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- verifico se va invertita la direzione di lavorazione perchè faccia verso l'alto (angolo maggiore di 0.01 deg)
+ local bInvert = ( vFace[i].Norm:getZ() > 0.0001745)
+ -- imposto inversione
+ EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
+ -- imposto lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bInvert, MCH_SAW_WS.LEFT, MCH_SAW_WS.RIGHT))
+ -- lato mandrino ( standard a sinistra se rotazione CCW, altrimenti a destra, oppure da funzione di macchina)
+ local nHeadSide = EgtIf( dSpeed < 0, MCH_SAW_HS.LEFT, MCH_SAW_HS.RIGHT)
+ if WD.GetSawHeadSide then nHeadSide = WD.GetSawHeadSide( dSpeed, sHead) end
+ EgtSetMachiningParam( MCH_MP.HEADSIDE, nHeadSide)
+ -- assegno i dati di attacco (sicurezza solo se angolo interno)
+ local nLeadIn = MCH_SAW_LI.CENT
+ if ( not bInvert and ( vFace[i].Type & 1) ~= 0) or ( bInvert and ( vFace[i].Type & 2) ~= 0) then
+ nLeadIn = MCH_SAW_LI.STRICT
+ end
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, nLeadIn)
+ local dSal = 0
+ if ( not bInvert and vFace[i].PrevAng < -0.1) or ( bInvert and vFace[j].PrevAng < -0.1) then
+ dSal = -WHISK_SAFE
+ end
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal)
+ -- assegno i dati di uscita (sicurezza solo se angolo interno)
+ local nLeadOut = MCH_SAW_LO.CENT
+ if ( not bInvert and ( vFace[i].Type & 2) ~= 0) or ( bInvert and ( vFace[i].Type & 1) ~= 0) then
+ nLeadOut = MCH_SAW_LO.STRICT
+ end
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, nLeadOut)
+ local dEal = 0
+ if ( not bInvert and vFace[j].PrevAng < -0.1) or ( bInvert and vFace[i].PrevAng < -0.1) then
+ dEal = -WHISK_SAFE
+ end
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal)
+ -- posizione braccio porta testa
+ if not bGearbox then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_NEAR)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ -- provo a invertire direzione, lato di lavoro e attacco/uscita
+ EgtSetMachiningParam( MCH_MP.INVERT, not bInvert)
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( not bInvert, MCH_SAW_WS.LEFT, MCH_SAW_WS.RIGHT))
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, EgtIf( nLeadOut == MCH_SAW_LO.STRICT, MCH_SAW_LI.STRICT, MCH_SAW_LI.CENT))
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, EgtIf( nLeadIn == MCH_SAW_LI.STRICT, MCH_SAW_LO.STRICT, MCH_SAW_LO.CENT))
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal)
+ -- ri-eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ end
+ end
+ -- se limite lunghezza di taglio e taglio lo supera
+ if WD.CUT_MAX_LENGTH and vFace[i].Len > WD.CUT_MAX_LENGTH then
+ -- sdoppio la lavorazione
+ local sSouName = EgtGetName( nMchId)
+ local nNewMchId = EgtCopyMachining( sSouName..'_B', sSouName)
+ --accorciamento iniziale della seconda
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.STRICT)
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, -vFace[i].Len/2)
+ --accorciamento finale della prima
+ EgtSetCurrMachining( nMchId)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.STRICT)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, -vFace[i].Len/2)
+ -- segnalo spezzatura lavorazione faccia
+ vFace[i].Split = true
+ end
+ end
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByCut( Proc, nRawId, b3Raw)
+ local sWarn = ''
+ -- ingombro del pezzo
+ local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ local sErr = 'Error : part box not found'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero la curva associata
+ local bOpposite = false
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then
+ AuxId = AuxId + Proc.Id
+ local vtExtr= EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ if vtExtr then
+ bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0)
+ if GetFacesExternalSide( Proc, vtExtr) ~= Proc.Grp then
+ bOpposite = not bOpposite
+ end
+ end
+ end
+ -- altezza massima delle facce
+ local dWidth = 0
+ for i = 1, Proc.Fct do
+ local _, _, dFctW = WL.GetFaceHvRefDim( Proc.Id, i - 1)
+ dWidth = max( dWidth, dFctW)
+ end
+ -- lettura parametri (probabile/i parametro/i Q)
+ local nConeCut = VerifyCornerType( Proc)
+ -- recupero la lavorazione di taglio con lama e i suoi parametri (dapprima cerco quella che possa tagliare completamente)
+ local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
+ local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard', dWidth, nTool_ID)
+ if not sCutting then
+ sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard', nil, nTool_ID)
+ sWarn = 'Warning : elevation bigger than max sawcut depth'
+ end
+ if not sCutting then
+ local sErr = 'Error : cutting not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- gruppo ausiliario
+ local nAddGrpId = WL.GetAddGroup( Proc.PartId)
+ -- recupero i dati di tutte le facce
+ local vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, true, dSawDiam, dSawMaxDepth, dSawThick, nAddGrpId, b3Raw, nil)
+ -- inserimento dei tagli di lama
+ local bCtOk, sCtErr = AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick)
+ if not bCtOk then return bCtOk, sCtErr end
+ -- se richiesta solo lama, esco
+ local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0
+ if nCntType == 1 and nTool_ID ~= 0 then return true, sWarn end
+ -- se ci sono facce inclinate, escludo la sega a catena
+ local bSlanting = false
+ for i = 1, #vFace do
+ if abs( vFace[i].Norm:getZ()) > 0.01 then
+ bSlanting = true
+ break
+ end
+ end
+ -- recupero la lavorazione con sega a catena
+ local sSawing = WM.FindSawing( 'Sawing')
+ -- recupero la lavorazione di fresatura
+ local sMilling, dMillMaxDepth = WM.FindMilling( 'FreeContour', dMaxWidth + WD.CUT_EXTRA, nil, nil, nil, nil, true)
+ if not sMilling and ( not sSawing or bSlanting) then
+ sMilling = WM.FindMilling( 'FreeContour', nil, nil, nil, nil, nil, true)
+ if not sMilling then
+ local sErr = 'Error : milling not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ end
+ -- se possibile, inserimento delle fresature
+ if sMilling then
+ local nMlOk, sMlErr, dThick = AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId)
+ if nMlOk == 0 then return false, sMlErr end
+ -- se ci sono almeno due facce e lavorato almeno un angolo
+ if Proc.Fct >= 2 and dThick then
+ -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite
+ -- o con fresa cono piccola e spessore sotto il limite
+ if ( nConeCut == 1 and nMlOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL)) or
+ ( nConeCut == 2 and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL)) then
+ local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
+ sMlErr, nAddGrpId, dThick, nNewProc, 0,
+ true)
+ if not bMcok then return bMcok, sMcErr end
+ else
+ -- messaggi nel log
+ if nConeCut == 1 then
+ if nMlOk ~= 1 then
+ local sErr = 'Clean corner 60° not applid because Milling not thru the thickness'
+ EgtOutLog( sErr)
+ else
+ local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
+ ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
+ EgtOutLog( sErr)
+ end
+ elseif nConeCut == 2 then
+ local sErr = 'Clean corner 30° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
+ ' is bigger than parameter MAX_CLEAN_CRN30: ' .. EgtNumToString( WD.MAX_CLEAN_CRN30 , 2)
+ EgtOutLog( sErr)
+ end
+ end
+ end
+ -- altrimenti provo con la sega a catena
+ else
+ local nCsOk, sCSErr, dThick = AddSawings( sSawing, vFace, Proc, nRawId, b3Raw)
+ if nCsOk == 0 then return false, sCsErr end
+ -- se ci sono almeno due facce e lavorato almeno un angolo
+ if Proc.Fct >= 2 and dThick then
+ -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite
+ if nConeCut == 1 and nCsOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then
+ local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
+ sCSErr, nAddGrpId, nil, nNewProc, 0,
+ true)
+ if not bMcok then return bMcok, sMcErr end
+ else
+ if nConeCut == 1 then
+ if nCsOk ~= 1 then
+ local sErr = 'Clean corner 60° not applied because Chainsawing not thru the thickness'
+ EgtOutLog( sErr)
+ else
+ local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
+ ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
+ EgtOutLog( sErr)
+ end
+ elseif nConeCut == 2 then
+ local sErr = 'Not possible apply Clean corner 30° after use sawing'
+ EgtOutLog( sErr)
+ end
+ end
+ end
+ end
+ return true, sWarn
+end
+
+---------------------------------------------------------------------
+local function MakeByMill( Proc, nRawId, b3Raw)
+ -- ingombro del pezzo
+ local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ local sErr = 'Error : part box not found'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero e verifico l'entità curva
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing profile geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati della curva e del profilo
+ local dDepth = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD)
+ local bToolInv = ( vtExtr:getZ() < -0.1)
+ local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
+ -- recupero la lavorazione
+ local sMilling = WM.FindMilling( 'FreeContour', nil, nil, nTool_ID, nil, nil, true)
+ if not sMilling then
+ local sErr = 'Error : milling not found in library'
+ if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati dell'utensile
+ local dMaxDepth = 0
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth
+ end
+ end
+ -- eventuale spezzatura sul tratto più lungo se curva chiusa
+ --BL.PutStartOnLonger( AuxId)
+ -- verifiche per affondamento
+ if b3Aux:getDimZ() > b3Raw:getDimZ() - 1.0 then
+ dDepth = min( dDepth, b3Raw:getDimZ()) + WD.CUT_EXTRA
+ end
+ if dDepth > dMaxDepth then
+ -- lo limito e tolgo eventuali Tabs
+ dDepth = dMaxDepth
+ EgtSetMachiningParam( MCH_MP.LEAVETAB, false)
+ end
+ -- inserisco la lavorazione
+ local sName = 'Free_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- se estrusione da sotto, inverto direzione fresa
+ if bToolInv then
+ EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
+ end
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- assegno lato di lavoro
+ if Proc.Grp == 0 then
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
+ elseif ( Proc.Grp == 3 and not bToolInv) or ( Proc.Grp == 4 and bToolInv) then
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
+ elseif ( Proc.Grp == 3 and bToolInv) or ( Proc.Grp == 4 and not bToolInv) then
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ -- posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByMark( Proc, nRawId, b3Raw)
+ -- ingombro del pezzo
+ local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ local sErr = 'Error : part box not found'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero e verifico l'entità curva
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing profile geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati della curva e del profilo
+ local dDepth = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD)
+ local bToolInv = ( vtExtr:getZ() < -0.1)
+ local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
+ -- recupero la lavorazione
+ local sMilling = WM.FindMilling( 'Text', nil, nil, nTool_ID)
+ if not sMilling then
+ local sErr = 'Error : milling not found in library'
+ if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione
+ local sName = 'FreeMark_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- se estrusione da sotto, inverto direzione fresa
+ if bToolInv then
+ EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
+ end
+ -- posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByNail( Proc, nRawId, b3Raw)
+ -- ingombro del pezzo
+ local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ local sErr = 'Error : part box not found'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero e verifico l'entità curva
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing profile geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati della curva e del profilo
+ local dDepth = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD)
+ local bToolInv = ( vtExtr:getZ() < -0.1)
+ local nCntData = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') or 0
+ if nCntData < 10 then
+ nCntData = nCntData + 10
+ end
+ local dCntPar = EgtGetInfo( Proc.Id, 'CNT_PAR', 'd') or 100
+ -- recupero la lavorazione
+ local sNailing = WM.FindNailing( nCntData)
+ if not sNailing then
+ local sErr = 'Error : nailing not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione
+ local sName = 'Nail_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchId = EgtAddMachining( sName, sNailing)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sNailing
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- se estrusione da sotto, inverto direzione fresa
+ if bToolInv then
+ EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
+ end
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, 10)
+ -- assegno lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
+ -- se in doppio lungo Y, devo dimezzare opportunamente la lavorazione
+ local dExtraDelta = 0
+ if Proc.Double == 2 then
+ dExtraDelta = 0.45 * dCntPar
+ if Proc.Delta > 0 then
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, -Proc.DblAcc - dExtraDelta)
+ else
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, -Proc.DblAcc - dExtraDelta)
+ end
+ end
+ -- assegno parametri a note utente
+ local sUserNotes = 'Par=' .. EgtNumToString( dCntPar, 0) .. ';'
+ if Proc.Double and Proc.Double > 0 then
+ sUserNotes = sUserNotes .. 'Dbl=' .. EgtNumToString( Proc.Double, 0) .. ';' ..
+ 'Dlt=' .. EgtNumToString( abs( Proc.Delta) + dExtraDelta, 0) .. ';'
+ end
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByPocket( Proc, nRawId, b3Raw)
+ -- recupero e verifico l'entità curva
+ local bOpposite = false
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ local vtExtr
+ if AuxId then
+ AuxId = AuxId + Proc.Id
+ vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ if vtExtr then
+ bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0)
+ if GetFacesExternalSide( Proc, vtExtr) ~= Proc.Grp then
+ bOpposite = not bOpposite
+ end
+ end
+ end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing profile geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ local bPocketBotface = false
+ -- se la curva è aperta non la svuoto
+ if not EgtCurveIsClosed( AuxId) then
+ bPocketBotface = true
+ end
+ -- recupero i dati della curva e del profilo
+ local dDepth = EgtIf( bPocketBotface, 0, abs( EgtCurveThickness( AuxId)))
+ local dOriDepth = dDepth
+ -- cerco la faccia di fondo della superfice (deve avere direzione circa quella di estrusione della curva)
+ local nFacet
+ for i = 1, Proc.Fct do
+ local _, vtN = EgtSurfTmFacetCenter( Proc.Id, i-1, GDB_ID.ROOT)
+ if abs( vtN * vtExtr) > 0.99 then
+ nFacet = i - 1
+ break
+ end
+ end
+ if not nFacet then
+ return MakeByCut( Proc, nRawId, b3Raw)
+ end
+ -- dati della faccia di fondo
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dDiam = min( dH, dV)
+ local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId)
+ -- gruppo ausiliario
+ local nAddGrpId = WL.GetAddGroup( Proc.PartId)
+ local nNewProc, nNumFacet = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet)
+ -- se ho forma a L
+ local bIsL = ( nNumFacet == 2 or TestElleShape3( nNewProc, nNumFacet) or TestElleShape4( nNewProc, nNumFacet) == 2)
+ -- verifico se U
+ local bIsU = ( nNumFacet == 3 and not TestElleShape3( nNewProc, nNumFacet))
+ local dMiddleFacetLength = 0
+ if bIsU then
+ local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( nNewProc, 1, GDB_ID.ROOT)
+ -- prendo la linea di base
+ if abs( dElev - dH2) < 1 and abs( dElev - dV2) > 1 then
+ dMiddleFacetLength = dV2
+ elseif abs( dElev - dV2) < 1 and abs( dElev - dH2) > 1 then
+ dMiddleFacetLength = dH2
+ end
+ end
+ if Proc.Fct < 5 and (( bIsL and not bIsU) or ( bIsU and dMiddleFacetLength > dDiam * 2)) then dDiam = dDiam * 2 end
+ local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i')
+ -- recupero la lavorazione
+ local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dDepth, nTool_ID)
+ if not sPocketing then
+ local sErr = 'Error : pocketing not found in library'
+ if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMaxDepth = 0
+ local dThDiam = 100
+ if EgtMdbSetCurrMachining( sPocketing) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth
+ dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam
+ end
+ end
+ -- inserisco la lavorazione di svuotatura
+ local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sPocketing)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ if bPocketBotface then
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
+ else
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ end
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameVectorApprox( vtExtr, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ local sWarn = ''
+ if bPocketBotface then
+ local dThElev = dThDiam / 2 * sqrt( vtExtr:getX() * vtExtr:getX() + vtExtr:getY() * vtExtr:getY())
+ if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then
+ dDepth = dMaxDepth - dElev - dThElev
+ sWarn = 'Warning : elevation bigger than max tool depth'
+ EgtOutLog( sWarn)
+ end
+ else
+ -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente
+ if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then
+ dDepth = dMaxDepth
+ sWarn = 'Warning : elevation bigger than max tool depth'
+ EgtOutLog( sWarn)
+ end
+ end
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- imposto elevazione
+ EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( EgtIf( bPocketBotface, min( dElev, dMaxDepth), dMaxDepth), 1) .. ';')
+ -- eseguo
+ local bAppOk = EgtApplyMachining( true, false)
+ if not bAppOk and not bPocketBotface then
+ bPocketBotface = true
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
+ dDepth = 0
+ local dThElev = dThDiam / 2 * sqrt( vtExtr:getX() * vtExtr:getX() + vtExtr:getY() * vtExtr:getY())
+ if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then
+ dDepth = dMaxDepth - dElev - dThElev
+ sWarn = 'Warning : elevation bigger than max tool depth'
+ EgtOutLog( sWarn)
+ end
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ bAppOk = EgtApplyMachining( true, false)
+ end
+ if not bAppOk then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ -- lettura parametri (probabile/i parametro/i Q)
+ local nConeCut = VerifyCornerType( Proc)
+ -- recupero i dati di tutte le facce
+ local vFace, dMaxWidth
+ vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, b3Raw, nNewProc)
+ -- se ci sono almeno due facce
+ if Proc.Fct >= 2 then
+ -- se abilitata la lavorazione corner con stop macchina e affondamento non superiore al limite
+ local dDepthMach = EgtIf( bPocketBotface, dDepth, ( dDepth - dOriDepth))
+ if nConeCut == 1 and dDepthMach <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then
+ local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
+ dMillDiam, nAddGrpId, nil, nNewProc, dDepthMach)
+ if not bMcok then return bMcok, sMcErr end
+ else
+ EgtErase( nNewProc)
+ if nConeCut == 1 then
+ local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) ..
+ ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2)
+ EgtOutLog( sErr)
+ elseif nConeCut == 2 then
+ local sErr = 'Clean corner 30° is not applied on pocketing'
+ EgtOutLog( sErr)
+ end
+ end
+ end
+ return true, sWarn
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPF.Make( Proc, nRawId, b3Raw)
+ -- recupero la tipologia (contorno o tasca)
+ local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
+ -- se svuotatura
+ if bPocket then
+ return MakeByPocket( Proc, nRawId, b3Raw)
+ -- altrimenti contorno
+ else
+ -- riordino le facce
+ ReorderFaces( Proc.Id, EgtSurfTmFacetCount( Proc.Id))
+ -- recupero il tipo di lavorazione
+ local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0
+ -- se fresatura
+ if nCntType == 2 then
+ return MakeByMill( Proc, nRawId, b3Raw)
+ -- se marcatura
+ elseif nCntType == 10 then
+ return MakeByMark( Proc, nRawId, b3Raw)
+ -- se chiodatura
+ elseif nCntType == 20 then
+ return MakeByNail( Proc, nRawId, b3Raw)
+ -- altrimenti, taglio con lama e pulizia angoli con fresa
+ else
+ return MakeByCut( Proc, nRawId, b3Raw)
+ end
+ end
+end
+
+---------------------------------------------------------------------
+return WPF
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessLapJoint.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessLapJoint.lua
new file mode 100644
index 0000000..25b34b8
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessLapJoint.lua
@@ -0,0 +1,2579 @@
+-- WProcessLapJoint.lua by Egaltech s.r.l. 2022/02/04
+-- Gestione calcolo mezzo-legno per Pareti
+-- 2021/08/27 DS Se tre o più facce con flag PCKT=1 forzo svuotatura con fresa (per Variant).
+-- 2021/08/29 DS Se svuotatura di fianco setto flag per farla dopo i tagli.
+-- 2021/09/03 DS Se due facce con sottosquadra ora si restituisce mesaaggio di errore.
+-- 2021/10/05 FM Gestione lavorazioni SideMill con creazione gola passaggio gambo utensile
+-- 2021/11/29 DS Correzione lav.ni SideMill quando più profonde che larghe.
+-- 2022/01/04 DS Se U con fondo verso basso o alto non ci possono essere spigoli verticali da pulire.
+-- 2022/01/17 ES Migliorata scelta fresa per lavorazione di fianco sotto.
+-- 2022/02/03 DS Gorge larga come gambo più sicurezza.
+-- 2022/02/04 DS In svuotatura aggiunta gestione WD.MAXDIAM_POCK_CORNER in presenza di almeno un angolo interno.
+
+-- Tabella per definizione modulo
+local WPL = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+local FreeContour = require( 'WProcessFreeContour')
+
+EgtOutLog( ' WProcessLapJoint started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+local WHISK_OFFS = 0.1
+local WHISK_SAFE = 5
+local MIN_LEN_CUT = 30
+
+-- variabili assegnazione parametri Q
+local Q_FORCE_BLADE = '' -- i
+local Q_SIDE_MILL = '' -- d
+local Q_CORNER_CUT = '' -- i
+
+-- variabile settaggio doppia lavorazione su angoo > 90
+local bMakeTwinCut = true
+-- angolo sottosquadra ammesso per fresa cono 30°
+local dAngleSmall = 70
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPL.Identify( Proc)
+ return ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) or
+ ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) or
+ ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) or
+ ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30) or
+ ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32) or
+ ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) or
+ ( ( Proc.Grp == 4) and Proc.Prc == 39)
+end
+
+---------------------------------------------------------------------
+local function AssignQIdent( Proc)
+
+ -- reset assegnazione parametri Q
+ Q_FORCE_BLADE = ''
+ Q_SIDE_MILL = ''
+ Q_CORNER_CUT = ''
+
+ if Proc.Grp == 0 and Proc.Prc == 12 then
+ Q_FORCE_BLADE = 'Q01' -- i
+ Q_SIDE_MILL = 'Q02' -- i
+ Q_CORNER_CUT = '' -- i
+ elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then
+ Q_FORCE_BLADE = '' -- i
+ Q_SIDE_MILL = 'Q08' -- i
+ Q_CORNER_CUT = 'Q05' -- i
+ else
+ Q_FORCE_BLADE = 'Q01' -- i
+ Q_SIDE_MILL = 'Q03' -- i
+ Q_CORNER_CUT = 'Q05' -- i
+ end
+ -- le altre features gestite non hanno parametri Q
+end
+
+---------------------------------------------------------------------
+local function EvaluateQParam( Proc)
+
+ local bForceUseBlade = false
+ if #Q_FORCE_BLADE == 0 or EgtGetInfo( Proc.Id, Q_FORCE_BLADE, 'i') == 1 then
+ bForceUseBlade = true
+ end
+
+ -- Verifico se utilizzare la fresa di lato :
+ -- 0 : niente
+ -- 1 : utilizzo fresa di lato (alla faccia selezionata)
+ local nUseSideMillAsBlade = EgtGetInfo( Proc.Id, Q_SIDE_MILL, 'i') or 0
+
+ -- Verifico il tipo di lavorazione su angolo :
+ -- 0 : niente
+ -- 1 : ripresa corner dopo pausa per rimozione sfridi (fresa 60deg)
+ -- 2 : ripresa corner senza pausa (fresa 30 deg)
+ -- 3 : scarico corner (tipo foro).
+ local nTypeCornerCut = EgtGetInfo( Proc.Id, Q_CORNER_CUT, 'i') or 0
+
+ return nTypeCornerCut, nUseSideMillAsBlade, bForceUseBlade
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPL.Classify( Proc, b3Raw)
+ -- se 1 faccia
+ if Proc.Fct == 1 then
+ -- dati della faccia
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ -- verifico se è lavorabile da sopra
+ return vtN:getZ() >= WD.NZ_MINA
+ -- se 2 facce
+ elseif Proc.Fct == 2 then
+ -- dati delle facce
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+ -- verifico se è lavorabile da sopra o di fianco
+ return ( vtN[1]:getZ() >= - 0.01 or vtN[2]:getZ() >= - 0.01)
+ -- se più di 2 facce
+ else
+ local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+ -- se trovata faccia di fondo
+ if nFacInd >= 0 then
+ -- determino componente Z della normale più diretta verso il basso
+ local dMinNz = 1
+ for i = 1, Proc.Fct do
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT)
+ if vtN:getZ() < dMinNz then
+ dMinNz = vtN:getZ()
+ end
+ end
+ -- dati della faccia
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
+ -- per lavorare alcune superfici che sono di poco negative controllo che la minima Z sia al di sopra del punto minimo calcolato per
+ -- una lama da 500
+ local bAllowNegativeFace
+ if vtN:getZ() < - 0.01 then
+ if vtN:getZ() > - 0.088 and Proc.Box:getMin():getZ() - b3Raw:getMin():getZ() - (500 * abs(vtN:getZ())) >= 0 then
+ bAllowNegativeFace = true
+ end
+ end
+ -- verifico se la faccia è lavorabile da sopra o di fianco
+ if ( vtN:getZ() >= WD.NZ_MINA or ( dMinNz < -0.866 and Proc.Fct >= 3 and ( vtN:getZ() > - 0.01 or bAllowNegativeFace))) then
+ Proc.Stype = 1
+ return true
+ -- altrimenti verifico la eventuale seconda faccia
+ elseif nFacInd2 then
+ -- dati della faccia
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT)
+ local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd2, GDB_ID.ROOT)
+ -- restituisco se faccia lavorabile
+ Proc.Stype = 2
+ return ( vtN2:getZ() >= WD.NZ_MINA or ( dMinNz < -0.866 and Proc.Fct >= 3 and vtN2:getZ() > - 0.01))
+ -- se tre facce
+ elseif Proc.Fct == 3 then
+ -- verifico se U da sopra
+ -- dati della faccia
+ local nFac2 = EgtIf( nFacInd == 0, 1, 0)
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFac2, GDB_ID.ROOT)
+ Proc.Stype = 3
+ return ( abs( ( vtN ^ vtN2) * Z_AX()) >= WD.NZ_MINA)
+ -- altrimenti non lavorabile
+ else
+ return false
+ end
+ -- se altrimenti tunnel
+ elseif nFacInd == -1 then
+ -- dati delle prime tre facce
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+ vtN[3] = EgtSurfTmFacetNormVersor( Proc.Id, 2, GDB_ID.ROOT)
+ -- verifico se è lavorabile da sopra
+ local vtAxN = vtN[1] ^ vtN[2]
+ if vtAxN:isSmall() then vtAxN = vtN[1] ^ vtN[3] end
+ Proc.Stype = 4
+ return ( abs( vtAxN:getZ()) >= WD.NZ_MINA)
+ -- altrimenti non lavorabile
+ else
+ return false
+ end
+ end
+end
+
+-- funzione che verifica se faccia lavorabile da sopra
+local function VerifyVtN( ProcId, nFct)
+ local nFlip0 = 0
+ local nFlip1 = 0
+ -- dati della faccia
+ local vtN = EgtSurfTmFacetNormVersor( ProcId, nFct, GDB_ID.ROOT)
+ local dVtNZ = vtN:getZ()
+ -- verifico se è lavorabile da sopra
+ nFlip0 = EgtIf( dVtNZ >= WD.NZ_MINA, 100, 0)
+ -- verifico se e' lavorabile da fliped: cambio segno al versore
+ nFlip1 = EgtIf( -dVtNZ >= WD.NZ_MINA, 100, 0)
+ return nFlip0, nFlip1
+end
+
+-- funzione che fa la media dei versori per assegnare punteggi flip
+local function VerifyVtNMedia(ProcId, nFct1, nFct2)
+ local nFlip0 = 0
+ local nFlip1 = 0
+ -- dati delle facce
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( ProcId, nFct1, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( ProcId, nFct2, GDB_ID.ROOT)
+ local dVtN1Z = vtN[1]:getZ()
+ local dVtN2Z = vtN[2]:getZ()
+ -- se entrambi i versori positivi
+ if (dVtN1Z >= - 0.01 and dVtN2Z >= - 0.01) then
+ -- posso lavorarlo da sopra
+ nFlip0 = 100
+ -- se almeno un versore positivo
+ elseif (dVtN1Z >= - 0.01 or dVtN2Z >= - 0.01) then
+ -- calcolo media dei versori: se positiva tende verso alto
+ local dVtNMedia = ( dVtN1Z + dVtN2Z) / 2
+ if dVtNMedia >= 0 - GEO.EPS_SMALL and dVtNMedia <= 0 + GEO.EPS_SMALL then
+ nFlip0 = 100
+ elseif dVtNMedia >= 0 + GEO.EPS_SMALL then
+ nFlip0 = 75
+ else
+ nFlip0 = 25
+ end
+ -- se entrambi i versori negativi, impossibile da fare
+ else
+ nFlip0 = 0
+ end
+ -- verifico se e' lavorabile da fliped: cambio segno ai versori
+ dVtN1Z = -dVtN1Z
+ dVtN2Z = -dVtN2Z
+ -- se entrambi i versori positivi
+ if (dVtN1Z >= - 0.01 and dVtN2Z >= - 0.01) then
+ -- posso lavorarlo da sopra
+ nFlip1 = 100
+ -- se almeno un versore positivo
+ elseif (dVtN1Z >= - 0.01 or dVtN2Z >= - 0.01) then
+ -- calcolo media dei versori: se positiva tende verso alto
+ local dVtNMedia = ( dVtN1Z + dVtN2Z) / 2
+ if dVtNMedia >= 0 - GEO.EPS_SMALL and dVtNMedia <= 0 + GEO.EPS_SMALL then
+ nFlip1 = 100
+ elseif dVtNMedia >= 0 + GEO.EPS_SMALL then
+ nFlip1 = 75
+ else
+ nFlip1 = 25
+ end
+ -- se entrambi i versori negativi, impossibile da fare
+ else
+ nFlip0 = 0
+ end
+ return nFlip0, nFlip1
+end
+
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPL.FlipClassify( Proc)
+ local nFlip0 = -1
+ local nFlip1 = -1
+ -- se 1 faccia
+ if Proc.Fct == 1 then
+ -- verifico che la normale permetta la lavorazione da sopra ed assegno punteggio di conseguenza
+ nFlip0, nFlip1 = VerifyVtN( Proc.Id, 0)
+ -- se 2 facce
+ elseif Proc.Fct == 2 then
+ -- calcolo la media delle normali delle facce ed assegno punteggio maggiore se positiva
+ nFlip0, nFlip1 = VerifyVtNMedia(Proc.Id, 0, 1)
+ -- se più di 2 facce
+ else
+ local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+ if nFacInd == -2 then return 0, 0 end
+ -- se 3 facce
+ if Proc.Fct == 3 then
+ -- se forma ad U
+ if not nFacInd2 or nFacInd2 == 0 then
+ -- verifico che la normale del fondo permetta la lavorazione da sopra ed assegno punteggio di conseguenza
+ nFlip0, nFlip1 = VerifyVtN( Proc.Id, nFacInd)
+ -- se non ad U
+ else
+ -- calcolo la media delle normali delle facce di fondo ed assegno punteggio maggiore se positiva
+ nFlip0, nFlip1 = VerifyVtNMedia(Proc.Id, nFacInd, nFacInd2)
+ end
+ -- se 4 facce
+ elseif Proc.Fct == 4 then
+ -- se senza fondo (tunnel)
+ if not nFacInd or nFacInd == -1 then
+ -- dati delle facce
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+ vtN[3] = EgtSurfTmFacetNormVersor( Proc.Id, 2, GDB_ID.ROOT)
+ vtN[4] = EgtSurfTmFacetNormVersor( Proc.Id, 3, GDB_ID.ROOT)
+ -- verifico se è lavorabile da sopra
+ local vtAxN = vtN[1] ^ vtN[2]
+ if vtAxN:isSmall() then
+ vtAxN = vtN[1] ^ vtN[3]
+ end
+ if ( abs( vtAxN:getZ()) >= WD.NZ_MINA) then
+ -- calcolo la media dei versori delle facce
+ local dVtNMedia = ( vtN[1]:getZ() + vtN[2]:getZ() + vtN[3]:getZ() + vtN[4]:getZ()) / 4
+ if dVtNMedia >= 0 - GEO.EPS_SMALL and dVtNMedia <= 0 + GEO.EPS_SMALL then
+ nFlip0 = 100
+ nFlip1 = 100
+ elseif dVtNMedia >= 0 + GEO.EPS_SMALL then
+ nFlip0 = 75
+ nFlip1 = 25
+ else
+ nFlip0 = 25
+ nFlip1 = 75
+ end
+ end
+ -- se con fondo
+ else
+ -- calcolo la media delle normali delle facce di fondo ed assegno punteggio maggiore se positiva
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT)
+ if vtN[1]:getZ() == -1 or vtN[2]:getZ() == -1 then return 0, 100 end
+ if vtN[1]:getZ() == 1 or vtN[2]:getZ() == 1 then return 100, 0 end
+ nFlip0, nFlip1 = VerifyVtNMedia(Proc.Id, nFacInd, nFacInd2)
+ end
+ -- se 5 facce
+ elseif Proc.Fct == 5 then
+ -- verifico che la normale del fondo permetta la lavorazione da sopra ed assegno punteggio di conseguenza
+ nFlip0, nFlip1 = VerifyVtN( Proc.Id, nFacInd)
+ end
+ end
+ return nFlip0, nFlip1
+end
+
+---------------------------------------------------------------------
+local function TestElleShape3( nIdGeom, nNumFacet)
+ -- valida solo nel caso di tre facce
+ if nNumFacet ~= 3 then return false end
+ -- determino se L con una faccia terminale o U con tre facce
+ local bIsL = true
+ for i = 1, 3 do
+ local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1]
+ -- le conto
+ local nCount = 0
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ nCount = nCount + 1
+ end
+ end
+ if nCount == 1 then
+ bIsL = false
+ break
+ end
+ end
+ return bIsL
+end
+
+---------------------------------------------------------------------
+local function TestElleShape4( nIdGeom, nNumFacet)
+ -- valida solo nel caso di quattro facce
+ if nNumFacet ~= 4 then return false end
+ -- determino se L con due facce terminali o O
+ local nFac3Adj = 0
+ local dMinArea3 = GEO.INFINITO * GEO.INFINITO
+ local dMaxArea2 = 0
+ for i = 1, 4 do
+ local vFacAdj = EgtSurfTmFacetAdjacencies( nIdGeom, i - 1)[1]
+ -- le conto
+ local nCount = 0
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ nCount = nCount + 1
+ end
+ end
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nIdGeom, i - 1, GDB_ID.ROOT)
+ local dArea = dH * dV
+ if nCount == 2 then
+ dMaxArea2 = max( dMaxArea2, dArea)
+ elseif nCount == 3 then
+ dMinArea3 = min( dMinArea3, dArea)
+ nFac3Adj = nFac3Adj + 1
+ end
+ end
+ if nFac3Adj ~= 2 then return false end
+ -- verifico se L profonda oppure lunga
+ if dMinArea3 < dMaxArea2 then
+ return 1
+ else
+ return 2
+ end
+end
+
+---------------------------------------------------------------------
+local function GetOtherRegions( nPartId)
+ local vOthers = {}
+ local nOtherId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL)
+ while nOtherId do
+ local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL)
+ while nRegId do
+ local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT)
+ if EgtExistsInfo( nRegId, 'REGION') and vtN and AreSameVectorApprox( vtN, Z_AX()) then
+ local b3Reg = EgtGetBBoxGlob( nRegId, GDB_BB.STANDARD)
+ if b3Reg then
+ table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg})
+ end
+ end
+ nRegId = EgtGetNext( nRegId)
+ end
+ nOtherId = EgtGetNextPartInRawPart( nOtherId)
+ end
+ return vOthers
+end
+
+---------------------------------------------------------------------
+local function ReorderFaces( nIdSurf, nNumFacet)
+ -- cerco una faccia senza precedenti
+ local nFirstFac
+ for i = 1, nNumFacet do
+ -- centro e normale della faccia
+ local ptCen, vtN = EgtSurfTmFacetCenter( nIdSurf, i - 1, GDB_ID.ROOT)
+ -- verifico con le altre facce
+ local bFoundPrec
+ for j = 1, nNumFacet do
+ if j ~= i then
+ -- verifico se è precedente
+ local bAdj, ptP1, _, _ = EgtSurfTmFacetsContact( nIdSurf, i - 1, j - 1, GDB_ID.ROOT)
+ if bAdj and ( vtN ^ ( ptCen - ptP1)) * Z_AX() > 0 then
+ bFoundPrec = true
+ break
+ end
+ end
+ end
+ if not bFoundPrec then
+ nFirstFac = i
+ break
+ end
+ end
+ -- se trovata, la metto al primo posto
+ if nFirstFac and nFirstFac ~= 1 then
+ EgtSurfTmSwapFacets( nIdSurf, nFirstFac - 1, 0)
+ end
+ -- ordino le facce in modo da avere una sequenza ordinata con le normali a destra
+ for i = 1, nNumFacet - 1 do
+ -- centro e normale della faccia
+ local ptCen, vtN = EgtSurfTmFacetCenter( nIdSurf, i - 1, GDB_ID.ROOT)
+ -- cerco la successiva
+ for j = i + 1, nNumFacet do
+ -- verifico se è successiva
+ local bAdj, ptP1, _, _ = EgtSurfTmFacetsContact( nIdSurf, i - 1, j - 1, GDB_ID.ROOT)
+ if bAdj and ( vtN ^ ( ptP1 - ptCen)) * Z_AX() > 0 then
+ EgtSurfTmSwapFacets( nIdSurf, i, j - 1)
+ break
+ end
+ end
+ end
+end
+
+---------------------------------------------------------------------
+local function RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFaceToDel)
+ -- copio la superfice nel gruppo ausiliario
+ local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
+ EgtSurfTmRemoveFacet( nNewProc, nFaceToDel)
+ local nNumFacet = EgtSurfTmFacetCount( nNewProc)
+ ReorderFaces( nNewProc, nNumFacet)
+ return nNewProc, nNumFacet
+end
+
+---------------------------------------------------------------------
+local function GetFacesData( nNewProc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, nPartId)
+
+ local nNumFacet = EgtSurfTmFacetCount( nNewProc)
+ local vFace = {}
+ -- recupero i dati di tutte le facce
+ for i = 1, nNumFacet do
+ -- indici faccia corrente e precedente
+ local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1)
+ local nPrecFac
+ if bOpposite then
+ nPrecFac = EgtIf( i == 1, 0, nFac + 1)
+ else
+ nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2)
+ end
+ -- recupero centro e normale della faccia
+ local ptCen, vtN = EgtSurfTmFacetCenter( nNewProc, nFac, GDB_ID.ROOT)
+ -- recupero le dimensioni della faccia
+ local _, dLen, dWidth = WL.GetFaceHvRefDim( nNewProc, nFac)
+ -- recupero l'angolo con la faccia precedente
+ local bAdj, ptLocP1, ptLocP2, dAng = EgtSurfTmFacetsContact( nNewProc, nPrecFac, nFac, GDB_ID.ROOT)
+ -- verifico che l'adiacenza sia veramente con il precedente (percorro con normale a destra)
+ if bAdj then
+ if ( vtN ^ ( ptLocP1 - ptCen)) * Z_AX() > 0 then
+ bAdj = false
+ end
+ end
+ -- salvo i dati
+ vFace[i] = { Fac = nFac, Cen = ptCen, Norm = vtN, Len = dLen, Width = dWidth, AngPrev = EgtIf( bAdj, dAng, 0)}
+ if bAdj then
+ if ptLocP1:getZ() < ptLocP2:getZ() then
+ vFace[i].PPrev = ptLocP1
+ else
+ vFace[i].PPrev = ptLocP2
+ end
+ end
+ end
+ -- analizzo le facce
+ local dMaxWidth = 0
+ for i = 1, #vFace do
+ -- aggiorno la massima larghezza
+ if vFace[i].Width > dMaxWidth then
+ dMaxWidth = vFace[i].Width
+ end
+ -- verifico l'affondamento
+ local dDepth = WD.CUT_EXTRA
+ if vFace[i].Width + WD.CUT_EXTRA > dToolMaxDepth then
+ dDepth = dToolMaxDepth - vFace[i].Width
+ end
+ -- lunghezza baffo
+ local dElev = vFace[i].Width + dDepth
+ local dWhisk = EgtIf( bCalclForBlade, ( dElev * sqrt( dToolDiam / dElev - 1) + WHISK_SAFE), (dToolDiam/2) + WHISK_SAFE)
+ -- determino la lunghezza del taglio passante e il tipo di attacco e uscita
+ local dLen = vFace[i].Len
+ local nType = 0
+ if vFace[i].AngPrev < -0.1 then
+ dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0)
+ nType = nType + 1
+ end
+ if vFace[EgtIf( i < nNumFacet, i + 1, 1)].AngPrev < -0.1 then
+ dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0)
+ nType = nType + 2
+ end
+ -- se lunghezza non significativa, non va inserito il taglio
+ if dLen < MIN_LEN_CUT then
+ nType = 4
+ end
+ vFace[i].Depth = dDepth
+ vFace[i].Whisk = dWhisk
+ vFace[i].Type = nType
+ end
+ -- recupero le regioni degli altri pezzi
+ local vOthers = GetOtherRegions( nPartId)
+ -- verifico i baffi sporgenti dei tagli rispetto alle altre regioni
+ for i = 1, #vFace do
+ -- verifico il baffo iniziale
+ if vFace[i].Type ~= 4 and ( vFace[i].Type & 1) == 0 then
+ -- creo il rettangolo del baffo
+ local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize()
+ local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), -90)
+ local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, -90)
+ local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt
+ local ptDir = ptIni + ( vFace[i].Whisk - WHISK_OFFS) * vtDir
+ local ptCross = ptDir + ( dToolThick - WHISK_OFFS) * vtOrt
+ local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB)
+ local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD)
+ -- verifico se interferisce con gli altri pezzi
+ for j = 1, #vOthers do
+ if OverlapsXY( b3Wh, vOthers[j].Box) then
+ local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0)
+ if nClass ~= GDB_RC.OUT then
+ local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 2) ~= 0, -vFace[i].Whisk, 0)
+ if dLen >= MIN_LEN_CUT then
+ vFace[i].Type = vFace[i].Type + 1
+ else
+ vFace[i].Type = 4
+ end
+ break
+ end
+ end
+ end
+ EgtErase( WhId)
+ end
+ -- verifico il baffo finale
+ if vFace[i].Type ~= 4 and ( vFace[i].Type & 2) == 0 then
+ -- creo il rettangolo del baffo
+ local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize()
+ local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), 90)
+ local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, 90)
+ local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt
+ local ptDir = ptIni + ( vFace[i].Whisk - WHISK_OFFS) * vtDir
+ local ptCross = ptDir + ( dToolThick - WHISK_OFFS) * vtOrt
+ local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB)
+ local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD)
+ -- verifico se interferisce con gli altri pezzi
+ for j = 1, #vOthers do
+ if OverlapsXY( b3Wh, vOthers[j].Box) then
+ local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0)
+ if nClass ~= GDB_RC.OUT then
+ local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 1) ~= 0, -vFace[i].Whisk, 0)
+ if dLen >= MIN_LEN_CUT then
+ vFace[i].Type = vFace[i].Type + 2
+ else
+ vFace[i].Type = 4
+ end
+ break
+ end
+ end
+ end
+ EgtErase( WhId)
+ end
+ end
+ -- eventuali stampe
+ for i = 1, #vFace do
+ local Face = vFace[i]
+ local sOut = 'Face '..tostring( Face.Fac)..' C'..tostring( Face.Cen)..' N'..tostring( Face.Norm)..
+ ' L='..EgtNumToString( Face.Len, 1)..' W='..EgtNumToString( Face.Width, 1)..' Ap='..EgtNumToString( Face.AngPrev, 1)..
+ ' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..' T='..tostring( Face.Type)
+ EgtOutLog( sOut, 3)
+ end
+
+ return vFace, dMaxWidth, nNewProc
+end
+
+---------------------------------------------------------------------
+local function GetTunnelDimension( nId, nPartId, nAddGrpId)
+ -- ottengo i versori delle 4 facce e ottengo l'orientamento del tunnel
+ -- recupero il numero di facce
+ local nFacCnt = EgtSurfTmFacetCount( nId)
+ -- recupero l'ingombro della trave
+ local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
+ -- variabili dimensioni fessura e id faccia lunga
+ local dDimMin
+ local dDimMax
+ local nLongIdFace = 0
+ local bNegFace
+ local bOppoFace = false
+ -- ottengo il versore ortogonale
+ local ptN1, vtN1 = EgtSurfTmFacetCenter( nId, 0, GDB_ID.ROOT)
+ local _, vtN2 = EgtSurfTmFacetCenter( nId, 1, GDB_ID.ROOT)
+ local vtOrtho = vtN1 ^ vtN2
+ if vtOrtho:isSmall() then
+ if nFacCnt >= 3 then
+ _, vtN2 = EgtSurfTmFacetCenter( nId, 2, GDB_ID.ROOT)
+ vtOrtho = vtN1 ^ vtN2
+ bOppoFace = true
+ else
+ return
+ end
+ end
+ if vtOrtho:getZ() < -0.5 then
+ vtOrtho = -vtOrtho
+ bNegFace = true
+ end
+ -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta la profondità della fessura
+ local frFc = Frame3d( ptN1, vtOrtho) ;
+ local bBoxLoc = EgtGetBBoxRef( nId, GDB_BB.STANDARD, frFc)
+ local dDepth = bBoxLoc:getDimZ()
+ -- mi assicuro che la Z del punto utilizzato per creare la superficie sia alla Z inferiore del bounding box locale
+ local ptN2 = Point3d(ptN1)
+ ptN2:toLoc(frFc)
+ ptN2 = Point3d( ptN2:getX(), ptN2:getY(), bBoxLoc:getMin():getZ() + 2*GEO.EPS_SMALL)
+ ptN2:toGlob(frFc)
+ -- creo superficie intermedia
+ local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptN2, vtOrtho, b3Solid, GDB_ID.ROOT)
+ -- ritaglio la superficie con le facce della fessura
+ for i = 1, nFacCnt do
+ local ptN, vtN = EgtSurfTmFacetCenter( nId, i - 1, GDB_ID.ROOT)
+ EgtCutSurfTmPlane( nSurfInt, ptN, -vtN, false, GDB_ID.ROOT)
+ end
+ -- sposto la geometria trovata sulla Z minima (era su di 2 * GEO.EPS_SMALL)
+ EgtMove( nSurfInt, Point3d(0,0,-2*GEO.EPS_SMALL) - ORIG(), GDB_RT.GLOB)
+ -- mi faccio dare il contorno della superfice e la ricreo in modo più corretto
+ local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId)
+ -- elimino le entità allineate dello stesso tipo
+ EgtMergeCurvesInCurveCompo( nIdCont, 2*GEO.EPS_SMALL)
+ EgtErase(nSurfInt)
+ nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2*GEO.EPS_SMALL)
+ -- elimino il contorno
+ EgtErase(nIdCont)
+ -- se normale negativa inverto
+ _, vtN1 = EgtSurfTmFacetCenter( nSurfInt, 0, GDB_ID.ROOT)
+ if vtN1:getZ() < -0.5 then EgtInvertSurf( nSurfInt) end
+ local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT)
+ dDimMin = min( DimH, DimV)
+ dDimMax = max( DimH, DimV)
+ _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFacCnt-1, GDB_ID.ROOT)
+ -- se faccia pari alla larghezza fessura
+ if abs(DimH - dDimMax) < GEO.EPS_SMALL or abs(DimV - dDimMax) < GEO.EPS_SMALL then
+ nLongIdFace = nFacCnt-1
+ -- altrimenti verifico anche con la faccia precedente
+ else
+ local nFaceToCheck = EgtIf( bOppoFace, nFacCnt-3, nFacCnt-2)
+ -- prendo le dimensioni della faccia e poi confronto con il minimo
+ _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFaceToCheck, GDB_ID.ROOT)
+ -- se trovato con il minimo, questa seconda faccia non è la più lunga
+ if abs(DimH - dDimMin) < GEO.EPS_SMALL or abs(DimV - dDimMin) < GEO.EPS_SMALL then
+ nLongIdFace = nFacCnt-1
+ else
+ nLongIdFace = nFaceToCheck
+ end
+ end
+ if not dDimMax then
+ return dDimMin, dDimMax, dDepth, nil, nil
+ end
+ return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt
+end
+
+---------------------------------------------------------------------
+local function ReorderFacesFromTab( nIdSurf, vFace)
+
+ local nFacCnt = EgtSurfTmFacetCount( nIdSurf)
+ for i = 1, #vFace do
+ for j = 1, nFacCnt do
+ -- ottengo punto iniziale e versore della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( nIdSurf, (j-1), GDB_ID.ROOT)
+ -- se versore e posizione coincidono e non corrispondono al numero faccia, faccio lo swap
+ if AreSameVectorExact( vFace[i].Norm, vtN) and AreSamePointEpsilon( vFace[i].Cen, ptC, 50*GEO.EPS_SMALL) then
+ if j - 1 ~= vFace[i].Fac then
+ EgtSurfTmSwapFacets( nIdSurf, vFace[i].Fac, (j-1))
+ end
+ break
+ end
+ end
+ end
+ return nIdSurf
+end
+
+---------------------------------------------------------------------
+local function CalcInterference( nNewProc, vtExtr, ptCentr, dDiam1, dDiam2,
+ dTall1, dTall2, dDiam3, dTall3)
+
+ local ptCentrGrid1 = ptCentr + ( vtExtr * 0.01)
+ local frOriTool = Frame3d( ptCentrGrid1, vtExtr)
+ local bColl1 = EgtCDeConeSolid( frOriTool, dDiam1/2, dDiam2/2, dTall1, nNewProc, 0, GDB_RT.GLOB)
+ if bColl1 then return true end
+ local ptCentrGrid2 = ptCentr + ( vtExtr * ( dTall1 + 0.01))
+ frOriTool = Frame3d( ptCentrGrid2, vtExtr)
+ local bColl2 = EgtCDeCylSolid( frOriTool, dDiam2/2, (dTall2-dTall1), nNewProc, 0, GDB_RT.GLOB)
+ if bColl2 then return true end
+ local ptCentrGrid3 = ptCentr + ( vtExtr * ( dTall2 + 0.01))
+ frOriTool = Frame3d( ptCentrGrid3, vtExtr)
+ local bColl3 = EgtCDeCylSolid( frOriTool, dDiam3/2, (dTall3-dTall2), nNewProc, 0, GDB_RT.GLOB)
+ if bColl3 then return true end
+ -- restituisco risultato controllo collisioni
+ return false
+end
+
+---------------------------------------------------------------------
+local function MakeLocalSurf( ptP1, ptP2, ptP3, nAddGrpId)
+
+ if not ptP1 or not ptP2 or not ptP3 then
+ return nil
+ end
+
+ local pAuxId = {}
+ local nAuxId, AuxId
+ nAuxId = EgtLine( nAddGrpId, ptP1, ptP2, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ nAuxId = EgtLine( nAddGrpId, ptP2, ptP3, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ nAuxId = EgtLine( nAddGrpId, ptP3, ptP1, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ -- trasformo in percorso
+ if #pAuxId ~= 3 then
+ return nil
+ end
+ AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true)
+ -- se non c'é il percorso esco
+ if not AuxId then
+ return nil
+ end
+ -- creo la superfice piana
+ local nidFace = EgtSurfTmByFlatContour( nAddGrpId, AuxId, 0.01)
+ if not nidFace then
+ EgtErase(AuxId)
+ return nil
+ end
+ -- se normale negativa inverto
+ local _, vtN1 = EgtSurfTmFacetCenter( nidFace, 0, GDB_ID.ROOT)
+ if vtN1:getZ() < -0.5 then EgtInvertSurf( nidFace) end
+
+ EgtErase(AuxId)
+ return nidFace
+end
+
+---------------------------------------------------------------------
+local function AddMillCornerMachining( nPartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, dOffsAng, dDepthMach,
+ bThruThick, dThSurf, dDiam1, dDiam2, dTall1,
+ dTall2, dDiam3, dTall3, bMakeLocSurf, vFace)
+ -- variabili costruzione geometria
+ local pAuxId = {}
+ local nAuxId
+ local ptApPoint
+ local AuxId
+ local nNewProcLoc
+ -- se devo creare superfice locale
+ if bMakeLocSurf then
+ -- creo superfice locale o esco
+ local nSurfToAdd = MakeLocalSurf( tFacAdj[1][7], tFacAdj[1][8], tFacAdj[1][9], nAddGrpId)
+ if nSurfToAdd then
+ local nFacCntPre = EgtSurfTmFacetCount( nNewProc)
+ -- creo copia del percorso principale e gli aggiungo la nuova faccia
+ nNewProcLoc = EgtCopyGlob( nNewProc, nAddGrpId)
+ nNewProcLoc = EgtSurfTmBySewing( nAddGrpId, {nNewProcLoc,nSurfToAdd} , true)
+ -- riordino le facce
+ nNewProcLoc = ReorderFacesFromTab( nNewProcLoc, vFace)
+ -- acquisisco il numero della faccia
+ nFacCnt = EgtSurfTmFacetCount( nNewProcLoc)
+ nFacInd = nFacCnt - 1
+ else
+ local sErr = 'Cannot make local bottom surface'
+ EgtOutLog( sErr)
+ return true, ''
+ end
+ else
+ nNewProcLoc = nNewProc
+ end
+ -- prendo il primo versore
+ local _, vtN1 = EgtSurfTmFacetCenter( nNewProcLoc, nFacInd, GDB_ID.ROOT)
+ local _, vtN2 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[1][1], GDB_ID.ROOT)
+ local _, vtN3 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[1][2], GDB_ID.ROOT)
+ -- trovo il punto sulla superfice di riferimento
+ local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1][1], GDB_ID.ROOT)
+ local _, ptLocP3, ptLocP4, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1][2], GDB_ID.ROOT)
+ -- se ho creato faccia locale su copia superficie, cancella la copia
+ if bMakeLocSurf then
+ EgtErase( nNewProcLoc)
+ end
+ local nIdIniPoint
+ local nIdEndPoint
+ if ptLocP1 and ptLocP2 then
+ if ( dist( ptLocP1, tFacAdj[1][4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][4]) < GEO.EPS_SMALL) then
+ nIdEndPoint = 4
+ nIdIniPoint = 5
+ elseif ( dist( ptLocP1, tFacAdj[1][5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[1][5]) < GEO.EPS_SMALL) then
+ nIdEndPoint = 5
+ nIdIniPoint = 4
+ end
+ end
+ -- versore direzione
+ local vtExtr = tFacAdj[1][nIdIniPoint] - tFacAdj[1][nIdEndPoint]
+ vtExtr:normalize()
+ -- versore direzione di uscita
+ local vtExtrExit
+ -- inserisco le prime tre linee
+ if nIdIniPoint and nIdEndPoint then
+ -- se fresatura da sotto salto la lavorazione
+ if vtExtr:getZ() < WD.DRILL_VZ_MIN then
+ local sErr = 'Error : Impossible insert clean corner from bottom'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- sommo i tre versori per avere una direzione media
+ vtExtrExit = vtN2 + vtN3
+ vtExtrExit:normalize()
+ -- se tipo 1 calcolo angolo tilt di 45°
+ if nTypeConeCut == 1 then
+ vtExtr = vtExtrExit + Z_AX()
+ -- altrimenti tipo 2, calcolo angolo tilt di 33° (dalla verticale)
+ else
+ vtExtr = vtExtrExit + Vector3d(0,0,1.539865)
+ end
+ vtExtr:normalize()
+ local vtCheck = Vector3d(vtExtr)
+ -- se ho un offset angolare ruoto il percorso
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ vtCheck:rotate( Z_AX(), dOffsAng)
+ end
+ -- controllo se c'è collisione con le facce della superfice
+ if nTypeConeCut == 1 and CalcInterference( nNewProc, vtCheck, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), dDiam1, dDiam2,
+ dTall1, dTall2, dDiam3, dTall3) then
+ local sErr = 'Collision detect from clean corner tool and surface'
+ EgtOutLog( sErr)
+ return true, ''
+ end
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdIniPoint], tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ -- se uso utensile cono 60°
+ if nTypeConeCut == 1 then
+ -- se offset angolare valido e/o negativo creo il baffo precedente
+ if dOffsAng < ( 100 * GEO.EPS_SMALL) then
+ -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
+ if dist( tFacAdj[1][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
+ ptApPoint = ptLocP2
+ else
+ ptApPoint = ptLocP1
+ end
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.2)
+ -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta
+ if dLenTrimExt > 10 * GEO.EPS_SMALL then
+ EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ -- prendo il nuovo punto finale
+ ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach)
+ else
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ end
+ table.insert( pAuxId, nAuxId)
+ -- creo linea di ritorno
+ nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ end
+ end
+ end
+ -- inserisco le ultime tre linee
+ -- trovo il secondo punto sulla superfice di riferimento
+ ptLocP1, ptLocP2 = ptLocP3, ptLocP4
+ if ptLocP1 and ptLocP2 then
+ -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
+ if dist( tFacAdj[1][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
+ ptApPoint = ptLocP2
+ else
+ ptApPoint = ptLocP1
+ end
+ -- se uso utensile cono 60°
+ if nTypeConeCut == 1 then
+ -- se offset angolare valido e/o negativo creo il baffo precedente
+ if dOffsAng > -( 100 * GEO.EPS_SMALL) then
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ local dLenTrimExt = dist( tFacAdj[1][nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.2)
+ -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta
+ if dLenTrimExt > 10 * GEO.EPS_SMALL then
+ EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ -- prendo il nuovo punto finale
+ ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach)
+ else
+ -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( nAuxId, tFacAdj[1][nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB)
+ end
+ end
+ table.insert( pAuxId, nAuxId)
+ -- creo linea di ritorno
+ nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ end
+ -- ultima linea di distacco (5mm in direzione utensile)
+ local pEnd = tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr)
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ else
+ -- linea di distacco (2mm in direzione utensile)
+ local pEnd = tFacAdj[1][nIdEndPoint] + ( 2 * vtExtr)
+ nAuxId = EgtLine( nAddGrpId, tFacAdj[1][nIdEndPoint], pEnd, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ -- ultima linea di risalita in Z
+ local pIni = pEnd
+ pEnd = pIni + ( dThick * Z_AX())
+ nAuxId = EgtLine( nAddGrpId, pIni, pEnd, GDB_RT.GLOB)
+ table.insert( pAuxId, nAuxId)
+ end
+ end
+ -- trasformo in percorso
+ if #pAuxId > 0 then
+ AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true)
+ end
+ -- se non c'é il percorso do errore
+ if not AuxId then
+ local sErr = 'Error : impossible make clean corner path'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- modifico versore direzione
+ EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB)
+ -- se ho un offset angolare ruoto il percorso
+ if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
+ EgtRotate( AuxId, tFacAdj[1][nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB)
+ end
+ -- inserisco la lavorazione
+ local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc))
+ local nMchId = EgtAddMachining( sName, sMilling)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', nPartId)
+ -- se flag lavorazione spessore passante setto la nota per spostarla dopo i tagli di lama
+ if bThruThick and nTypeConeCut == 1 then
+ EgtSetInfo( nMchId, 'MOVE_AFTER', 1)
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_YM
+ if vtExtr:getY() > 100 * GEO.EPS_ZERO then
+ nSCC = MCH_SCC.ADIR_YP
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, 0)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 4)
+ -- allungo inizio e fine di 10mm
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10)
+ -- setto affondamento 0
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ -- Note utente con dichiarazione nessuna generazione sfridi per Vmill
+ local sUserNotes = 'VMRS=0;'
+ -- aggiungo alle note massima elevazione
+-- sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dMaxDepth, 1) .. ';'
+ sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( 0.0, 1) .. ';'
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ else
+ local _, sWarn = EgtGetMachMgrWarning( 0)
+ if EgtIsMachiningEmpty() then
+ EgtSetOperationMode( nMchId, false)
+ return false, sWarn
+ end
+ end
+
+ return true, ''
+end
+
+---------------------------------------------------------------------
+local function AddMillCorner( nTypeConeCut, vFace, Proc, nRawId, b3Raw,
+ dToolDiam, nAddGrpId, dThick, nMasterNewProc, dDepthMach,
+ bThruThick)
+
+ local sMilling, dMaxDepth
+ -- se ripresa angolo con fresa cono 60° con ripresa
+ if nTypeConeCut == 1 then
+ -- recupero la lavorazione di fresatura
+ sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner60')
+ if not sMilling then
+ local sErr = 'Error : CleanCorner 60 not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se ripresa angolo con fresa cono piccola senza ripresa
+ else
+ sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner30')
+ if not sMilling then
+ local sErr = 'Error : CleanCorner 30 not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMillTotDiam = 20
+ local dMillDiamTh = 20
+ local dToolLength = 20
+ local dThickTool = 20
+ local dSideAng = 0
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh
+ dMillTotDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) or dMillTotDiam
+ dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or dSideAng
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dThickTool = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dThickTool
+ dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength
+ dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth -- qui è la distanza dal portautensile
+ -- calcolo il secondo diametro del cono
+ dMillTotDiam = dMillDiam + ( abs(dThickTool) * tan(dSideAng)) * 2
+ end
+ end
+ -- copio la feature nel layer di appoggio
+ local nNewProc
+ if nMasterNewProc then
+ nNewProc = nMasterNewProc
+ else
+ nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
+ end
+ local nFacCnt = EgtSurfTmFacetCount( nNewProc)
+ local nFacInd, dDimMin, dDimMax, dDepth, nSurfInt
+ local bMakeLocSurf
+ if nFacCnt <= 4 then
+ -- ottengo le dimensioni apertura, la normale e la faccia inferiore
+ dDimMin, dDimMax, dDepth, _, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId)
+ if nSurfInt then
+ -- uso la dimensione minima anche nel caso che la cava sborda perchè la lavorazione potrebbe collidere con un pezzo limitrofo
+ local dMinWidth = dDimMin
+ nNewProc = EgtSurfTmBySewing( nAddGrpId, {nNewProc,nSurfInt} , true)
+ -- riordino le facce
+ nNewProc = ReorderFacesFromTab( nNewProc, vFace)
+ -- acquisisco il numero della faccia
+ nFacCnt = EgtSurfTmFacetCount( nNewProc)
+ nFacInd = nFacCnt - 1
+ else
+ local sErr = 'Error : cannot create base surface'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ else
+ bMakeLocSurf = true
+ end
+ -- verifico se ciclo chiuso
+ local bClosed = ( abs( vFace[1].AngPrev) > 0.1)
+ -- ciclo di inserimento delle fresate sulle facce del contorno in esame
+ local i = 1
+ -- se faccia finale con fine non lavorato, forzo partenza da prima faccia non tutta saltata (tipo 4)
+ if bClosed and ( vFace[#vFace].Type == 4 or ( vFace[#vFace].Type & 2) ~= 0) then
+ while i <= #vFace and vFace[i].Type == 4 do
+ i = i + 1
+ end
+ end
+ -- se facce tutte da saltare, parto dall'inizio
+ local bAllType4 = ( i > #vFace)
+ if bAllType4 or bClosed then i = 1 end
+ while i <= #vFace do
+ -- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura
+ if ( vFace[i].Type & 2) ~= 0 or vFace[i].Type == 4 then
+ -- variabili costruzione geometria
+ local tFacAdj = {}
+ local nFace1 = vFace[i].Fac
+ local nFace2
+ -- ricavo i tre punti per eventuale superficie locale
+ local ptLoc1, ptLoc2, ptLoc3
+ -- punto precedente (punto precedente della faccia [i])
+ ptLoc3 = vFace[i].PPrev
+ -- aggiungo geometria
+ i = i + 1
+ local j = EgtIf( i <= #vFace, i, EgtIf( bClosed, 1, nil))
+ if not j then
+ return true
+ end
+ nFace2 = vFace[j].Fac
+ -- punto in comune tra le due facce (punto precedente della faccia [j])
+ ptLoc1 = vFace[j].PPrev
+ -- punto successivo ( precedente della faccia successiva)
+ j = j + 1
+ local k = EgtIf( j <= #vFace, j, EgtIf( bClosed, 1, nil))
+ -- se è un percorso aperto prendo il punto medio della seconda faccia come punto locale 2
+ if not k then
+ ptLoc2 = Point3d( vFace[j-1].Cen:getX(), vFace[j-1].Cen:getY(), ptLoc1:getZ())
+ else
+ ptLoc2 = vFace[k].PPrev
+ end
+ -- ricavo i punti e l'angolo interno
+ local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( nNewProc, nFace1, nFace2, GDB_ID.ROOT)
+ -- se punti validi e angolo è interno e non è quasi piatto e >= 90 creo istanza
+ if ptP1 and ptP2 and dAng < 0 and dAng < -6 and dAng > EgtIf( nTypeConeCut == 1, -(90 + 10 * GEO.EPS_SMALL), -(180-dAngleSmall + 10 * GEO.EPS_SMALL)) then
+ local dLen = dist( ptP1, ptP2)
+ table.insert( tFacAdj, { nFace1, nFace2, dLen, ptP1, ptP2, dAng, ptLoc1, ptLoc2, ptLoc3})
+ end
+ -- se ho un elemento creo percorso o percorsi in base al tipo di cono e all'apertura dall'angolo rispetto ai 90°
+ -- con una tolleranza di 2 gradi
+ if #tFacAdj > 0 then
+ if nTypeConeCut == 1 and bMakeTwinCut and (dAng + 90) > 2 then
+ local dAngOffs = (dAng + 90) / 2
+ -- primo taglio
+ local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, -dAngOffs, dDepthMach,
+ bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
+ dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
+ if not bOk then return bOk, sErr end
+ -- secondo taglio
+ bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, dAngOffs, dDepthMach,
+ bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
+ dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
+ if not bOk then return bOk, sErr end
+ -- altrimenti ho un solo percorso
+ else
+ local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId,
+ dToolDiam, dThick, sMilling, 0, dDepthMach,
+ bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool),
+ dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace)
+ if not bOk then return bOk, sErr end
+ end
+ end
+ else
+ i = i + 1
+ end
+ end
+ -- cancello la copia della superfice
+ if nNewProc then
+ EgtErase(nNewProc)
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByChainSaw( Proc, nFacet, nRawId, b3Raw, dElev, dH, dV)
+ local sWarn
+ -- dati della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT)
+ -- Recupero le facce adiacenti alla principale
+ local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacet)[1]
+ if not vAdj or #vAdj == 0 then
+ local sErr = 'Error : main face without adjacencies'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3)
+ -- Cerco una faccia adiacente alla principale sul lato più lungo
+ local nFacAdj
+ local dMaxLen = 0
+ for i = 1, #vAdj do
+ if vAdj[i] >= 0 then
+ local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacet, vAdj[i], GDB_ID.ROOT)
+ local dLen = dist( ptP1, ptP2)
+ local vtAdjN = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT)
+ if dLen > dMaxLen - 1 and vtAdjN:getZ() > -0.1 then
+ nFacAdj = vAdj[i]
+ dMaxLen = dLen
+ EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 3)
+ end
+ end
+ end
+ if not nFacAdj then
+ local sErr = 'Error : long adjacent face not found'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- Recupero la lavorazione
+ local sSawing = WM.FindSawing( 'Sawing')
+ if not sSawing then
+ local sErr = 'Error : chainsawing not found in library'
+ EgtOutLog( sErr)
+ return false, sErr, 'MNF'
+ end
+ -- Recupero i dati dell'utensile
+ local dSawWidth = 75
+ local dSawThick = 8
+ local dMaxDepth = 200
+ if EgtMdbSetCurrMachining( sSawing) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dSawWidth = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawWidth
+ dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
+ dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
+ end
+ end
+ if dSawThick > dV + 10 * GEO.EPS_SMALL then
+ local sErr = 'Error : chainsaw too thick'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- Calcolo uso faccia
+ local nFaceUse = WL.GetNearestParalOpposite( vtN)
+ -- Calcolo angolo 3° asse rot (da direz. utensile)
+ local sRot3Ang = 'A1=180'
+ if WD.GetChainSawBlockedAxis then
+ sRot3Ang = WD.GetChainSawBlockedAxis( 1)
+ end
+ -- Calcolo angoli iniziali suggeriti
+ local sStartAngs
+ if WD.GetChainSawStartAngs then
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT)
+ sStartAngs = WD.GetChainSawStartAngs( vtN2)
+ end
+ -- Lati chiusi
+ local bOpenStart = false
+ local bOpenEnd = false
+ -- Verifico se necessarie più passate
+ local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick)
+ local dStep = 0
+ if nStep > 1 then
+ dStep = ( dV - dSawThick) / ( nStep - 1)
+ end
+ for i = 1, nStep do
+ -- Applico la lavorazione con sega a catena a questa faccia
+ local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
+ local nMchFId = EgtAddMachining( sName, sSawing)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}})
+ -- imposto uso faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
+ -- imposto accorciamento iniziale/finale per estremi aperti/chiusi
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2))
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2))
+ -- imposto angolo 3° asse rot
+ EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang)
+ -- imposto angoli iniziali suggeriti
+ if sStartAngs then
+ EgtSetMachiningParam( MCH_MP.INITANGS, sStartAngs)
+ end
+ -- imposto offset radiale
+ local dOffs = ( i - 1) * dStep
+ EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
+ -- se necessario, limito l'affondamento
+ if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then
+ sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')'
+ dDepth = dMaxDepth - dElev
+ EgtOutLog( sWarn)
+ EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH '..EgtNumToString( dDepth, 1))
+ end
+ -- imposto elevazione
+ local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 2) .. ';'
+ EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ elseif EgtIsMachiningEmpty() then
+ _, sWarn = EgtGetMachMgrWarning( 0)
+ EgtSetOperationMode( nMchFId, false)
+ return false, sWarn
+ end
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByMill( Proc, nFacet, nOthFac, nRawId, b3Raw, dSideDist)
+ -- dati della faccia e dell'altra
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId)
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dDiam = min( dH, dV)
+ local _, vtRef = EgtSurfTmFacetCenter( Proc.Id, nOthFac, GDB_ID.ROOT)
+ -- recupero la lavorazione
+ local sMilling = WM.FindMilling( 'Side')
+ if not sMilling then return false end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMillLen = 10
+ local dMillTotLen = 30
+ local dMaxDepth = 0
+ local dThDiam = 100
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMillLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLen
+ dMillTotLen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dMillTotLen
+ dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth
+ dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam
+ end
+ end
+ if dMillDiam < dDiam or dMaxDepth < dElev then
+ local sErr = 'Error : Side Elevation too big'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ local dMillExtra = dMillTotLen - dMillLen
+ if Proc.Box:getMin():getZ() - dMillExtra < b3Raw:getMin():getZ() - 10 * GEO.EPS_SMALL then
+ local sErr = 'Error : Tool collide with table'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione di contornatura
+ local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sMilling)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
+ -- sistemo i parametri di attacco e uscita
+ local dAddLen = ( WD.MID_GAP or 50) - ( WD.MID_SIC or 5)
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) -- -dMillDiam/2 + dAddLen)
+ EgtSetMachiningParam( MCH_MP.LITANG, 0)
+ EgtSetMachiningParam( MCH_MP.LIPERP, dSideDist + WD.CUT_SIC)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) -- -dMillDiam/2 + dAddLen)
+ EgtSetMachiningParam( MCH_MP.LOTANG, 0)
+ EgtSetMachiningParam( MCH_MP.LOPERP, dSideDist + WD.CUT_SIC)
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameOrOppositeVectorApprox( vtN, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- imposto modo di lavorare la faccia
+ local nFaceUse = WL.GetNearestOrthoOpposite( vtRef, vtN)
+ EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, dMaxDepthOnSide, bEnablePreMill, bMachFromDn, dAng, bAsEnablePreMill, nSinglePass)
+ -- dati della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId)
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dThick = min( dH, dV)
+ local frFace = Frame3d( ptC, vtN)
+ local b3Proc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFace)
+ local dSideElev = b3Proc:getDimZ()
+ local sMilling
+ -- se ho lavorazione custom
+ if sCustomMach then
+ sMilling = sCustomMach
+ -- altrimenti la cerco
+ else
+ sMilling = WM.FindMilling( 'SideGroove')
+ end
+ if not sMilling then
+ local sErr = 'Error : SideGroove not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMillLen = 10
+ local dMillTotLen = 30
+ local dMaxMat = 0
+ local dMillDiamTh = 0
+ if EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMillLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLen
+ dMillTotLen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dMillTotLen
+ if ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE) ~= 0 then
+ dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dMaxMat
+ if not dMaxDepthOnSide or dMaxDepthOnSide < 0.1 then
+ dMaxDepthOnSide = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
+ end
+ else
+ dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat
+ if not dMaxDepthOnSide or dMaxDepthOnSide < 0.1 then
+ dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd')
+ end
+ end
+ dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh
+ end
+ end
+ local dMaxSideElev = EgtIf( dMaxDepthOnSide and dMaxDepthOnSide > 0, dMaxDepthOnSide, dMillDiam / 2 - 30)
+ -- se profondità ribasso è maggiore della capacità dichiarata nelle note o di quella netta al gambo utensile
+ if ( not bEnablePreMill and bMachFromDn) and ( dElev > dMaxSideElev or dElev >= ( 0.5 * ( dMillDiam - dMillDiamTh))) then
+ local sErr = 'Error : Side Elevation too big'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ local dMillExtra = dMillTotLen - dMillLen
+ if Proc.Box:getMin():getZ() - dMillExtra < b3Raw:getMin():getZ() - 10 * GEO.EPS_SMALL then
+ local sErr = 'Error : Tool collide with table'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ if Proc.Fct == 2 and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + 100 * GEO.EPS_SMALL and dMaxMat > dThick + 10 * GEO.EPS_SMALL then
+ local sErr = 'Error : Tool thickness is too big'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- verifico che la lavorazione sia passante dal grezzo
+ local dLongGorge = max( dH, dV)
+ local dExtraLongExtPlus = 0
+ local dExtraLongExtNeg = 0
+ local dExtraLongIni = 0
+ local dExtraLongEnd = 0
+ local bStartPos
+ local bInvertMach
+ local nModifyLeadInOut = 0
+ local nFace2ndFace
+ local dMaxDistToOut = EgtIf( bMachFromDn, 1800, 300)
+ -- se orientato lungo la Y
+ if abs( vtN:getX()) > 0.866 then
+ dExtraLongExtPlus = abs( Proc.Box:getMax():getY() - b3Raw:getMax():getY())
+ dExtraLongExtNeg = abs( Proc.Box:getMin():getY() - b3Raw:getMin():getY())
+ if dLongGorge + dMillDiamTh < b3Raw:getDimY() then
+ nModifyLeadInOut = 1
+ -- se non può sbordare da nessuna parte do errore
+ if dExtraLongExtPlus > dMaxDistToOut and dExtraLongExtNeg > dMaxDistToOut and dElev > dMaxDistToOut then
+ local sErr = 'Error : Not possible insert SideMill groove machining'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se non sborda solo dai lati
+ if dElev < dExtraLongExtPlus and dElev < dExtraLongExtNeg then
+ nModifyLeadInOut = 2
+ end
+ end
+ -- se la distanza superiore è minore della distanza inferiore segno di partire dalla parte positiva
+ if dExtraLongExtPlus < dExtraLongExtNeg then
+ bStartPos = true
+ end
+ -- se normale su X positivo parte dall'alto
+ if vtN:getX() > 0.866 then
+ -- se deve partire dalla parte negativa setto il flag di inversione lavorazione
+ if not bStartPos then
+ bInvertMach = true
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ else
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ end
+ -- asseggno lato di lavoro seconda faccia
+ if bMachFromDn then
+ nFace2ndFace = MCH_MILL_FU.ORTUP_LEFT
+ else
+ nFace2ndFace = MCH_MILL_FU.ORTHO_LEFT
+ end
+ -- altrimenti normale su X negativa parte dal basso
+ else
+ -- se deve partire dalla parte positiva setto il flag di inversione lavorazione
+ if bStartPos then
+ bInvertMach = true
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ else
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ end
+ -- asseggno lato di lavoro seconda faccia
+ if bMachFromDn then
+ nFace2ndFace = MCH_MILL_FU.ORTUP_RIGHT
+ else
+ nFace2ndFace = MCH_MILL_FU.ORTHO_RIGHT
+ end
+ end
+ -- altrimenti orientato lungo la X
+ elseif abs( vtN:getY()) > 0.866 then
+ dExtraLongExtPlus = abs( Proc.Box:getMax():getX() - b3Raw:getMax():getX())
+ dExtraLongExtNeg = abs( Proc.Box:getMin():getX() - b3Raw:getMin():getX())
+ if dLongGorge + dMillDiamTh < b3Raw:getDimX() then
+ nModifyLeadInOut = 1
+ -- se non può sbordare da nessuna parte do errore
+ if dExtraLongExtPlus > dMaxDistToOut and dExtraLongExtNeg > dMaxDistToOut and dElev > dMaxDistToOut then
+ local sErr = 'Error : Not possible insert SideMill groove machining'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se non sborda solo dai lati
+ if dElev < dExtraLongExtPlus and dElev < dExtraLongExtNeg then
+ nModifyLeadInOut = 2
+ end
+ end
+ -- se la distanza positiva è minore della distanza negativa segno di partire dalla parte positiva
+ if dExtraLongExtPlus < dExtraLongExtNeg then
+ bStartPos = true
+ end
+ -- se normale su Y positivo parte da sinistra (parte negativa)
+ if vtN:getY() > 0.866 then
+ -- se deve partire dalla parte positiva setto il flag di inversione lavorazione
+ if bStartPos then
+ bInvertMach = true
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ else
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ end
+ -- assegno lato di lavoro seconda faccia
+ if bMachFromDn then
+ nFace2ndFace = MCH_MILL_FU.ORTUP_FRONT
+ else
+ nFace2ndFace = MCH_MILL_FU.ORTHO_FRONT
+ end
+ -- altrimenti normale su Y negativa parte da destra (parte positiva)
+ else
+ -- se deve partire dalla parte negativa setto il flag di inversione lavorazione
+ if not bStartPos then
+ bInvertMach = true
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ else
+ dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5)
+ dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5)
+ end
+ -- assegno lato di lavoro seconda faccia
+ if bMachFromDn then
+ nFace2ndFace = MCH_MILL_FU.ORTUP_BACK
+ else
+ nFace2ndFace = MCH_MILL_FU.ORTHO_BACK
+ end
+ end
+ end
+ if not bEnablePreMill and not bAsEnablePreMill then
+ dExtraLongIni = 0
+ dExtraLongEnd = 0
+ end
+ -- se ho abilitato la lavorazione di fresatura per garantire passaggio gambo utensile, inserisco la lavorazione
+ local bThroughRaw = false
+ if bEnablePreMill then
+ -- verifico se feature e' passante
+ if ((Proc.Box:getMin():getX() < ( b3Raw:getMin():getX() + 50)) and (Proc.Box:getMax():getX() > ( b3Raw:getMax():getX() - 50))) or
+ ((Proc.Box:getMin():getY() < ( b3Raw:getMin():getY() + 50)) and (Proc.Box:getMax():getY() > ( b3Raw:getMax():getY() - 50))) then
+ bThroughRaw = true
+ end
+
+ -- recupero la lavorazione di taglio
+ local sCuttingGorge = WM.FindCutting( 'Standard')
+ if not sCuttingGorge then
+ local sErr = 'Error : Sawblade not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+
+ -- acquisisco dati utensile lama
+ local dSawThickness = 0
+ local dSawDiam = 0
+ if EgtMdbSetCurrMachining( sCuttingGorge) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dSawThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThickness
+ dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam
+ end
+ end
+
+ -- calcolo larghezza canale
+ local dGorgeWidth = dMillDiam
+ -- verifico se elevazione minore per fare meno tagli
+ if dElev + 2 * WD.COLL_SIC < dGorgeWidth then
+ dGorgeWidth = max( dElev + 2 * WD.COLL_SIC, 0)
+ end
+
+ -- sottraggo lato esterno lapjoint per ottenere larghezza netta del gorge
+ dGorgeWidth = dGorgeWidth - dSideElev
+
+ -- calcolo quanti passi devo fare in larghezza per scaricare l'area di impegno utensile
+ local nNumStep = ceil( ( dGorgeWidth) / ( WD.SAWGORGE_INTERAX or 100))
+ -- calcolo larghezza passate
+ local dC = 0
+ if ( nNumStep - 1) > 0 then
+ dC = ( dGorgeWidth) / ( nNumStep)
+ else
+ nNumStep = 1
+ end
+
+ -- dati utensile fresa piccola
+ local dMillDiamFirst = 0
+ local dMaxMatFirst = 0
+ local bMillInvert = false
+ local bSawInvertSE = false
+
+ -- se non passante, aggiungo fresatura area della fresa
+ if not bThroughRaw and nNumStep - 1 > 0 then
+ local SquareId -- Id della composita da fresare
+ local dSawShortening = sqrt( b3Raw:getDimZ() * ( dSawDiam - b3Raw:getDimZ())) -- da calcolare in base a raggio lama e spessore grezzo
+ -- gruppo ausiliario
+ local nAddGrpId = WL.GetAddGroup( Proc.PartId)
+ -- disegno quadrato di fresatura
+ local p3Start
+ -- se orientato lungo la Y (direzione)
+ if abs( vtN:getX()) > 0.866 then
+ local dStartX = EgtIf( vtN:getX() > 0.866, Proc.Box:getMax():getX(), Proc.Box:getMin():getX())
+ local dStartY = EgtIf( bStartPos, Proc.Box:getMin():getY(), Proc.Box:getMax():getY())
+ p3Start = Point3d( dStartX, dStartY, Proc.Box:getMin():getZ())
+ local vtNPerp = Vector3d( vtN)
+ vtNPerp:rotate(-Z_AX(), 90 * EgtIf( bStartPos, 1, -1) * EgtIf( vtN:getX() > 0.866, 1, -1))
+ local FirstLineId = EgtLinePVL( nAddGrpId, p3Start, vtNPerp, dMillDiam / 2 , GDB_RT.GLOB) -- Y_AX()
+ local SecondLineId = EgtLinePVL( nAddGrpId, EgtEP( FirstLineId, GDB_RT.GLOB), vtN, dMillDiam - dSideElev, GDB_RT.GLOB) -- -X_AX()
+ local dThirdLineLen = min( (dMillDiam / 2) + ( Proc.Box:getMax():getY() - Proc.Box:getMin():getY()), dSawShortening + 10)
+ local ThirdLineId = EgtLinePVL( nAddGrpId, EgtEP( SecondLineId, GDB_RT.GLOB), -vtNPerp, dThirdLineLen, GDB_RT.GLOB) -- -Y_AX()
+ local FourthLineId = EgtLinePVL( nAddGrpId, EgtEP( ThirdLineId, GDB_RT.GLOB), -vtN, dMillDiam -dSideElev , GDB_RT.GLOB) -- X_AX()
+ SquareId = EgtCurveCompo( nAddGrpId, { FirstLineId, SecondLineId, ThirdLineId, FourthLineId})
+ bMillInvert = EgtIf( vtN:getX() > 0.866, not (bStartPos or false), bStartPos or false)
+ bSawInvertSE = EgtIf( vtN:getX() > 0.866, bStartPos or false, not (bStartPos or false))
+ -- altrimenti orientato lungo la X
+ elseif abs( vtN:getY()) > 0.866 then
+ local dStartX = EgtIf( bStartPos, Proc.Box:getMin():getX(), Proc.Box:getMax():getX())
+ local dStartY = EgtIf( vtN:getY() > 0.866, Proc.Box:getMax():getY(), Proc.Box:getMin():getY())
+ p3Start = Point3d( dStartX, dStartY, Proc.Box:getMin():getZ())
+ local vtNPerp = Vector3d( vtN)
+ vtNPerp:rotate(-Z_AX(), 90 * EgtIf( bStartPos, -1, 1) * EgtIf( vtN:getY() > 0.866, 1, -1))
+ local FirstLineId = EgtLinePVL( nAddGrpId, p3Start, vtNPerp, dMillDiam / 2 , GDB_RT.GLOB) -- Y_AX()
+ local SecondLineId = EgtLinePVL( nAddGrpId, EgtEP( FirstLineId, GDB_RT.GLOB), vtN, dMillDiam -dSideElev, GDB_RT.GLOB) -- -X_AX()
+ local dThirdLineLen = min( (dMillDiam / 2) + ( Proc.Box:getMax():getX() - Proc.Box:getMin():getX()), dSawShortening + 10)
+ local ThirdLineId = EgtLinePVL( nAddGrpId, EgtEP( SecondLineId, GDB_RT.GLOB), -vtNPerp, dThirdLineLen, GDB_RT.GLOB) -- -Y_AX()
+ local FourthLineId = EgtLinePVL( nAddGrpId, EgtEP( ThirdLineId, GDB_RT.GLOB), -vtN, dMillDiam -dSideElev , GDB_RT.GLOB) -- X_AX()
+ SquareId = EgtCurveCompo( nAddGrpId, { FirstLineId, SecondLineId, ThirdLineId, FourthLineId})
+ bMillInvert = EgtIf( vtN:getY() > 0.866, bStartPos or false, not (bStartPos or false))
+ bSawInvertSE = EgtIf( vtN:getY() > 0.866, not (bStartPos or false), bStartPos or false)
+ end
+
+ -- recupero la lavorazione
+ local sMillingGorge = WM.FindMilling( 'Gorge', nil, nil, nil, 80)
+ if not sMillingGorge then
+ local sErr = 'Error : Gorge not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- acquisisco dati utensile
+ if EgtMdbSetCurrMachining( sMillingGorge) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiamFirst = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiamFirst
+ dMaxMatFirst = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMatFirst
+ end
+ end
+ -- inserisco la lavorazione di fresatura
+ local sNameGorge = 'Gorge_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. tostring( nFacet) .. '_' .. tostring( nNm)
+ local nMchFId = EgtAddMachining( sNameGorge, sMillingGorge)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sNameGorge .. '-' .. sMillingGorge
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( SquareId)
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if abs( vtN:getZ()) < GEO.EPS_SMALL then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- imposto modo di lavorare la faccia
+ local nFaceUse = WL.GetNearestParalOpposite( Z_AX(), vtN)
+ EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
+ -- imposto elevazione e step
+ local dStep = EgtGetMachiningParam( MCH_MP.STEP)
+ if dStep < GEO.EPS_SMALL then dStep = dMaxMat end
+ ---- se sto lavorando la gola centrale setto l'elevazione e l'affondamento
+ --if nSinglePass and nSinglePass == 0 then
+ -- local dZElev = b3Raw:getDimZ()
+ -- local dDepth = Proc.Box:getMax():getZ() - b3Raw:getMin():getZ()
+ -- EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dZElev, 3) .. ';')
+ -- EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ --end
+ EgtSetMachiningParam( MCH_MP.STEP, dStep)
+ -- imposto invert in base al lato fresa
+ local bWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE)
+ if bWorkSide == MCH_MILL_WS.RIGHT then
+ bMillInvert = not bMillInvert
+ end
+ EgtSetMachiningParam( MCH_MP.INVERT, bMillInvert)
+ -- aggiungo allungamenti iniziali e finali
+ EgtSetMachiningParam( EgtIf( bMillInvert, MCH_MP.STARTADDLEN, MCH_MP.ENDADDLEN), -dMillDiamFirst / 2 - dSawThickness / 2)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ end
+
+ -- inserisco la lavorazione
+ local nNm = 0
+ -- passi di allargamento
+ for i = 1, nNumStep - 1 do
+ nNm = nNm + 1
+ -- inserisco la lavorazione di taglio sfrido gorge
+ local sNameGorge = 'GorgeCut_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. tostring( nFacet) .. '_' .. tostring( nNm)
+ local nMchFId = EgtAddMachining( sNameGorge, sCuttingGorge)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sNameGorge .. '-' .. sCuttingGorge
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
+
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- assegno invert
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ -- assegno il lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- EgtIf( bMillInvert, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT))
+ -- assegno l'attacco e l'uscita
+ if not bThroughRaw and bSawInvertSE then
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.STRICT)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.CENT)
+ -- aggiungo allungamento finale
+ if not bThroughRaw then
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, ( dMillDiam / 2) - ( dMillDiamFirst / 2))
+ end
+ elseif not bThroughRaw and not bSawInvertSE then
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LO.CENT)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LI.STRICT)
+ -- aggiungo allungamento finale
+ if not bThroughRaw then
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, ( dMillDiam / 2) - ( dMillDiamFirst / 2))
+ end
+ else
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LO.CENT)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LI.CENT)
+ end
+ -- aggiungo l'offset laterale
+ EgtSetMachiningParam( MCH_MP.OFFSL, ( dSideElev - dSawThickness + ( dC * ( i))))
+ -- nessun criterio per il braccio è necessario
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
+
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ end
+ end
+ -- inserisco la lavorazione di ribasso o gola
+ local sName = EgtIf( bEnablePreMill ~= nil, 'SideMill_', 'Mill_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sMilling)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- se ho abilitato la lavorazione di lama per garantire passaggio utensile, setto la nota per spostare la fresatura dopo i tagli di lama
+ if bEnablePreMill or bAsEnablePreMill then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
+ -- imposto posizione braccio porta testa
+ --local nSCC = MCH_SCC.ADIR_ZP
+ --if abs( vtN:getZ()) < GEO.EPS_SMALL then
+ -- nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ --end
+ local nSCC = MCH_SCC.ADIR_NEAR
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- imposto modo di lavorare la faccia
+ local nFaceUse = WL.GetNearestParalOpposite( Z_AX(), vtN)
+ EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
+ -- imposto elevazione e step
+ local dStep = EgtGetMachiningParam( MCH_MP.STEP)
+ if dStep < GEO.EPS_SMALL then dStep = 0.75 * dMaxMat end
+ local nStep = ceil( ( dThick - dMaxMat) / dStep)
+ dStep = max( ( dThick - dMaxMat) / max( nStep, 1), 0)
+ local dMaxElev = max( ( nStep + 1) * dStep - GEO.EPS_SMALL, 0)
+ if nSinglePass and nSinglePass > 0 then
+ dStep = 0
+ if nSinglePass == 1 then
+ EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat)
+ end
+ end
+ EgtSetMachiningParam( MCH_MP.STEP, dStep)
+ EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dMaxElev, 3) .. ';')
+ -- setto il lato di lavoro standard
+ EgtSetMachiningParam( MCH_MP.INVERT, true)
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
+ -- modifico ingressi e uscita
+ -- se ho inserito il pretaglio modifico
+ if bEnablePreMill or bAsEnablePreMill then
+ if nModifyLeadInOut > 0 then
+ -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita
+ if dElev > ( 0.5 * dMillDiam) then
+ if nModifyLeadInOut == 1 then
+ -- setto il tipo di passo a una via
+ EgtSetMachiningParam( MCH_MP.STEPTYPE, MCH_MILL_ST.ONEWAY)
+ -- modifico il tipo di uscita
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.PERP_TG)
+ EgtSetMachiningParam( MCH_MP.LIPERP, 0)
+ -- modifico dati supplementari uscita
+ EgtSetMachiningParam( MCH_MP.LOPERP, 0.5)
+ EgtSetMachiningParam( MCH_MP.LOTANG, -( dLongGorge + dExtraLongIni + dExtraLongEnd))
+ else
+ EgtSetMachiningParam( MCH_MP.LIPERP, dElev)
+ EgtSetMachiningParam( MCH_MP.LOPERP, dElev)
+ end
+ end
+ -- setto allungamenti iniziali e finali
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd)
+ if bInvertMach then
+ -- setto il lato di lavoro invertito
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ else
+ -- setto allungamenti iniziali e finali
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd)
+ -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita
+ if dElev > ( 0.5 * dMillDiam) then
+ -- setto allungamenti perpendicolari
+ EgtSetMachiningParam( MCH_MP.LIPERP, 0)
+ EgtSetMachiningParam( MCH_MP.LOPERP, 0)
+ end
+ end
+ -- se richiesto, setto la nota per spostare la lavorazione alla fine
+ if not WD.SIDEMILL_BEFORE then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ else
+ if nModifyLeadInOut > 0 then
+ -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita
+ if dElev > ( 0.5 * dMillDiam) then
+ -- setto il tipo di passo a una via
+ EgtSetMachiningParam( MCH_MP.STEPTYPE, 1)
+ end
+ if bInvertMach then
+ -- setto il lato di lavoro invertito
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ end
+ -- setto allungamenti iniziali e finali
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd)
+ -- se richiesto, setto la nota per spostare la lavorazione alla fine
+ if not WD.SIDEMILL_BEFORE then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ -- verifico se devo lavorare anche la seconda faccia basandomi sul valore dell'angolo interno
+ if dAng and dAng > -90 + 10 * GEO.EPS_SMALL then
+ local nOtherFacet = abs( nFacet - 1)
+ -- inserisco la lavorazione di contornatura
+ local sName = 'Mill_Oth_Fac_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sMilling)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, nOtherFacet}})
+ -- imposto posizione braccio porta testa
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFacet, GDB_ID.ROOT)
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameOrOppositeVectorApprox( vtN2, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- imposto modo di lavorare la faccia
+ EgtSetMachiningParam( MCH_MP.FACEUSE, nFace2ndFace)
+ EgtSetMachiningParam( MCH_MP.STEP, 0)
+ local dMaxElev = dMaxMat
+ EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dMaxElev, 3) .. ';')
+ if bMachFromDn then
+ EgtSetMachiningParam( MCH_MP.INVERT, true)
+ EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat)
+ else
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ end
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
+ -- modifico ingressi e uscita
+ -- se ho inserito il pretaglio modifico
+ if bEnablePreMill or bAsEnablePreMill then
+ if nModifyLeadInOut > 0 then
+ -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita
+ if dElev > ( 0.5 * dMillDiam) then
+ -- setto il tipo di passo a una via
+ EgtSetMachiningParam( MCH_MP.STEPTYPE, 1)
+ -- modifico il tipo di uscita
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 5)
+ EgtSetMachiningParam( MCH_MP.LIPERP, 0)
+ -- modifico dati supplementari uscita
+ EgtSetMachiningParam( MCH_MP.LOPERP, 0.5)
+ EgtSetMachiningParam( MCH_MP.LOTANG, -( dLongGorge + dExtraLongIni + dExtraLongEnd))
+ end
+ -- setto allungamenti iniziali e finali
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd)
+ if bInvertMach then
+ -- setto il lato di lavoro invertito
+ if bMachFromDn then
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ else
+ EgtSetMachiningParam( MCH_MP.INVERT, true)
+ end
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ else
+ -- setto allungamenti iniziali e finali
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd)
+ -- Invece del numero di passi in sgrossatura confronto il raggio fresa con l'elevazione dalla normale
+ -- per vedere se devo modificare l'uscita
+ -- if nNumStep > 1 then
+ if dElev > ( 0.5 * dMillDiam) then
+ -- setto allungamenti perpendicolari
+ EgtSetMachiningParam( MCH_MP.LIPERP, 0)
+ EgtSetMachiningParam( MCH_MP.LOPERP, 0)
+ end
+ end
+ -- se richiesto, setto la nota per spostare la lavorazione alla fine
+ if not WD.SIDEMILL_BEFORE then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ else
+ if nModifyLeadInOut > 0 then
+ -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita
+ if dElev > ( 0.5 * dMillDiam) then
+ -- setto il tipo di passo a una via
+ EgtSetMachiningParam( MCH_MP.STEPTYPE, 1)
+ end
+ if bInvertMach then
+ -- setto il lato di lavoro invertito
+ if bMachFromDn then
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ else
+ EgtSetMachiningParam( MCH_MP.INVERT, true)
+ end
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ end
+ end
+ -- setto allungamenti iniziali e finali
+ EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni)
+ EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd)
+ -- se richiesto, setto la nota per spostare la lavorazione alla fine
+ if not WD.SIDEMILL_BEFORE then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ end
+
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar)
+ -- dati della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId)
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
+ local dDiam = min( dH, dV)
+ -- gruppo ausiliario
+ local nAddGrpId = WL.GetAddGroup( Proc.PartId)
+ local nNewProc, nNumFacet = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet)
+ -- se forma ad L
+ local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc.Id, Proc.Fct) or TestElleShape4( Proc.Id, Proc.Fct) == 2)
+ if bIsL then
+ dDiam = 2 * dDiam
+ end
+ -- se forma ad U
+ local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc.Id, Proc.Fct))
+ if bIsU then
+ local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
+ -- prendo la linea di base
+ local dMiddleFacetLength = 0
+ if abs( dElev - dH2) < 1 and abs( dElev - dV2) > 1 then
+ dMiddleFacetLength = dV2
+ elseif abs( dElev - dV2) < 1 and abs( dElev - dH2) > 1 then
+ dMiddleFacetLength = dH2
+ end
+ if dMiddleFacetLength > dDiam then
+ dDiam = min( 2 * dDiam, dMiddleFacetLength)
+ end
+ end
+ -- in presenza di angoli interni, limito secondo impostazione globale il diametro massimo utensile
+ if Proc.Fct == 3 and bIsL then
+ dDiam = min( dDiam, WD.MAXDIAM_POCK_CORNER or 1000)
+ elseif Proc.Fct >= 4 then
+ dDiam = min( dDiam, WD.MAXDIAM_POCK_CORNER or 1000)
+ end
+ -- recupero la lavorazione
+ local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dElev)
+ if not sPocketing then
+ sPocketing = WM.FindPocketing( 'Pocket', dDiam)
+ if not sPocketing then
+ local sErr = 'Error : pocketing not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMaxDepth = 0
+ local dThDiam = 100
+ if EgtMdbSetCurrMachining( sPocketing) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth
+ dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam
+ end
+ end
+ -- inserisco la lavorazione di svuotatura
+ local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sPocketing)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- se lavorazione di fianco setto la nota per spostarla dopo i tagli di lama
+ if vtN:getZ() < WD.NZ_MINA then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, nFacet}})
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameVectorApprox( vtN, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente
+ local dThElev = dThDiam / 2 * sqrt( vtN:getX() * vtN:getX() + vtN:getY() * vtN:getY())
+ local dDepth = 0
+ local sWarn = ''
+ if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then
+ dDepth = dMaxDepth - dElev - dThElev
+ sWarn = 'Warning : elevation bigger than max tool depth'
+ EgtOutLog( sWarn)
+ end
+ EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
+ -- imposto elevazione
+ EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( min( dElev, dMaxDepth), 1) .. ';')
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ -- verifica parametro Q per pulitura spigoli
+ if bCheckQPar and not ( bIsU and AreSameOrOppositeVectorApprox( vtN, Z_AX())) then
+ -- lettura parametri (probabile/i parametro/i Q)
+ local nConeCut = EvaluateQParam( Proc)
+ -- recupero i dati di tutte le facce
+ local vFace, dMaxWidth = GetFacesData( nNewProc, false, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, Proc.PartId)
+ -- se abilitata la lavorazione corner con stop macchina
+ if nConeCut == 1 then
+ local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw,
+ dMillDiam, nAddGrpId, dMaxWidth, nNewProc, dDepth)
+ if not bMcok then return bMcok, sMcErr end
+ elseif nConeCut == 2 then
+ local sErr = 'Clean corner 30° is not applied on pocketing'
+ EgtOutLog( sErr)
+ EgtErase( nNewProc)
+ else
+ EgtErase( nNewProc)
+ end
+ else
+ EgtErase( nNewProc)
+ end
+ return true, sWarn
+end
+
+---------------------------------------------------------------------
+local function MakeOneFace( Proc, nRawId, b3Raw)
+ -- dati della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ -- dimensioni della faccia
+ local _, dDimH, dDimV = WL.GetFaceHvRefDim( Proc.Id, 0)
+ -- recupero la lavorazione di taglio con lama e i suoi parametri
+ local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard')
+ -- se non inclinata o capacità di taglio non sufficiente, provo con svuotatura
+ if not sCutting or vtN:getZ() > 0.866 or dSawMaxDepth < dDimV + WD.CUT_SIC then
+ -- faccio con svuotatura
+ local nFacet = 0
+ return MakeByPocketing( Proc, nFacet, nRawId, b3Raw)
+ end
+ -- eseguo il taglio di lama
+ local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. tostring( Proc.Id)
+ local nMchId = EgtAddMachining( sName, sCutting)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( { { Proc.Id, 0}})
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ -- assegno il lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- assegno l'attacco e l'uscita
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.CENT)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.CENT)
+ -- nessun criterio per il braccio è necessario
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeTwoFaces( Proc, nRawId, b3Raw)
+ -- dati delle facce
+ local ptC = {}
+ local vtN = {}
+ ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT)
+ -- determino l'intersezione tra le due facce
+ local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
+ if not bAdj then
+ return false, 'Feature with two faces not adjacentes'
+ end
+ -- se equivalente ad un contorno
+ if abs( ptP1:getZ() - ptP2:getZ()) > 0.9 * b3Raw:getDimZ() then
+ -- verifico ordinamento (esterno a destra)
+ if ( vtN[1] ^ ( ptP1 - ptC[1])) * Z_AX() < 0 then
+ EgtSurfTmSwapFacets( Proc.Id, 0, 1)
+ end
+ -- applico lavorazione di contorno libero
+ return FreeContour.Make( Proc, nRawId, b3Raw)
+ end
+ -- versore della linea di intersezione
+ local vtX = ptP2 - ptP1 ; vtX:normalize()
+ -- larghezza delle facce ortogonalmente all'intersezione
+ local dDimY = {}
+ for i = 1, 2 do
+ local vtY = vtN[i] ^ vtX ; vtY:normalize()
+ local frRef = Frame3d( ptC[i], ptC[i] + 100 * vtX, ptC[i] + 100 * vtY)
+ local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, i - 1, GDB_BB.STANDARD, frRef)
+ dDimY[i] = b3Ref:getDimY()
+ end
+ -- recupero la lavorazione di taglio con lama e i suoi parametri
+ local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard')
+ -- se parametro Q abilita lavorazione ribasso con fresa di fianco
+ local _, nUseMillOnSide = EvaluateQParam( Proc)
+ local dMaxZVers, dMinZVers
+ if nUseMillOnSide >= 1 then
+ dMaxZVers = 0.866
+ dMinZVers = 0.5
+ else
+ dMaxZVers = 0.95
+ dMinZVers = 0.1
+ end
+ -- se di fianco in basso
+ local dMaxThick, dMinSideElev
+ if vtN[1]:getZ() < -dMaxZVers or vtN[2]:getZ() < -dMaxZVers then
+ if vtN[1]:getZ() < -0.5 then
+ dMaxThick = dDimY[2]
+ dMinSideElev = dDimY[1]
+ elseif vtN[2]:getZ() < -0.5 then
+ dMaxThick = dDimY[1]
+ dMinSideElev = dDimY[2]
+ end
+ end
+ local sMillOnSide, dTMaxDepth, dMaxMat, dDiam = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev)
+ local bEnableMillOnSide
+ if sMillOnSide and nUseMillOnSide >= 1 then
+ dMaxZVers = 0.866
+ dMinZVers = 0.5
+ bEnableMillOnSide = true
+ else
+ dMaxZVers = 0.95
+ dMinZVers = 0.1
+ end
+ -- se di fianco in basso
+ if vtN[1]:getZ() < -dMaxZVers or vtN[2]:getZ() < -dMaxZVers then
+ -- cerco la faccia verticale o quasi
+ local nFacet = EgtIf( abs( vtN[1]:getZ()) < dMinZVers, 0, 1)
+ -- cerco nei parametri utensili la nota di affondamento di fianco SIDEDEPTH
+ local dMaxDepthOnSide = 0
+ local dMillDiam = 0
+ local dMillDiamTh = 0
+ if bEnableMillOnSide and EgtMdbSetCurrMachining( sMillOnSide) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh
+ dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide
+ dMaxDepthOnSide = min( dMaxDepthOnSide, 0.5 * ( dMillDiam - dMillDiamTh))
+ end
+ end
+ local dMaxDist = 300
+ if bEnableMillOnSide and dMaxDepthOnSide > 0 then
+ dMaxDist = dMaxDepthOnSide
+ end
+ -- se vicino al bordo del grezzo e non troppo larga, provo con fresatura di fianco
+ local ptMid = ( ptP1 + ptP2) / 2
+ local bMakeFirstGroove
+ local bMachFromDn = true
+ local bInsertMach
+ local dSideDist
+ -- per evitare errori in casi di pezzi molto stretti, verifico le distanze in base alla direzione della faccia
+ -- se normale verso X
+ if vtN[nFacet+1]:getX() > 0.99 then
+ dSideDist = abs( ptMid:getX() - b3Raw:getMax():getX())
+ -- altrimenti se normale verso X-
+ elseif vtN[nFacet+1]:getX() < -0.99 then
+ dSideDist = abs( ptMid:getX() - b3Raw:getMin():getX())
+ -- altrimenti se normale verso Y+
+ elseif vtN[nFacet+1]:getY() > 0.99 then
+ dSideDist = abs( ptMid:getY() - b3Raw:getMax():getY())
+ -- altrimenti se normale verso Y-
+ elseif vtN[nFacet+1]:getY() < -0.99 then
+ dSideDist = abs( ptMid:getY() - b3Raw:getMin():getY())
+ end
+ if dSideDist and dSideDist < dMaxDist then
+ bInsertMach = true
+ bMakeFirstGroove = false
+ -- altrimenti la distanza è maggiore e se è sempre abilitata la lavorazione MillOnSide
+ elseif bEnableMillOnSide and dMaxDepthOnSide then
+ bInsertMach = true
+ bMakeFirstGroove = true
+ end
+ -- se posso eseguire la lavorazione per distanza inferiore utensile o lavorazione preceduta da sgossatura gola
+ if bInsertMach then
+ return MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng)
+ else
+ local sErr = 'Error feature not machinable (dimensions)'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- se altrimenti di fianco in alto
+ elseif vtN[1]:getZ() > dMaxZVers or vtN[2]:getZ() > dMaxZVers then
+ -- cerco la faccia con il maggior numero di adiacenze (e minor elevazione)
+ local nFacInd, _, nFacInd2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+ if nFacInd == -2 then
+ local sErr = 'Error feature with 2 faces with undercut'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+ local dSideDist
+ local ptMid = ( ptP1 + ptP2) / 2
+ -- faccia orizzontale
+ local nFacet = EgtIf( vtN:getZ() >= WD.NZ_MINA, nFacInd, nFacInd2)
+ -- faccia verticale
+ local nFacetVert = EgtIf( nFacet == nFacInd, nFacInd2, nFacInd)
+ local vtNV = EgtSurfTmFacetNormVersor( Proc.Id, nFacetVert, GDB_ID.ROOT)
+ -- per evitare errori in casi di pezzi molto stretti, verifico le distanze in base alla direzione della faccia
+-- local dSideDist = min( abs( ptMid:getX() - b3Raw:getMin():getX()), abs( ptMid:getX() - b3Raw:getMax():getX()),
+-- abs( ptMid:getY() - b3Raw:getMin():getY()), abs( ptMid:getY() - b3Raw:getMax():getY()))
+ -- se normale verso X
+ if vtNV:getX() > 0.99 then
+ dSideDist = abs( ptMid:getX() - b3Raw:getMax():getX())
+ -- altrimenti se normale verso X-
+ elseif vtNV:getX() < -0.99 then
+ dSideDist = abs( ptMid:getX() - b3Raw:getMin():getX())
+ -- altrimenti se normale verso Y+
+ elseif vtNV:getY() > 0.99 then
+ dSideDist = abs( ptMid:getY() - b3Raw:getMax():getY())
+ -- altrimenti se normale verso Y-
+ elseif vtNV:getY() < -0.99 then
+ dSideDist = abs( ptMid:getY() - b3Raw:getMin():getY())
+ end
+ -- cerco nei parametri utensili la nota di affondamento di fianco SIDEDEPTH
+ local dMaxDepthOnSide = 0
+ local dMillDiam = 0
+ if bEnableMillOnSide and EgtMdbSetCurrMachining( sMillOnSide) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide
+ end
+ end
+ -- 2021.10.08 E.S. in base a richieste del cliente:
+ -- Se parametro Q riduce utilizzo lavorazione di lato come lama ed elevazione laterale supera il 60% diametro utensile
+ -- disabilito
+ if nUseMillOnSide == 2 and dSideDist > 0.6 * dMillDiam then
+ bEnableMillOnSide = false
+ end
+ -- per il fianco in alto non ci sono problemi di inserimento massimo laterale, setto la variabile pari al raggio utensile - 1mm
+ dMaxDepthOnSide = ( 0.5 * dMillDiam) - 1
+ local dMaxDist = 300
+ if bEnableMillOnSide and dMaxDepthOnSide > 0 then
+ dMaxDist = dMaxDepthOnSide
+ end
+ -- se vicino al bordo del grezzo e non troppo larga, provo con fresatura di fianco
+ local bMakeFirstGroove = false
+ local bLikeAsMakeFirstGroove
+ local bMachFromDn = false
+ local bInsertMach
+ if dSideDist and dSideDist < dMaxDist then
+ -- se abilitata SideMill
+ if bEnableMillOnSide and dMaxDepthOnSide > 0 then
+ bLikeAsMakeFirstGroove = false
+ return MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove)
+ elseif MakeByMill( Proc, nFacet, 1 - nFacet, nRawId, b3Raw, dSideDist) then
+ return true
+ end
+ elseif bEnableMillOnSide and dMaxDepthOnSide > 0 then
+ bLikeAsMakeFirstGroove = true
+ local bOk, sErr = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove)
+ if bOk then return true end
+ end
+ -- se non inclinate o capacità di taglio non sufficiente o non molto grandi (80mm), provo con contornatura o svuotatura
+ if not sCutting or dSawMaxDepth < dDimY[1] + WD.CUT_SIC or dSawMaxDepth < dDimY[2] + WD.CUT_SIC or dDimY[1] < 80 or dDimY[2] < 80 then
+ -- eseguo la svuotatura
+ return MakeByPocketing( Proc, nFacet, nRawId, b3Raw)
+ end
+ -- se una delle due facce rivolta verso il basso
+ elseif vtN[1]:getZ() < -0.001 or vtN[2]:getZ() < -0.001 then
+ -- cerco la faccia rivolta verso l'alto
+ local nFacet
+ if vtN[1]:getZ() > 0 then
+ nFacet = 0
+ elseif vtN[2]:getZ() > 0 then
+ nFacet = 1
+ else
+ local sErr = 'Error feature with 2 faces facing down'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- eseguo la svuotatura
+ return MakeByPocketing( Proc, nFacet, nRawId, b3Raw)
+ end
+ -- ordino i tagli per fare prima quello meno inclinato
+ local nOrd = { 0, 1}
+ if vtN[2]:getZ() > vtN[1]:getZ() then
+ nOrd = { 1, 0}
+ end
+ -- eseguo i tagli di lama
+ for i = 1, 2 do
+ -- inserisco la lavorazione
+ local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. tostring( Proc.Id) .. '_' .. tostring( i)
+ local nMchId = EgtAddMachining( sName, sCutting)
+ if not nMchId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchId, 'Part', Proc.PartId)
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( { { Proc.Id, nOrd[i]}})
+ -- percorso da non invertire
+ EgtSetMachiningParam( MCH_MP.INVERT, false)
+ -- assegno affondamento
+ EgtSetMachiningParam( MCH_MP.DEPTH, 0)
+ -- assegno il lato di lavoro
+ EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
+ -- assegno l'attacco e l'uscita
+ EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.CENT)
+ EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.CENT)
+ -- nessun criterio per il braccio è necessario
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchId, false)
+ return false, sErr
+ end
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+local function MakeMoreFaces( Proc, nRawId, b3Raw)
+ -- con una faccia di fondo valida
+ if Proc.Stype == 1 or Proc.Stype == 2 then
+ -- recupero eventuale flag forzatura svuotatura
+ local bPckt = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1)
+ -- cerco la faccia con il maggior numero di adiacenze
+ local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+ -- se necessario scambio le facce
+ if Proc.Stype == 2 then
+ nFacInd, dElev, nFacInd2, dElev2 = nFacInd2, dElev2, nFacInd, dElev
+ end
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+ local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
+ -- se di fianco
+ if not bPckt and Proc.Fct >= 3 and vtN:getZ() < WD.NZ_MINA then
+ -- recupero elevazione faccia in feature
+ local dSideElev = WL.GetFaceElevation( Proc.Id, nFacInd)
+ -- se abilitata lavorazione ribasso con fresa di fianco e parametro Q03 abilitato
+ local sMillOnSide, dTMaxDepth, dMaxMat, dDiam = WM.FindMilling( 'SideMill', nil, nil, nil, nil, min( dH, dV), nil, dSideElev)
+ local _, nUseMillOnSide = EvaluateQParam( Proc)
+ -- se ho abilitata lavorazione di fresa di fianco
+ if Proc.Fct >= 3 and sMillOnSide and nUseMillOnSide >= 1 then
+ -- cerco nei parametri utensili la nota di affondamento di fianco SIDEDEPTH
+ local dMaxDepthOnSide = 0
+ local dMillDiam = 0
+ if EgtMdbSetCurrMachining( sMillOnSide) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide
+ end
+ end
+ local bMakeFirstGroove
+ local bLikeAsMakeFirstGroove
+ local bInsertMach
+ local dElevToPiece = WL.GetFaceElevation( Proc.Id, nFacInd, nRawId)
+ -- Se distanza dal grezzo è minore della Max lavorazione laterale utensile
+ if dElevToPiece < dMaxDepthOnSide then
+ bInsertMach = true
+ bMakeFirstGroove = false
+ -- altrimenti la distanza è maggiore e se è sempre abilitata la lavorazione MillOnSide
+ elseif dMaxDepthOnSide > 0 then
+ bInsertMach = true
+ bMakeFirstGroove = true
+ end
+ -- se posso eseguire la lavorazione per distanza inferiore utensile o lavorazione preceduta da sgossatura gola
+ -- e gola più grande o uguale spessore utensile
+ if bInsertMach and dMaxMat <= min( dH, dV) + 20 * GEO.EPS_SMALL then
+ local nSinglePass = 0
+ bLikeAsMakeFirstGroove = bMakeFirstGroove
+ -- se positivo setto il flag per lavorare singola passata bassa e disabilito sgrossatura
+ if vtN:getZ() > 20 * GEO.EPS_SMALL then
+ nSinglePass = 1
+ bMakeFirstGroove = false
+ -- se negativo setto il flag per lavorare singola passata alta e disabilito sgrossatura
+ elseif vtN:getZ() < -20 * GEO.EPS_SMALL then
+ nSinglePass = 2
+ bMakeFirstGroove = false
+ end
+ return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, EgtIf( dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, nil, nil, bLikeAsMakeFirstGroove, nSinglePass)
+ end
+ else
+ -- fresatura (se definita)
+ local sMilling = WM.FindMilling( 'SideGroove')
+ -- recupero i dati dell'utensile
+ local dMaxMat = 1000
+ local dMaxDepthOnSide = 0
+ if sMilling and EgtMdbSetCurrMachining( sMilling) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ local dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ if ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE) ~= 0 then
+ dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dMaxMat
+ dMaxDepthOnSide = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
+ else
+ dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat
+ dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd')
+ end
+ if not dMaxDepthOnSide then
+ local dMillDiamTh = EgtTdbGetCurrToolThDiam() or 60
+ dMaxDepthOnSide = ( dMillDiam - dMillDiamTh) / 2
+ end
+ end
+ end
+ if sMilling and dElev < dMaxDepthOnSide and dMaxMat <= min( dH, dV) + 20 * GEO.EPS_SMALL then
+ return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, sMilling)
+ -- altrimenti sega a catena
+ else
+ return MakeByChainSaw( Proc, nFacInd, nRawId, b3Raw, dElev, dH, dV)
+ end
+ end
+ end
+ local nFacet = EgtIf( bPckt or vtN:getZ() >= WD.NZ_MINA, nFacInd, nFacInd2)
+ if nFacet then
+ -- eseguo la svuotatura
+ return MakeByPocketing( Proc, nFacet, nRawId, b3Raw, true)
+ else
+ local sErr = 'Side milling not possible'
+ EgtOutLog( sErr)
+ return true, sErr
+
+ end
+ -- fessura verticale
+ elseif Proc.Stype == 3 then
+ -- riordino le facce come contorno libero da lavorare a destra (sono una U)
+ -- porto la faccia centrale in seconda posizione (indice 1)
+ local nFacInd = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+ if nFacInd ~= 1 then
+ EgtSurfTmSwapFacets( Proc.Id, 1, nFacInd)
+ end
+ -- verifico se la prima (indice 0) la deve precedere o seguire
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ local bAdj, ptAdj, _, _ = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
+ if bAdj and ( vtN ^ ( ptAdj - ptC)) * Z_AX() < 0 then
+ EgtSurfTmSwapFacets( Proc.Id, 0, 2)
+ end
+ -- applico lavorazione di contorno libero
+ return FreeContour.Make( Proc, nRawId, b3Raw)
+ -- tunnel
+ elseif Proc.Stype == 4 then
+ -- riordino le facce come contorno libero da lavorare a destra (formano un anello chiuso e quindi posso partire da una qualunque)
+ for i = 1, Proc.Fct - 2 do
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT)
+ for j = i + 1, Proc.Fct do
+ local bAdj, ptAdj, _, _ = EgtSurfTmFacetsContact( Proc.Id, i - 1, j - 1, GDB_ID.ROOT)
+ if bAdj and ( vtN ^ ( ptAdj - ptC)) * Z_AX() > 0 then
+ if i ~= j - 1 then
+ EgtSurfTmSwapFacets( Proc.Id, i, j - 1)
+ end
+ break
+ end
+ end
+ end
+ -- applico lavorazione di contorno libero
+ return FreeContour.Make( Proc, nRawId, b3Raw)
+ end
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPL.Make( Proc, nRawId, b3Raw)
+ -- in base al tipo di feature attribuisco il significato dei parametri Q
+ AssignQIdent( Proc)
+ if Proc.Fct == 1 then
+ return MakeOneFace( Proc, nRawId, b3Raw)
+ elseif Proc.Fct == 2 then
+ return MakeTwoFaces( Proc, nRawId, b3Raw)
+ else
+ return MakeMoreFaces( Proc, nRawId, b3Raw)
+ end
+end
+
+---------------------------------------------------------------------
+return WPL
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessMark.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessMark.lua
new file mode 100644
index 0000000..71af91f
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessMark.lua
@@ -0,0 +1,152 @@
+-- WProcessMark.lua by Egaltech s.r.l. 2021/04/20
+-- Gestione calcolo marcatura per Pareti
+
+-- Tabella per definizione modulo
+local WPMK = {}
+
+-- Include
+require( 'EgtBase')
+
+EgtOutLog( ' WProcessMark started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPMK.Identify( Proc)
+ return (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 60)
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPMK.Classify( Proc, b3Raw)
+ -- recupero il versore estrusione o normale se testo
+ local vtN
+ if EgtGetType( Proc.Id) ~= GDB_TY.EXT_TEXT then
+ vtN = EgtCurveExtrusion( Proc.Id, GDB_ID.ROOT)
+ else
+ vtN = EgtTextNormVersor( Proc.Id, GDB_ID.ROOT)
+ end
+ -- verifico sia una curva/testo
+ if not vtN then
+ return false
+ end
+ -- verifico se la marcatura è lavorabile (solo da sopra)
+ return ( vtN:getZ() > WD.NZ_MINA)
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPMK.FlipClassify( Proc)
+ local nFlip0, nFlip1
+ local vtN
+ if EgtGetType( Proc.Id) ~= GDB_TY.EXT_TEXT then
+ vtN = EgtCurveExtrusion( Proc.Id, GDB_ID.ROOT)
+ else
+ vtN = EgtTextNormVersor( Proc.Id, GDB_ID.ROOT)
+ end
+ -- verifico sia una curva/testo
+ if not vtN then
+ return false
+ end
+ -- verifico se la marcatura è lavorabile (solo da sopra)
+ nFlip0 = EgtIf( vtN:getZ() > WD.NZ_MINA, 100, 0)
+ nFlip1 = EgtIf( - vtN:getZ() > WD.NZ_MINA, 100, 0)
+ return nFlip0, nFlip1
+
+end
+
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPMK.Make( Proc, nRawId, b3Raw)
+ -- recupero eventuale geometria ausiliaria
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then AuxId = AuxId + Proc.Id end
+ -- recupero i dati della marcatura
+ local vtExtr
+ if EgtGetType( Proc.Id) ~= GDB_TY.EXT_TEXT then
+ vtExtr = EgtCurveExtrusion( Proc.Id, GDB_RT.GLOB)
+ else
+ vtExtr = EgtTextNormVersor( Proc.Id, GDB_ID.ROOT)
+ end
+ -- verifico sia una curva/testo
+ if not vtExtr then
+ local sErr = 'Error : Mark with geometry type not accepted'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- verifico che la marcatura non sia orientata verso il basso
+ if vtExtr:getZ() < WD.NZ_MINA then
+ local sErr = 'Error : Mark from bottom impossible'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero la lavorazione
+ local sMilling = WM.FindMilling( 'Text')
+ if not sMilling then
+ local sErr = 'Error : milling not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione di fresatura
+ local sName = 'Decor_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sMilling)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, -1}})
+ -- imposto posizione braccio porta testa
+ if vtExtr:getY() <= 0 then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ -- eventuale lavorazione su seconda geometria
+ if AuxId then
+ -- inserisco la lavorazione di fresatura
+ local sName2 = 'Decor2_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchF2Id = EgtAddMachining( sName, sMilling)
+ if not nMchF2Id then
+ local sErr = 'Error adding machining ' .. sName2 .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- imposto posizione braccio porta testa
+ if vtExtr:getY() <= 0 then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchF2Id, false)
+ return false, sErr
+ end
+ -- se geometria a X maggiore, la sposto prima
+ local ptS1 = EgtSP( Proc.Id, GDB_ID.ROOT)
+ local ptS2 = EgtSP( AuxId, GDB_ID.ROOT)
+ if ptS2:getX() > ptS1:getX() then
+ EgtRelocateGlob( nMchF2Id, nMchFId, GDB_IN.BEFORE)
+ end
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+return WPMK
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessMortise.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessMortise.lua
new file mode 100644
index 0000000..860e751
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessMortise.lua
@@ -0,0 +1,303 @@
+-- WProcessMortise.lua by Egaltech s.r.l. 2021/07/30
+-- Gestione calcolo mortase per Pareti
+
+-- Tabella per definizione modulo
+local WPM = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+
+EgtOutLog( ' WProcessMortise started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPM.Identify( Proc)
+ return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 50) or
+ (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 53))
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature: decide se la feature è in una posizione che per lavorala
+-- deve essere ribaltata o no
+function WPM.Classify( Proc, b3Raw)
+ -- recupero e verifico il percorso supplementare
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then AuxId = AuxId + Proc.Id end
+ -- recupero versore estrusione della curva supplementare e non più della superficie
+ -- perché quest'ultima potrebbe non avere il fondo e dare quindi un risultato non corretto
+ local vtExtr = EgtCurveExtrusion( AuxId or GDB_ID.NULL, GDB_ID.ROOT)
+ -- recupero i dati della faccia di fondo
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ -- verifico sia una superficie
+ if not vtExtr then
+ return false
+ end
+ if not vtN then
+ return false
+ end
+ -- Confronto le direzioni Z dei 2 versori : se diverse la faccia 0 non è il fondo => mortasa passante
+ if abs( vtExtr:getZ() - vtN:getZ()) > 10 * GEO.EPS_SMALL then
+ return true
+ -- altrimenti è chiusa
+ else
+ -- verifico se la mortasa è lavorabile da sopra
+ return ( vtN:getZ() > WD.NZ_MINA)
+ end
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPM.FlipClassify( Proc)
+ -- recupero e verifico il percorso supplementare
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then AuxId = AuxId + Proc.Id end
+ -- recupero versore estrusione della curva supplementare e non più della superficie
+ -- perché quest'ultima potrebbe non avere il fondo e dare quindi un risultato non corretto
+ local vtExtr = EgtCurveExtrusion( AuxId or GDB_ID.NULL, GDB_ID.ROOT)
+ -- recupero i dati della faccia di fondo
+ local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
+ -- verifico sia una superficie
+ if not vtExtr then
+ return false
+ end
+ if not vtN then
+ return false
+ end
+ -- Confronto le direzioni Z dei 2 versori : se diverse la faccia 0 non è il fondo => mortasa passante
+ if abs( vtExtr:getZ() - vtN:getZ()) > 10 * GEO.EPS_SMALL then
+ return 100, 100
+ -- altrimenti è chiusa
+ else
+ -- verifico se la mortasa è lavorabile da sopra
+ nFlip0 = EgtIf( vtN:getZ() > WD.NZ_MINA, 100, 0)
+ nFlip1 = EgtIf( - vtN:getZ() > WD.NZ_MINA, 100, 0)
+ end
+
+ return nFlip0, nFlip1
+
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPM.Make( Proc, nRawId, b3Raw)
+ -- recupero e verifico l'entità curva
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then AuxId = AuxId + Proc.Id end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing profile geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero versore estrusione della curva supplementare
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
+ -- recupero i dati della faccia di fondo
+ local frMor, dL, dW = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 0, GDB_ID.ROOT)
+ local ptC = ORIG()
+ local vtN = V_NULL()
+ if frMor then
+ ptC = frMor:getOrigin()
+ vtN = frMor:getVersZ()
+ end
+ -- verifico se è presente il fondo (sempre faccia 0)
+ local bClosedBtm = AreSameVectorApprox( vtExtr, vtN)
+ -- Se curva di contorno aperta
+ local dLenOpenSide = 0
+ if not EgtCurveIsClosed( AuxId) then
+ -- se c'è il fondo
+ if bClosedBtm then
+ local NewId, nCount = EgtExtractSurfTmFacetLoops( Proc.Id, 0, EgtGetParent( Proc.Id))
+ if NewId then
+ -- elimino eventuali loop interni (non dovrebbero comunque esserci)
+ for i = 1, nCount - 1 do
+ EgtErase( NewId + i)
+ end
+ -- sostituisco il loop esterno alla curva originale
+ EgtModifyCurveExtrusion( NewId, vtExtr, GDB_ID.ROOT)
+ EgtRelocate( NewId, AuxId, GDB_IN.AFTER)
+ EgtErase( AuxId)
+ EgtChangeId( NewId, AuxId)
+ -- sistemo i lati aperti
+ local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.Id, 0)[1]
+ if vFacAdj then
+ local sOpen = ''
+ for i = 1, #vFacAdj do
+ if vFacAdj[i] < 0 then
+ sOpen = sOpen .. EgtIf( #sOpen > 0, ',', '') .. tostring( i - 1)
+ local dLen = dist( EgtUP( AuxId, i-1), EgtUP( AuxId, i))
+ dLenOpenSide = max( dLen, dLenOpenSide)
+ end
+ end
+ if #sOpen > 0 then
+ EgtSetInfo( AuxId, 'OPEN', sOpen)
+ end
+ end
+ end
+ -- altrimenti aperta
+ else
+ dLenOpenSide = dist( EgtSP( AuxId), EgtEP( AuxId))
+ local _, nCrvCnt = EgtCurveDomain( AuxId)
+ EgtCloseCurveCompo( AuxId)
+ EgtSetInfo( AuxId, 'OPEN', nCrvCnt)
+ end
+ end
+ -- Se mortasa passante
+ if not bClosedBtm then
+ -- creo superficie chiusa
+ local nFlat = EgtSurfTmByFlatContour( EgtGetParent( AuxId), AuxId, 0.05)
+ if nFlat then
+ -- la superficie deve sempre essere rivolta verso l'alto
+ local vtNN = EgtSurfTmFacetNormVersor( nFlat, 0, GDB_ID.ROOT)
+ frMor, dL, dW = EgtSurfTmFacetMinAreaRectangle( nFlat, 0, GDB_ID.ROOT)
+ ptC = frMor:getOrigin()
+ vtN = frMor:getVersZ()
+ -- verifico se copiare la geometria lungo l'asse Z
+ local b3Aux = EgtGetBBoxRef( AuxId, GDB_BB.STANDARD, frMor)
+ local bxMax = b3Aux:getMax()
+ local b3Mor = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frMor)
+ local bxMin = b3Mor:getMin()
+ local dMove = bxMin:getZ() - bxMax:getZ()
+ if vtNN:getZ() < 0.1 then dMove = -dMove end
+ -- se il percorso ausiliario è esterno al grezzo, lo riavvicino
+ if abs( dMove) > GEO.EPS_SMALL then
+ AuxId = EgtCopyGlob( AuxId, WL.GetAddGroup( Proc.PartId))
+ EgtMove( AuxId, Vector3d( 0, 0, dMove), GDB_RT.GLOB)
+ EgtMove( nFlat, Vector3d( 0, 0, dMove), GDB_RT.GLOB)
+ frMor, dL, dW = EgtSurfTmFacetMinAreaRectangle( nFlat, 0, GDB_ID.ROOT)
+ ptC = frMor:getOrigin()
+ vtN = frMor:getVersZ()
+ end
+ -- cancello le prove del misfatto (superficie piana)
+ EgtErase( nFlat)
+ end
+ end
+ -- scrivo info nel log
+ EgtOutLog( 'ptC=' .. tostring( ptC) ..' vtN=' .. tostring( vtN), 3)
+ -- Se mortasa chiusa
+ local bForceOneSide
+ local bRevertSide
+ if bClosedBtm then
+ -- verifico che la mortasa non sia orientata verso il basso (limite -5 deg)
+ if vtN:getZ() < WD.NZ_MINA then
+ local sErr = 'Error : Mortise from bottom impossible'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- altrimenti passante
+ else
+ -- determino se la mortasa da lavorare sul lato opposto sia di angolo inferiore a quello consentito
+ if abs( vtN:getZ()) > 0.1 then
+ bForceOneSide = true
+ end
+ -- determino se è meglio lavorare la mortasa nel lato opposto
+ if vtN:getZ() < -GEO.EPS_SMALL then
+ bRevertSide = true
+ end
+ end
+
+ -- determino altezza della mortasa
+ local b3Mor = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frMor)
+ local dMorH = b3Mor:getDimZ()
+ -- elevazione del punto centro
+ local _, dCenElev = WL.GetPointDirDepth( Proc.PartId, ptC, vtN)
+ dMorH = max( dMorH, dCenElev or 0)
+ -- determino larghezza della mortasa
+ if dL < dW then dL, dW = dW, dL end
+ dW = max( dW, min( 2 * dW, dLenOpenSide))
+ -- recupero la lavorazione
+ local sPocketing
+ if Proc.Prc ~= 53 then
+ sPocketing = WM.FindPocketing( 'Mortise', dW)
+ end
+ if not sPocketing then
+ sPocketing = WM.FindPocketing( 'Pocket', dW)
+ end
+ if not sPocketing then
+ local sErr = 'Error : Mortise or Pocket not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero i dati dell'utensile
+ local dMillDiam = 20
+ local dMaxDepth = 0
+ local bCW = true
+ if EgtMdbSetCurrMachining( sPocketing) then
+ local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
+ if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
+ dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
+ dMaxDepth = ( EgtTdbGetCurrToolMaxDepth() or dMaxDepth)
+ local dSpeed = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) or 0
+ bCW = ( dSpeed >= 0)
+ end
+ end
+ -- inserisco la lavorazione di svuotatura
+ local sName = 'Mort_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sPocketing)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- verifico se invertire versore estrusione geometria
+ if bRevertSide then
+ EgtModifyCurveExtrusion( AuxId, -vtExtr, GDB_ID.ROOT)
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ AuxId, -1}})
+ -- sistemo la direzione di lavoro
+ EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bCW, true, false))
+ -- imposto posizione braccio porta testa
+ if vtN:getY() < GEO.EPS_SMALL then
+ if bRevertSide then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
+ end
+ else
+ if bRevertSide then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
+ end
+ end
+ local sWarn
+ local nDepthMin
+ -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente
+ if dMorH > dMaxDepth + 10 * GEO.EPS_SMALL then
+ sWarn = 'Warning in mortise : elevation (' .. EgtNumToString( dMorH,1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth,1) .. ')'
+ -- se non ho invertito la direzione di estrusione
+ if not bRevertSide then
+ nDepthMin = dMaxDepth - EgtIf( not bClosedBtm and not bForceOneSide, dMorH * 2, dMorH)
+ else
+ nDepthMin = dMaxDepth
+ end
+ EgtSetMachiningParam( MCH_MP.DEPTH, nDepthMin)
+ dMorH = dMaxDepth
+ EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')')
+ else
+ if not bClosedBtm and not bForceOneSide then -- se mortasa passante setto metà profondità
+ nDepthMin = -dMorH
+ EgtSetMachiningParam( MCH_MP.DEPTH, nDepthMin)
+ elseif bRevertSide then
+ EgtSetMachiningParam( MCH_MP.DEPTH, dMorH)
+ end
+ end
+ -- imposto elevazione
+ EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dMorH, 1) .. ';')
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+
+ return true, sWarn
+end
+
+---------------------------------------------------------------------
+return WPM
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessSawCut.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessSawCut.lua
new file mode 100644
index 0000000..5a9ede2
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessSawCut.lua
@@ -0,0 +1,58 @@
+-- WProcessSawCut.lua by Egaltech s.r.l. 2021/04/28
+-- Gestione calcolo taglio di lama per Pareti
+
+-- Tabella per definizione modulo
+local WPSC = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+local Cut = require( 'WProcessCut')
+
+EgtOutLog( ' WProcessSawCut started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPSC.Identify( Proc)
+ return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 13)
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPSC.Classify( Proc, b3Raw)
+ -- recupero i dati del versore direzione di accesso della lavorazione
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if not AuxId then return false end
+ AuxId = AuxId + Proc.Id
+ local vtDir = EgtSV( AuxId, GDB_ID.ROOT)
+ return ( vtDir:getZ() > 0.5)
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPSC.FlipClassify( Proc)
+ -- recupero i dati del versore direzione di accesso della lavorazione
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if not AuxId then return false end
+ AuxId = AuxId + Proc.Id
+ local vtDir = EgtSV( AuxId, GDB_ID.ROOT)
+ local vtDirZ = vtDir:getZ()
+ nFlip0 = EgtIf( vtDirZ > 0.5, 100, 0)
+ nFlip1 = EgtIf( - vtDirZ > 0.5, 100, 0)
+
+ return nFlip0, nFlip1
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPSC.Make( Proc, nRawId, b3Raw)
+ return Cut.Make( Proc, nRawId, b3Raw)
+end
+
+---------------------------------------------------------------------
+return WPSC
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessText.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessText.lua
new file mode 100644
index 0000000..a67651e
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessText.lua
@@ -0,0 +1,104 @@
+-- WProcessText.lua by Egaltech s.r.l. 2021/04/20
+-- Gestione calcolo testi per Travi
+
+-- Tabella per definizione modulo
+local WPT = {}
+
+-- Include
+require( 'EgtBase')
+
+EgtOutLog( ' WProcessText started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPT.Identify( Proc)
+ return ( Proc.Grp == 4 and Proc.Prc == 61)
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature
+function WPT.Classify( Proc, b3Raw)
+ -- recupero i dati del testo
+ local vtN = EgtTextNormVersor( Proc.Id, GDB_ID.ROOT)
+ -- verifico sia un testo
+ if not vtN then
+ return false
+ end
+ -- verifico se il testo è lavorabile (solo da sopra)
+ return ( vtN:getZ() > WD.NZ_MINA)
+end
+
+----------------------------------------------------------------------
+-- Classificazione del flip della feature per nesting
+-- return nFlip0, nFlip1
+function WPT.FlipClassify( Proc)
+ local nFlip0, nFlip1
+ -- recupero i dati del testo
+ local vtN = EgtTextNormVersor( Proc.Id, GDB_ID.ROOT)
+ -- verifico sia un testo
+ if not vtN then
+ return false
+ end
+ -- verifico se il testo è lavorabile (solo da sopra)
+ nFlip0 = EgtIf( vtN:getZ() > WD.NZ_MINA, 100, 0)
+ nFlip1 = EgtIf( - vtN:getZ() > WD.NZ_MINA, 100, 0)
+ return nFlip0, nFlip1
+
+end
+
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+function WPT.Make( Proc, nRawId, b3Raw)
+ -- recupero i dati del testo
+ local vtN = EgtTextNormVersor( Proc.Id, GDB_ID.ROOT)
+ -- verifico sia un testo
+ if not vtN then
+ local sErr = 'Error : Text with geometry type not accepted'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- verifico che il testo non sia orientato verso il basso
+ if vtN:getZ() < WD.NZ_MINA then
+ local sErr = 'Error : Text from bottom impossible'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- recupero la lavorazione
+ local sMilling = WM.FindMilling( 'Text')
+ if not sMilling then
+ local sErr = 'Error : milling not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione di fresatura
+ local sName = 'Text_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sMilling)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, -1}})
+ -- imposto posizione braccio porta testa
+ if vtN:getY() <= 0 then
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
+ else
+ EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
+ end
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+return WPT
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WProcessVariant.lua b/ProgettoRestylingWall/Wall/LuaLibs/WProcessVariant.lua
new file mode 100644
index 0000000..303be65
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WProcessVariant.lua
@@ -0,0 +1,115 @@
+-- WProcessVariant.lua by Egaltech s.r.l. 2021/08/27
+-- Gestione calcolo Feature Custom (Variant) per Pareti
+
+-- Tabella per definizione modulo
+local WPV = {}
+
+-- Include
+require( 'EgtBase')
+local WL = require( 'WallLib')
+
+EgtOutLog( ' WProcessVariant started', 1)
+
+-- Dati
+local WD = require( 'WallData')
+local WM = require( 'WMachiningLib')
+
+---------------------------------------------------------------------
+-- Riconoscimento della feature
+function WPV.Identify( Proc)
+ return (( Proc.Grp == 0 or Proc.Grp == 1 or Proc.Grp == 2 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 900)
+end
+
+---------------------------------------------------------------------
+-- Classificazione della feature: decide se la feature è in una posizione lavorabile
+local function ClassifyCode_1( Proc, b3Raw)
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then
+ AuxId = AuxId + Proc.Id
+ end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing containement geometry'
+ EgtOutLog( sErr)
+ return false
+ end
+ local vtExtr = EgtCurveExtrusion( AuxId or GDB_ID.NULL, GDB_ID.ROOT)
+ return ( vtExtr:getZ() > -0.01)
+end
+
+---------------------------------------------------------------------
+function WPV.Classify( Proc, b3Raw)
+ -- recupero il codice identificativo
+ local sCode = EgtGetInfo( Proc.Id, 'DES')
+ -- gestione in base al codice
+ if sCode == '1' then
+ return ClassifyCode_1( Proc, b3Raw)
+ else
+ return false
+ end
+end
+
+---------------------------------------------------------------------
+-- Applicazione della lavorazione
+local function MakeCode_1( Proc, nRawId, b3Raw)
+ -- recupero e verifico l'entità curva associata
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
+ if AuxId then
+ AuxId = AuxId + Proc.Id
+ end
+ if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then
+ local sErr = 'Error : missing containement geometry'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ local vtExtr = EgtCurveExtrusion( AuxId or GDB_ID.NULL, GDB_ID.ROOT)
+ -- recupero la lavorazione
+ local sSurfFin = WM.FindSurfacing( 'Finishing')
+ if not sSurfFin then
+ local sErr = 'Error : surface finishing not found in library'
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ -- inserisco la lavorazione di finitura superficie
+ local sName = 'SurfFin_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
+ local nMchFId = EgtAddMachining( sName, sSurfFin)
+ if not nMchFId then
+ local sErr = 'Error adding machining ' .. sName .. '-' .. sSurfFin
+ EgtOutLog( sErr)
+ return false, sErr
+ end
+ EgtSetInfo( nMchFId, 'Part', Proc.PartId)
+ -- se lavorazione di fianco setto la nota per spostarla dopo i tagli di lama
+ if vtExtr:getZ() < WD.NZ_MINA then
+ EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
+ end
+ -- aggiungo geometria
+ EgtSetMachiningGeometry( {{ Proc.Id, -1},{AuxId, -1}})
+ -- imposto posizione braccio porta testa
+ local nSCC = MCH_SCC.ADIR_ZP
+ if AreSameVectorApprox( vtExtr, Z_AX()) then
+ nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP)
+ end
+ EgtSetMachiningParam( MCH_MP.SCC, nSCC)
+ -- eseguo
+ if not EgtApplyMachining( true, false) then
+ local _, sErr = EgtGetLastMachMgrError()
+ EgtSetOperationMode( nMchFId, false)
+ return false, sErr
+ end
+ return true
+end
+
+---------------------------------------------------------------------
+function WPV.Make( Proc, nRawId, b3Raw)
+ -- recupero il codice identificativo
+ local sCode = EgtGetInfo( Proc.Id, 'DES')
+ -- gestione in base al codice
+ if sCode == '1' then
+ return MakeCode_1( Proc, nRawId, b3Raw)
+ else
+ return false, 'Feature Id Code non recognized for machining'
+ end
+end
+
+---------------------------------------------------------------------
+return WPV
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WallExec.lua b/ProgettoRestylingWall/Wall/LuaLibs/WallExec.lua
new file mode 100644
index 0000000..06b51ed
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WallExec.lua
@@ -0,0 +1,691 @@
+-- WallExec.lua by Egaltech s.r.l. 2022/03/15
+-- Libreria esecuzione lavorazioni per Pareti
+
+-- Tabella per definizione modulo
+local WallExec = {}
+
+-- Include
+require( 'EgtBase')
+
+-- Carico i dati globali e libero tutti gli altri
+_G.package.loaded.WallData = 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 WD = require( 'WallData')
+if WALL and WALL.NESTINGCORNERBL then WD.NESTING_CORNER = 'BL' end
+
+-- Carico le librerie
+_G.package.loaded.WMachiningLib = nil
+_G.package.loaded.WallLib = nil
+_G.package.loaded.WProcessCut = nil
+_G.package.loaded.WProcessDoubleCut = nil
+_G.package.loaded.WProcessSawCut = nil
+_G.package.loaded.WProcessLapJoint = nil
+_G.package.loaded.WProcessDrill = nil
+_G.package.loaded.WProcessMortise = nil
+_G.package.loaded.WProcessDtMortise = nil
+_G.package.loaded.WProcessMark = nil
+_G.package.loaded.WProcessText = nil
+_G.package.loaded.WProcessFreeContour = nil
+_G.package.loaded.WProcessVariant = nil
+local WM = require( 'WMachiningLib')
+local WL = require( 'WallLib')
+local Cut = require( 'WProcessCut')
+local DoubleCut = require( 'WProcessDoubleCut')
+local SawCut = require( 'WProcessSawCut')
+local LapJoint = require( 'WProcessLapJoint')
+local Drill = require( 'WProcessDrill')
+local Mortise = require( 'WProcessMortise')
+local DtMortise = require( 'WProcessDtMortise')
+local Mark = require( 'WProcessMark')
+local Text = require( 'WProcessText')
+local FreeContour = require( 'WProcessFreeContour')
+local Variant = require( 'WProcessVariant')
+
+
+-------------------------------------------------------------------------------------------------------------
+-- *** Inserimento delle pareti nel pannello ***
+-------------------------------------------------------------------------------------------------------------
+function WallExec.ProcessWalls( dRawL, dRawW, dRawH, vWall, bMachGroupOk, bNewProcess, nRawOutlineId)
+
+ -- Creazione nuovo gruppo di lavoro
+ if not bMachGroupOk then
+ local sMgName = EgtGetMachGroupNewName( 'Mach')
+ 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 di riferimento della tavola rispetto a sua origine in BL
+ local OrigOnTab
+ local nCorner
+ local sOrigCorner = WD.ORIG_CORNER or 'BR'
+ if WD.GetOrigCorner then
+ sOrigCorner = WD.GetOrigCorner( EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL, 'REFPOS', 'i') or 1)
+ end
+ if sOrigCorner == 'TL' then
+ nCorner = MCH_CR.TL
+ OrigOnTab = Point3d( 0, b3Tab:getDimY(), 0)
+ elseif sOrigCorner == 'BL' then
+ nCorner = MCH_CR.BL
+ OrigOnTab = Point3d( 0, 0, 0)
+ elseif sOrigCorner == 'TR' then
+ nCorner = MCH_CR.TR
+ OrigOnTab = Point3d( b3Tab:getDimX(), b3Tab:getDimY(), 0)
+ elseif sOrigCorner == 'BR' then
+ nCorner = MCH_CR.BR
+ OrigOnTab = Point3d( b3Tab:getDimX(), 0, 0)
+ elseif sOrigCorner == 'TM' then
+ nCorner = MCH_CR.TR
+ OrigOnTab = Point3d( WD.MID_REF, b3Tab:getDimY(), 0)
+ elseif sOrigCorner == 'BM' then
+ nCorner = MCH_CR.BR
+ OrigOnTab = Point3d( WD.MID_REF, 0, 0)
+ end
+ -- Impostazione dell'attrezzaggio di default
+ EgtImportSetup()
+ -- Creazione del grezzo e suo posizionamento in macchina
+ local nRaw = GDB_ID.NULL
+ if nRawOutlineId and nRawOutlineId ~= GDB_ID.NULL then
+ nRaw = EgtAddRawPartWithPart( 0, nRawOutlineId, 0, WD.RAWCOL)
+ else
+ nRaw = EgtAddRawPart( Point3d(0,0,0), dRawL, dRawW, dRawH, WD.RAWCOL)
+ end
+ EgtMoveToCornerRawPart( nRaw, OrigOnTab, nCorner)
+ EgtSetInfo( nRaw, 'ORD', 1)
+ -- Inserimento dei pezzi nel grezzo
+ for i = 1, #vWall do
+ -- assegno identificativo pezzo
+ local Pz = vWall[i].Id
+ -- dati del pezzo
+ local b3Part = EgtGetBBoxGlob( Pz or GDB_ID.NULL, GDB_BB.EXACT)
+ local b3Solid = vWall[i].Box
+ if b3Part:isEmpty() or b3Solid:isEmpty() then break end
+ local PartLen = b3Solid:getDimX()
+ local PartWidth = b3Solid:getDimY()
+ local PartHeight = b3Solid:getDimZ()
+ local vtOffs = b3Part:getMin() - b3Solid:getMin()
+ -- creo o pulisco gruppo geometrie aggiuntive
+ if not WL.CreateOrEmptyAddGroup( Pz) then
+ local sOut = 'Error creating Additional Group in Part ' .. tostring( Pz)
+ return false, sOut
+ end
+ -- inserisco il pezzo nel grezzo
+ EgtDeselectPartObjs( Pz)
+ local ptPos
+ if bNewProcess then
+ local sNestingRef = ( WALL.NESTING_REF or WD.NESTING_CORNER)
+ if sNestingRef == 'TL' then
+ ptPos = Point3d( vWall[i].PosX, dRawW - PartWidth - vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs
+ elseif sNestingRef == 'TR' then
+ ptPos = Point3d( dRawL - PartLen - vWall[i].PosX, dRawW - PartWidth - vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs
+ elseif sNestingRef == 'BR' then
+ ptPos = Point3d( dRawL - PartLen - vWall[i].PosX, vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs
+ else -- 'BL'
+ ptPos = Point3d( vWall[i].PosX, vWall[i].PosZ, ( dRawH - PartHeight) / 2) + vtOffs
+ end
+ else
+ local dPosH = EgtIf( vWall[i].PosY < 0.1, ( dRawH - PartHeight) / 2, vWall[i].PosY)
+ ptPos = Point3d( dRawL - vWall[i].PosX - PartLen, vWall[i].PosZ, dPosH) + vtOffs
+ end
+ EgtAddPartToRawPart( Pz, ptPos, nRaw)
+ end
+ return true
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- *** Inserimento delle lavorazioni nelle pareti ***
+-------------------------------------------------------------------------------------------------------------
+function WallExec.CollectFeatures( PartId, b3Raw)
+ -- recupero le feature
+ local vProc = {}
+ local LayerId = {}
+ LayerId[1] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Outline')
+ LayerId[2] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Processings')
+ for nInd = 1, #LayerId 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.PartId = PartId
+ Proc.Id = ProcId
+ Proc.Grp = nGrp
+ Proc.Prc = nPrc
+ Proc.Flg = 1
+ Proc.Fct = EgtSurfTmFacetCount( ProcId) or 0
+ Proc.Diam = 0
+ Proc.Fcs = 0
+ Proc.Fce = 0
+ Proc.CutId = nCutId
+ Proc.TaskId = nTaskId
+ Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD)
+ if Proc.Box and not Proc.Box:isEmpty() then
+ 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
+ -- definisco dati seconda parte
+ local Proc2 = {}
+ Proc2.PartId = PartId
+ Proc2.Id = ProcId
+ Proc2.Grp = nGrp
+ Proc2.Prc = nPrc
+ Proc2.Flg = -2
+ Proc2.Box = BBox3d( Proc.Box)
+ Proc2.Fct = Proc.Fct
+ Proc2.Diam = Proc.Diam
+ Proc2.Fcs = Proc.Fce
+ Proc2.Fce = Proc.Fcs
+ Proc2.CutId = Proc.CutId
+ Proc2.TaskId = Proc.TaskId
+ table.insert( vProc, Proc2)
+ end
+ end
+ else
+ EgtOutLog( ' Feature ' .. tostring( Proc.Id) .. ' is empty (no geometry)')
+ end
+ end
+ end
+ ProcId = EgtGetNext( ProcId)
+ end
+ end
+ return vProc
+end
+
+-------------------------------------------------------------------------------------------------------------
+local function ClassifyFeatures( vProc, b3Raw)
+ for i = 1, #vProc do
+ local Proc = vProc[i]
+ -- se taglio
+ if Cut.Identify( Proc) then
+ local bOk = Cut.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se taglio doppio
+ elseif DoubleCut.Identify( Proc) then
+ local bOk = DoubleCut.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se taglio con lama
+ elseif SawCut.Identify( Proc) then
+ local bOk = SawCut.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se tasca
+ elseif LapJoint.Identify( Proc) then
+ local bOk = LapJoint.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se foratura
+ elseif Drill.Identify( Proc) then
+ local bOk = Drill.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se mortasatura
+ elseif Mortise.Identify( Proc) then
+ local bOk = Mortise.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se mortasatura a coda di rondine
+ elseif DtMortise.Identify( Proc) then
+ local bOk = DtMortise.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se marcatura
+ elseif Mark.Identify( Proc) then
+ local bOk = Mark.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se testo
+ elseif Text.Identify( Proc) then
+ local bOk = Text.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se contorno libero, outile o aperture
+ elseif FreeContour.Identify( Proc) then
+ local bOk = FreeContour.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ -- se feature custom (Variant)
+ elseif Variant.Identify( Proc) then
+ local bOk = Variant.Classify( Proc, b3Raw)
+ if not bOk then Proc.Flg = 0 end
+ end
+ end
+end
+
+-------------------------------------------------------------------------------------------------------------
+local function PrintFeatures( vProc)
+ EgtOutLog( ' *** Feature List ***')
+ for i = 1, #vProc do
+ local Proc = vProc[i]
+ local sOut = string.format( 'Part=%3d Proc=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Fcse=%1d,%1d Diam=%.2f Fct=%2d Dbl=%2d Dlt=%.1f Box=%s',
+ Proc.PartId, Proc.Id, Proc.Grp, Proc.Prc, Proc.TaskId, Proc.CutId,
+ Proc.Flg, Proc.Fcs, Proc.Fce, Proc.Diam, Proc.Fct, Proc.Double or 0, Proc.Delta or 0, tostring( Proc.Box))
+ EgtOutLog( sOut)
+ end
+end
+
+-------------------------------------------------------------------------------------------------------------
+local function AddFeatureMachining( Proc, nRawId, b3Raw)
+ local bOk = true
+ local sErr = ''
+ EgtOutLog( ' * Process ' .. tostring( Proc.Id) .. ' *', 1)
+ -- se taglio (1/2-010-X) o taglio longitudinale (0/3/4-010-X)
+ if Cut.Identify( Proc) then
+ -- esecuzione taglio
+ bOk, sErr = Cut.Make( Proc, nRawId, b3Raw)
+ -- se taglio doppio (1/2-011-X) o taglio doppio longitudinale (0-012-X)
+ elseif DoubleCut.Identify( Proc) then
+ -- esecuzione taglio
+ bOk, sErr = DoubleCut.Make( Proc, nRawId, b3Raw)
+ -- se taglio con lama (0/3/4-013-X)
+ elseif SawCut.Identify( Proc) then
+ -- esecuzione taglio
+ bOk, sErr = SawCut.Make( Proc, nRawId, b3Raw)
+ -- se tasca (3/4-030-X) o similari
+ elseif LapJoint.Identify( Proc) then
+ -- esecuzione tasca
+ bOk, sErr = LapJoint.Make( Proc, nRawId, b3Raw)
+ -- se foratura ( 3/4-040-X)
+ elseif Drill.Identify( Proc) then
+ -- esecuzione foratura
+ bOk, sErr = Drill.Make( Proc, nRawId, b3Raw)
+ -- se mortasatura (3/4-050-X) o similari
+ elseif Mortise.Identify( Proc) then
+ -- esecuzione mortasatura
+ bOk, sErr = Mortise.Make( Proc, nRawId, b3Raw)
+ -- se mortasatura a coda di rondine (3/4-055-X)
+ elseif DtMortise.Identify( Proc) then
+ -- esecuzione mortasatura a coda di rondine
+ bOk, sErr = DtMortise.Make( Proc, nRawId, b3Raw)
+ -- se marcatura (3/4-060-X)
+ elseif Mark.Identify( Proc) then
+ -- esecuzione marcatura
+ bOk, sErr = Mark.Make( Proc, nRawId, b3Raw)
+ -- se testo (4-061-X)
+ elseif Text.Identify( Proc) then
+ -- esecuzione incisione testo
+ bOk, sErr = Text.Make( Proc, nRawId, b3Raw)
+ -- se contorno libero, outline o apertura ( 0/3/4-250/251/252-X)
+ elseif FreeContour.Identify( Proc) then
+ -- esecuzione contorno
+ bOk, sErr = FreeContour.Make( Proc, nRawId, b3Raw)
+ -- se feature custom (Variant)
+ elseif Variant.Identify( Proc) then
+ -- esecuzione
+ bOk, sErr = Variant.Make( Proc, nRawId, b3Raw)
+ -- altrimenti feature non riconosciuta
+ else
+ bOk = false
+ sErr = 'Feature type non recognized for machining'
+ end
+ return bOk, sErr
+end
+
+-------------------------------------------------------------------------------------------------------------
+local function MoveMachiningsAtEnd( nPhase, nType, sStartName, sProperty)
+ local nOperId = EgtGetPhaseDisposition( nPhase)
+ local nLastId = EgtGetLastOperation()
+ local nInsertId = nLastId
+ while nOperId do
+ local nNextOperId = EgtGetNextOperation( nOperId)
+ if EgtGetOperationPhase( nOperId) == nPhase and EgtGetOperationType( nOperId) == nType and
+ ( ( EgtGetInfo( nOperId, 'MOVE_AFTER', 'i') == 1 ) or
+ ( not sStartName or string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName)) then
+ EgtRelocateGlob( nOperId, nInsertId, GDB_IN.AFTER)
+ nInsertId = nOperId
+ end
+ if nOperId == nLastId then
+ break
+ end
+ nOperId = nNextOperId
+ end
+end
+
+------ Ordinamento dei tagli, delle fresature e delle forature -------
+local function SpSorting( TabCut, PrevMch, nType, bOneWay)
+
+ -- ordino le lavorazioni (in gruppi di max 1000 entità se 32bit 10000 se 64bit)
+ --EgtOutLog('Dati per ShortestPath :')
+ local SP_MAX_ENT = EgtIf( EgtIs64bit(), 10000, 1000)
+ local nBase = 0
+ while nBase < #TabCut do
+ -- calcolo ordinamento
+ EgtSpInit()
+ for i = 1, min( #TabCut - nBase, SP_MAX_ENT) do
+ local ptS = TabCut[nBase+i].Start
+ local ptE = TabCut[nBase+i].End
+ EgtSpAddPoint( ptS:getX(), ptS:getY(), ptS:getZ(), 0, 0,
+ ptE:getX(), ptE:getY(), ptE:getZ(), 0, 0)
+ end
+ EgtSpSetAngularParams( 1000, 40, 2000, 60)
+ EgtSpSetOpenBound( true, SHP_OB.NEAR_PNT, 50000, 0, 0, 0, 0)
+ if WD.BEAM_MACHINE and (nType & MCH_OY.SAWING) == MCH_OY.SAWING then
+ EgtSpSetOpenBound( false, SHP_OB.NEAR_PNT, -50000, 0, 0, 0, 0)
+ end
+ EgtSpSetZzOwStep( 10)
+ local nType = EgtIf( bOneWay, SHP_TY.ONEWAY_YM, SHP_TY.OPEN)
+ local vOrd = EgtSpCalculate( nType)
+ EgtSpTerminate()
+ -- applico ordinamento calcolato
+ if vOrd then
+ for i = 1, #vOrd do
+ EgtRelocateGlob( TabCut[nBase+vOrd[i]].Mch, PrevMch, GDB_IN.AFTER)
+ PrevMch = TabCut[nBase+vOrd[i]].Mch
+ end
+ end
+ -- incremento la base
+ nBase = nBase + SP_MAX_ENT
+ end
+
+ return PrevMch
+end
+
+local function ContainsStartName( nOperId, StartNames)
+ local bFound = false
+ for i = 1, #StartNames do
+ local sStartName = StartNames[i]
+ if string.sub( EgtGetName( nOperId), 1, #sStartName) == sStartName then
+ bFound = true
+ end
+ end
+ return bFound
+end
+
+------ Ordinamento dei tagli, delle fresature e delle forature -------
+local function SortMach( nPhase, PrevMch, nPartId, nType, StartNames, bExistName, sInfo, bExistInfo, bOneWay, bByTool, bByToolAngle)
+ -- dichiarazione tabella
+ local TabCut = {}
+ -- Recupero gli identificativi delle lavorazioni e annullo eventuali allungamenti e Id di altre lavorazioni rappresentate
+ local nOperId = EgtGetNextOperation( PrevMch)
+ while nOperId do
+ local nOperType = EgtGetOperationType( nOperId)
+ -- Se appartiene alla fase corrente e taglio con lama non da sopra (sempre su 1 sola entità)
+ if EgtGetOperationPhase( nOperId) == nPhase and ( nType & nOperType) == nOperType and
+ ( not nPartId or EgtGetInfo( nOperId, 'Part', 'i') == nPartId) and
+ ( not StartNames or ( bExistName and ContainsStartName( nOperId, StartNames)) or
+ ( not bExistName and not ContainsStartName( nOperId, StartNames))) and
+ ( not sInfo or ( bExistInfo and EgtGetInfo( nOperId, sInfo, 'i') == 1) or
+ ( not bExistInfo and EgtGetInfo( nOperId, sInfo, 'i') ~= 1)) then
+ -- non si deve cambiare lo stato di attivazione della lavorazione (se disabilitata errata)
+ EgtSetCurrMachining( nOperId)
+ if not EgtIsMachiningEmpty() then
+ -- punto iniziale e finale e direzione della lavorazione
+ local ptStart = EgtGetMachiningStartPoint()
+ local ptEnd = EgtGetMachiningEndPoint()
+ local sTUUID = ''
+ local nToolType = 0
+ local nToolDiam = 0
+ local nToolDir = 0
+ if bByTool then
+ sTUUID = EgtGetMachiningParam( MCH_MP.TUUID)
+ local sToolName = EgtTdbGetToolFromUUID( sTUUID)
+ if EgtTdbSetCurrTool( sToolName) then
+ nToolType = EgtTdbGetCurrToolParam( MCH_TP.TYPE)
+ nToolDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM)
+ else
+ sTUUID = ''
+ end
+ end
+ if bByToolAngle then
+ local nClId = EgtGetFirstNameInGroup( nOperId, 'CL')
+ local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL)
+ local vtTool = EgtGetInfo( nPathId, 'EXTR', 'v')
+ nToolDir = EgtIf( vtTool:getZ() > 0.999999, 1, 0)
+ end
+ table.insert( TabCut, {Mch=nOperId, Ent=nEntId, Start=ptStart, End=ptEnd, Tool=sTUUID, ToolType=nToolType, ToolDiam=nToolDiam, ToolDir=nToolDir})
+ end
+ end
+ -- Passo alla operazione successiva
+ nOperId = EgtGetNextOperation( nOperId)
+ end
+
+ if bByTool then
+ function ToolCompare(a,b)
+ if a.ToolType < b.ToolType then
+ return true
+ elseif a.ToolType == b.ToolType then
+ if a.ToolDiam > b.ToolDiam then
+ return true
+ elseif a.ToolDiam == b.ToolDiam then
+ if a.Tool < b.Tool then
+ return true
+ elseif a.Tool == b.Tool then
+ if bByToolAngle then
+ if a.ToolDir > b.ToolDir then
+ return true
+ elseif a.ToolDir == b.ToolDir then
+ return a.Mch < b.Mch
+ end
+ else
+ return a.Mch < b.Mch
+ end
+ end
+ end
+ end
+ return false
+ end
+ -- test della funzione di ordinamento
+ if EgtGetDebugLevel() >= 3 then
+ EgtOutLog( ' CompareFeatures Test ')
+ local bCompTest = true
+ for i = 1, #TabCut do
+ for j = i + 1, #TabCut do
+ local bComp1 = ToolCompare( TabCut[i], TabCut[j])
+ local bComp2 = ToolCompare( TabCut[j], TabCut[i])
+ if bComp1 == bComp2 then
+ bCompTest = false
+ EgtOutLog( string.format( ' ProcId : %d vs %d --> ERROR', TabCut[i].Mch, TabCut[j].Mch))
+ end
+ end
+ end
+ if bCompTest then
+ EgtOutLog( ' ALL OK')
+ end
+ end
+
+ table.sort(TabCut, ToolCompare)
+-- table.sort(TabCut, function(a,b) return a.ToolType < b.ToolType and a.ToolDiam > b.ToolDiam and a.Tool < b.Tool end)
+ local SupportTabCut = {}
+ local nPrevTUUID = 0
+ local nPrevTDirZ = 1
+ for i = 1, #TabCut do
+ -- se tuuid uguale al precedente, lo aggiungo alla lista
+ if nPrevTUUID == TabCut[i].Tool and ( not bByToolAngle or nPrevTDirZ == TabCut[i].ToolDir) then
+ table.insert( SupportTabCut, TabCut[i])
+ -- se tuuid diverso,
+ else
+ -- faccio calcolare la lista
+ PrevMch = SpSorting( SupportTabCut, PrevMch, nType, bOneWay)
+ -- cancello la lista e aggiorno tuuid corrente
+ SupportTabCut = {}
+ nPrevTUUID = TabCut[i].Tool
+ if bByToolAngle then
+ nPrevTDirZ = TabCut[i].ToolDir
+ end
+ table.insert( SupportTabCut, TabCut[i])
+ end
+ end
+ -- calcolo ultima lista
+ if #SupportTabCut > 0 then
+ PrevMch = SpSorting( SupportTabCut, PrevMch, nType, bOneWay)
+ end
+ else
+ PrevMch = SpSorting( TabCut, PrevMch, nType, bOneWay)
+ end
+
+ return PrevMch
+
+end
+
+-------------------------------------------------------------------------------------------------------------
+local function SortMachinings( nPhase, PrevMch, nPartId)
+ -- Chiodature
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Nail_'}, true)
+ -- Tagli con sega a catena che sono rifiniture di spigoli
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MORTISING, { 'Csaw_'}, false)
+ -- Forature orizzontali con punte lunghe
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING, { 'LhDrill_'}, true, 'MOVE_AFTER', false, true)
+ -- Preforature per fori inclinati
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.POCKETING, { 'PreDrill_'}, true)
+ -- Forature e Svuotature
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING + MCH_OY.POCKETING + MCH_OY.MILLING, { 'SideMill_', 'Clean_'}, false, 'MOVE_AFTER', false, false, true)
+-- -- Forature ***
+-- PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING, nil, nil, 'MOVE_AFTER', false)
+-- -- Svuotature ***
+-- PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.POCKETING, nil, nil, 'MOVE_AFTER', false)
+-- -- Fresature che sono rifiniture di spigoli
+-- PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Clean_'}, false, 'MOVE_AFTER', false, false, true)
+ -- Lavorazioni di superficie
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFFINISHING, nil, nil, 'MOVE_AFTER', false)
+ -- Fresature per gole
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Gorge_'}, true, 'MOVE_AFTER', false)
+ -- Fresature che sono rifiniture di spigoli
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'SideMill_'}, true, 'MOVE_AFTER', false, false, true, true)
+ -- Fresature che sono puliture di spigoli
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'Clean_'}, true, 'MOVE_AFTER', false)
+ -- Tagli per gole
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.SAWING, { 'GorgeCut_'}, true)
+ -- Tagli con lama
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.SAWING)
+ -- Qui rimozione sfridi (se ci sono lavorazioni successive)
+ -- Fresature dei lapjoint che necessitano di gorge
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, { 'SideMill_'}, true, 'MOVE_AFTER', true, false, true, true)
+ -- Tagli con sega a catena che vanno fatti dopo i tagli con lama
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MORTISING, { 'Csaw_'}, true)
+ -- Fresature (puliture di spigoli) che vanno fatte dopo i tagli con lama
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.MILLING, nil, nil, 'MOVE_AFTER', true)
+ -- Forature che vanno fatte dopo i tagli con lama
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.DRILLING, nil, nil, 'MOVE_AFTER', true)
+ -- Svuotature che vanno fatte dopo i tagli con lama
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_OY.POCKETING, nil, nil, 'MOVE_AFTER', true)
+ -- Lavorazioni di superficie che vanno fatte dopo i tagli con lama
+ PrevMch = SortMach( nPhase, PrevMch, nPartId, MCH_MY.SURFFINISHING, nil, nil, 'MOVE_AFTER', true)
+ return PrevMch
+end
+
+-------------------------------------------------------------------------------------------------------------
+function WallExec.ProcessFeatures()
+ -- errori e stato
+ local nTotErr = 0
+ local Stats = {}
+ -- recupero il grezzo e il suo box
+ local nRawId = EgtGetFirstRawPart()
+ local b3Raw = EgtGetRawPartBBox( nRawId)
+ -- raccolgo l'elenco dei pezzi
+ local vPart = {}
+ local nPartId = EgtGetFirstPartInRawPart( nRawId)
+ while nPartId do
+ local Ls = EgtGetFirstNameInGroup( nPartId, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ table.insert( vPart, {Id=nPartId, Box=b3Solid})
+ nPartId = EgtGetNextPartInRawPart( nPartId)
+ end
+ -- raccolgo l'elenco delle feature da lavorare, ciclando sui pezzi
+ local vProc = {}
+ for i = 1, #vPart do
+ -- recupero le feature di lavorazione della parete
+ local vPartProc = WallExec.CollectFeatures( vPart[i].Id, b3Raw)
+ vProc = EgtJoinTables( vProc, vPartProc)
+ end
+ -- classifico le feature
+ ClassifyFeatures( vProc, b3Raw)
+ -- Eventuale determinazione delle feature lavorabili in parallelo (implementata nella configurazione macchina)
+ -- si impostano i flag Double (nil/0=no, 1=su X, 2=su Y) e Delta (offset tra T14 e T12 positivo o negativo)
+ if WD.FindFeaturesInDouble then
+ WD.FindFeaturesInDouble( vProc, b3Raw)
+ end
+ -- debug
+ if EgtGetDebugLevel() >= 1 then
+ PrintFeatures( vProc)
+ end
+ EgtOutLog( ' *** AddMachinings ***', 1)
+ -- inserisco le lavorazioni
+ for i = 1, #vProc do
+ -- creo la lavorazione
+ local Proc = vProc[i]
+ if Proc.Flg ~= 0 then
+ local bOk, sMsg = AddFeatureMachining( Proc, nRawId, 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
+ elseif not Proc.Double then
+ local sMsg = 'Feature not machinable by orientation'
+ table.insert( Stats, {Err=1, Msg=sMsg, Rot=0, CutId=Proc.CutId, TaskId=Proc.TaskId})
+ end
+ end
+ EgtOutLog( ' *** End AddMachinings ***', 1)
+ -- se macchina pareti
+ if not WD.BEAM_MACHINE then
+ -- riordino le lavorazioni tra tutti i pezzi
+ local nPhase = 1
+ local PrevMch = EgtGetPhaseDisposition( nPhase)
+ SortMachinings( nPhase, PrevMch)
+ -- Aggiornamento finale di tutto
+ EgtSetCurrPhase( 1)
+ EgtApplyAllMachinings()
+ -- altrimenti macchina travi
+ else
+ -- dichiaro lavorazione pareti
+ EgtSetInfo( EgtGetCurrMachGroup() or GDB_ID.NULL, 'Wall', '1')
+ -- ordino i pezzi secondo le X decrescenti
+ local function CompareParts( P1, P2)
+ return P1.Box:getCenter():getX() > P2.Box:getCenter():getX()
+ end
+ table.sort( vPart, CompareParts)
+ -- riordino le lavorazioni sui singoli pezzi
+ local nPhase = 1
+ local PrevMch = EgtGetPhaseDisposition( nPhase)
+ for i = 1, #vPart do
+ PrevMch = SortMachinings( nPhase, PrevMch, vPart[i].Id)
+ end
+ -- aggiungo dati su prima disposizione
+ local nDispId = EgtGetPhaseDisposition( 1)
+ EgtSetInfo( nDispId, 'TYPE', 'START')
+ EgtSetInfo( nDispId, 'ORD', 1)
+ -- aggiungo flag su ultima lavorazione
+ local nLastMchId = EgtGetLastActiveOperation()
+ EgtSetCurrMachining( nLastMchId)
+ EgtSetMachiningParam( MCH_MP.USERNOTES, 'Cut;')
+ -- aggiungo disposizione per lo scarico
+ EgtAddPhase()
+ local nRawId = EgtGetFirstRawPart()
+ EgtKeepRawPart( nRawId, 1)
+ local nDisp2Id = EgtGetPhaseDisposition( 2)
+ EgtSetInfo( nDisp2Id, 'TYPE', 'END')
+ EgtSetInfo( nDisp2Id, 'ORD', 1)
+ -- Aggiornamento finale di tutto
+ EgtSetCurrPhase( 1)
+ local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings()
+ 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
+ -- non interessano perchè riguardano lo scarico delle travi
+ end
+ end
+ -- restituzione risultati
+ return ( nTotErr == 0), Stats
+end
+
+-------------------------------------------------------------------------------------------------------------
+return WallExec
diff --git a/ProgettoRestylingWall/Wall/LuaLibs/WallLib.lua b/ProgettoRestylingWall/Wall/LuaLibs/WallLib.lua
new file mode 100644
index 0000000..058143d
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/LuaLibs/WallLib.lua
@@ -0,0 +1,317 @@
+-- WallLib.lua by Egaltech s.r.l. 2020/11/18
+-- Libreria globale per Pareti
+
+-- Tabella per definizione modulo
+local WallLib = {}
+
+-- Include
+require( 'EgtBase')
+
+EgtOutLog( ' WallLib started', 1)
+
+-------------------------------------------------------------------------------------------------------------
+function WallLib.GetAddGroup( PartId)
+ -- recupero il nome del gruppo di lavoro corrente
+ local sMchGrp = EgtGetMachGroupName( EgtGetCurrMachGroup() or GDB_ID.NULL)
+ if not sMchGrp then return nil, nil end
+ -- cerco il gruppo aggiuntivo omonimo nel pezzo e se esiste lo restituisco
+ local AddGrpId = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, sMchGrp)
+ -- restituisco Id e Nome
+ return AddGrpId, sMchGrp
+end
+
+-------------------------------------------------------------------------------------------------------------
+function WallLib.CreateOrEmptyAddGroup( PartId)
+ -- recupero i dati del gruppo aggiuntivo
+ local AddGrpId, sMchGrp = WallLib.GetAddGroup( PartId)
+ if not sMchGrp then return false end
+ -- se esiste lo svuoto
+ if AddGrpId then
+ return EgtEmptyGroup( AddGrpId)
+ end
+ -- altrimenti lo creo
+ AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
+ if not AddGrpId then return false end
+ -- assegno nome, flag di layer per gruppo di lavoro e colore
+ EgtSetName( AddGrpId, sMchGrp)
+ EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
+ EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 50))
+ return true
+end
+
+-------------------------------------------------------------------------------------------------------------
+function WallLib.GetPointDirDepth( nRawId, ptP, vtDir)
+ -- recupero il solido del grezzo
+ local nSolId = EgtGetFirstNameInGroup( nRawId, 'RawSolid')
+ if not nSolId then return end
+ -- interseco con la retta
+ local bOk, vType, vPar = EgtLineSurfTmInters( ptP, vtDir, nSolId, GDB_RT.GLOB)
+ if not bOk then return end
+ if not vPar or #vPar == 0 then return -2 end
+ local dLenIn, dLenOut
+ for i = 1, #vPar do
+ if vPar[i] < 0 then
+ if vType[i] == GDB_SLT.IN or vType[i] == GDB_SLT.TG_INI then
+ dLenIn = -1
+ end
+ if vType[i] == GDB_SLT.OUT or vType[i] == GDB_SLT.TG_FIN then
+ dLenIn = -2
+ end
+ else
+ if vType[i] == GDB_SLT.IN or vType[i] == GDB_SLT.TG_INI then
+ dLenIn = vPar[i]
+ end
+ if vType[i] == GDB_SLT.OUT or vType[i] == GDB_SLT.TG_FIN or vType[i] == GDB_SLT.TOUCH then
+ dLenOut = vPar[i]
+ end
+ end
+ end
+ return dLenIn, dLenOut
+end
+
+---------------------------------------------------------------------
+function WallLib.GetFaceElevation( nSurfId, nFac, nRawId)
+ local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFac, GDB_ID.ROOT)
+ if not ptC or not vtN then return 0 end
+ local frOCS = Frame3d( ptC, vtN) ;
+ local b3Box = EgtGetBBoxRef( nSurfId, GDB_BB.STANDARD, frOCS)
+ local dElev = b3Box:getMax():getZ()
+ if nRawId then
+ local _, dCenElev = WallLib.GetPointDirDepth( nRawId, ptC, vtN)
+ if dCenElev and dCenElev > dElev then dElev = dCenElev end
+ local dOffsX = min( 20, b3Box:getDimX() / 4)
+ local _, dP1Elev = WallLib.GetPointDirDepth( nRawId, ptC + dOffsX * frOCS:getVersX(), vtN)
+ if dP1Elev and dP1Elev > dElev then dElev = dP1Elev end
+ local _, dP2Elev = WallLib.GetPointDirDepth( nRawId, ptC - dOffsX * frOCS:getVersX(), vtN)
+ if dP2Elev and dP2Elev > dElev then dElev = dP2Elev end
+ local dOffsY = min( 20, b3Box:getDimY() / 4)
+ local _, dP3Elev = WallLib.GetPointDirDepth( nRawId, ptC + dOffsY * frOCS:getVersY(), vtN)
+ if dP3Elev and dP3Elev > dElev then dElev = dP3Elev end
+ local _, dP4Elev = WallLib.GetPointDirDepth( nRawId, ptC - dOffsY * frOCS:getVersY(), vtN)
+ if dP4Elev and dP4Elev > dElev then dElev = dP4Elev end
+ end
+ return dElev
+end
+
+---------------------------------------------------------------------
+function WallLib.GetFaceWithMostAdj( nSurfId, nPartId, bCompare3Fc, dCosSideAng)
+ -- recupero il numero di facce
+ local nFacCnt = EgtSurfTmFacetCount( nSurfId)
+ if not dCosSideAng then
+ dCosSideAng = -0.09
+ end
+ -- recupero le normali delle facce
+ local vvtN = {}
+ for i = 1, nFacCnt do
+ local _, vtN = EgtSurfTmFacetCenter( nSurfId, i - 1, GDB_ID.ROOT)
+ vvtN[i] = vtN ;
+ end
+ -- adiacenze e sottosquadra delle facce
+ local vAdj = {}
+ local vUcut = {}
+ local vOrtho = {}
+ local vBlind = {}
+ for i = 1, nFacCnt do
+ -- recupero le adiacenze del loop esterno
+ local vFacAdj = EgtSurfTmFacetAdjacencies( nSurfId, i - 1)[1]
+ -- le conto
+ local nCount = 0
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ nCount = nCount + 1
+ end
+ end
+ vAdj[i] = nCount
+ -- ne determino eventuale sottosquadra ( dal valore passato o - 3deg) e ortogonalità
+ local bUcut = false
+ local bOrtho = true
+ for j = 1, #vFacAdj do
+ if vFacAdj[j] >= 0 then
+ local vtN = vvtN[i]
+ local vtN2 = vvtN[vFacAdj[j]+1]
+ local dResV = vtN * vtN2
+ if dResV < dCosSideAng - GEO.EPS_SMALL then
+ bUcut = true
+ end
+ if abs( dResV) > 2 * GEO.EPS_SMALL then
+ bOrtho = false
+ end
+ end
+ end
+ -- verifico se schermata da altra faccia
+ local bBlind = false
+ for j = 1, nFacCnt do
+ if i ~= j then
+ if vvtN[i] * vvtN[j] < -0.5 then
+ bBlind = true
+ end
+ end
+ end
+ -- assegno i risultati
+ vUcut[i] = bUcut
+ vOrtho[i] = bOrtho
+ vBlind[i] = bBlind
+ end
+ -- se 4 facce tutte con adiacenza 2, allora è un tunnel
+ if nFacCnt == 4 then
+ if vAdj[1] == 2 and vAdj[2] == 2 and vAdj[3] == 2 and vAdj[4] == 2 then
+ -- se tutte le facce sono ortogonali tra loro esco con un flag che ne indica questa propietà
+ if vOrtho[1] == true and vOrtho[2] == true and vOrtho[3] == true and vOrtho[4] == true then
+ return -1, GEO.INFINITO, true
+ else
+ return -1, GEO.INFINITO
+ end
+ end
+ end
+ -- se 3 facce con una che ha 2 adiacenze e le altre hanno 1 adiacenza, allora è una semi-fessura
+ if bCompare3Fc and nFacCnt == 3 then
+ local nCount2Adc = 0
+ local nCount1Adc = 0
+ -- ottengo il numero di facce con due adiacenze e il numero di facce con una adiacenza
+ for i = 1, #vAdj do
+ if vAdj[i] == 2 then
+ nCount2Adc = nCount2Adc + 1
+ elseif vAdj[i] == 1 then
+ nCount1Adc = nCount1Adc + 1
+ end
+ end
+ -- se il numero di adiacenze corrisponde
+ if nCount2Adc == 1 and nCount1Adc == 2 then
+ if vOrtho[1] == true and vOrtho[2] == true and vOrtho[3] == true then
+ return -1, GEO.INFINITO, true
+ else
+ return -1, GEO.INFINITO
+ end
+ end
+ end
+ -- recupero le facce non in sottosquadra e con il maggior numero di adiacenze
+ local nFacInd = {}
+ local nMaxAdj = -1
+ local nSupAdj = -1
+ for i = 1, nFacCnt do
+ if not vUcut[i] and not vBlind[i] then
+ if vAdj[i] >= nMaxAdj and vAdj[i] > 0 then
+ table.insert( nFacInd, i - 1)
+ nMaxAdj = vAdj[i]
+ elseif vAdj[i] > 0 then
+ table.insert( nFacInd, i - 1)
+ end
+ end
+ if vAdj[i] > nSupAdj then
+ nSupAdj = vAdj[i]
+ end
+ end
+ -- verifico non ci sia una faccia in sottosquadra con adiacenza superiore
+ if nSupAdj > nMaxAdj then
+ return -2, GEO.INFINITO
+ end
+ -- premio la faccia con minore elevazione
+ local nFacOpt, nFacOpt2
+ local nOptAdj, nOptAdj2
+ local dMinElev, dMinElev2 = GEO.INFINITO, GEO.INFINITO
+ for i = 1, #nFacInd do
+ local dElev = WallLib.GetFaceElevation( nSurfId, nFacInd[i], nPartId)
+ if dElev < dMinElev and ( not nOptAdj or vAdj[nFacInd[i]+1] >= nOptAdj) then
+ if dMinElev < dMinElev2 then
+ nFacOpt2 = nFacOpt
+ nOptAdj2 = nOptAdj
+ dMinElev2 = dMinElev
+ end
+ nFacOpt = nFacInd[i]
+ nOptAdj = vAdj[nFacInd[i]+1]
+ dMinElev = dElev
+ elseif dElev < dMinElev2 and ( not nOptAdj2 or vAdj[nFacInd[i]+1] >= nOptAdj2) then
+ nFacOpt2 = nFacInd[i]
+ nOptAdj2 = vAdj[nFacInd[i]+1]
+ dMinElev2 = dElev
+ end
+ end
+ return nFacOpt, dMinElev, nFacOpt2, dMinElev2
+end
+
+---------------------------------------------------------------------
+function WallLib.GetFaceHvRefDim( nSurfId, nFacet)
+ -- recupero centro e normale della faccia
+ local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFacet, GDB_ID.ROOT)
+ if not ptC or not vtN then return end
+ -- riferimento tipo OCS della faccia (X orizz, Y max pendenza, Z normale)
+ local frHV = Frame3d( ptC, vtN)
+ if frHV:getVersY():getZ() < 0 then
+ frHV:rotate( ptC, vtN, 180)
+ end
+ -- determino l'ingombro in questo riferimento
+ local b3HV = EgtSurfTmGetFacetBBoxRef( nSurfId, nFacet, GDB_BB.STANDARD, frHV)
+ -- restituisco i valori calcolati
+ return frHV, b3HV:getDimX(), b3HV:getDimY()
+end
+
+---------------------------------------------------------------------
+function WallLib.GetNearestParalOpposite( vtRef)
+ -- devo confrontare la componente orizzontale con quella verticale
+ local dHorSq = vtRef:getX() * vtRef:getX() + vtRef:getY() * vtRef:getY()
+ local dVertSq =vtRef:getZ() * vtRef:getZ()
+ -- se prevalente la componente orizzontale
+ if dHorSq >= dVertSq then
+ if abs( vtRef:getX()) > abs( vtRef:getY()) then
+ if vtRef:getX() > 0 then
+ return MCH_MILL_FU.PARAL_LEFT
+ else
+ return MCH_MILL_FU.PARAL_RIGHT
+ end
+ else
+ if vtRef:getY() > 0 then
+ return MCH_MILL_FU.PARAL_FRONT
+ else
+ return MCH_MILL_FU.PARAL_BACK
+ end
+ end
+ -- altrimenti prevale la verticale
+ else
+ if vtRef:getZ() > 0 then
+ return MCH_MILL_FU.PARAL_DOWN
+ else
+ return MCH_MILL_FU.PARAL_TOP
+ end
+ end
+ return nil
+end
+
+---------------------------------------------------------------------
+function WallLib.GetNearestOrthoOpposite( vtRef, vtNorm)
+ -- se definita anche la normale alla faccia, elimino la parte di vtRef parallela a questa
+ local vtMyRef = Vector3d( vtRef)
+ if vtNorm then
+ vtMyRef = vtMyRef - ( vtMyRef * vtNorm) * vtNorm
+ vtMyRef:normalize()
+ end
+ -- devo confrontare la componente orizzontale con quella verticale
+ local dHorSq = vtMyRef:getX() * vtMyRef:getX() + vtMyRef:getY() * vtMyRef:getY()
+ local dVertSq = vtMyRef:getZ() * vtMyRef:getZ()
+ -- se prevalente la componente orizzontale
+ if dHorSq >= dVertSq then
+ if abs( vtMyRef:getX()) >= abs( vtMyRef:getY()) then
+ if vtMyRef:getX() > 0 then
+ return MCH_MILL_FU.ORTHO_LEFT
+ else
+ return MCH_MILL_FU.ORTHO_RIGHT
+ end
+ else
+ if vtMyRef:getY() > 0 then
+ return MCH_MILL_FU.ORTHO_FRONT
+ else
+ return MCH_MILL_FU.ORTHO_BACK
+ end
+ end
+ -- altrimenti prevale la verticale
+ else
+ if vtMyRef:getZ() > 0 then
+ return MCH_MILL_FU.ORTHO_DOWN
+ else
+ return MCH_MILL_FU.ORTHO_TOP
+ end
+ end
+ return nil
+end
+
+-------------------------------------------------------------------------------------------------------------
+return WallLib
diff --git a/ProgettoRestylingWall/Wall/NestFlipAndRotate.lua b/ProgettoRestylingWall/Wall/NestFlipAndRotate.lua
new file mode 100644
index 0000000..b2b655a
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/NestFlipAndRotate.lua
@@ -0,0 +1,454 @@
+-- NestFlipAndRotate.lua by Egaltech s.r.l. 2021/11/25
+-- Flip e rotazione ottimali per il nesting in base all'analisi delle features
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+-- NFAR.PARTID =
+NFAR.RAW_GRAIN_DIR_X = true
+
+local sLog = 'Flip And Rotate Part ' .. tostring( NFAR.PARTID)
+EgtOutLog( sLog)
+
+-- Imposto direttorio libreria specializzata per Travi
+local sBaseDir = EgtGetSourceDir()
+EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua')
+
+-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Pareti
+local sMachDir = EgtGetCurrMachineDir()
+if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then
+ NFAR.ERR = 12
+ NFAR.MSG = 'Error not configured for walls machine : ' .. sMachine
+ WriteErrToLogFile( NFAR.ERR, NFAR.MSG)
+ PostErrView( NFAR.ERR, NFAR.MSG)
+ return
+end
+
+-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
+EgtRemoveBaseMachineDirFromPackagePath()
+EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua')
+
+-- Carico le librerie
+_G.package.loaded.WallExec = nil
+local WE = require( 'WallExec')
+_G.package.loaded.WProcessLapJoint = nil
+local LapJoint = require( 'WProcessLapJoint')
+_G.package.loaded.WProcessDrill = nil
+local Drill = require( 'WProcessDrill')
+_G.package.loaded.WProcessCut = nil
+local Cut = require( 'WProcessCut')
+_G.package.loaded.WProcessDoubleCut = nil
+local DoubleCut = require( 'WProcessDoubleCut')
+_G.package.loaded.WProcessSawCut = nil
+local SawCut = require( 'WProcessSawCut')
+_G.package.loaded.WProcessFreeContour = nil
+local FreeContour = require( 'WProcessFreeContour')
+_G.package.loaded.WProcessMortise = nil
+local Mortise = require( 'WProcessMortise')
+_G.package.loaded.WProcessDtMortise = nil
+local DtMortise = require( 'WProcessDtMortise')
+_G.package.loaded.WProcessMark = nil
+local Mark = require( 'WProcessMark')
+_G.package.loaded.WProcessText = nil
+local Text = require( 'WProcessText')
+
+-- Carico i dati globali
+local WD = require( 'WallData')
+
+local function ClassifyFlip( vPartProc, b3Part)
+
+ local FlipFeatureStates = {}
+ local bLapJoints = false
+
+ for nInd = 1, #vPartProc do
+ if LapJoint.Identify( vPartProc[nInd]) then
+ -- setto parametro Q
+ if vPartProc[nInd].Prc == 30 then
+ EgtSetInfo( vPartProc[nInd].Id, "Q08", 1)
+ EgtSetInfo( vPartProc[nInd].Id, "Q08A", 1)
+ else
+ EgtSetInfo( vPartProc[nInd].Id, "Q03", 1)
+ EgtSetInfo( vPartProc[nInd].Id, "Q03A", 1)
+ end
+ bLapJoints = true
+ local nFlip0, nFlip1 = LapJoint.FlipClassify(vPartProc[nInd])
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif Drill.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = Drill.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif Cut.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = Cut.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif DoubleCut.Identify( vPartProc[nInd]) then
+ -- setto parametro Q
+ if vPartProc[nInd].Prc == 12 then
+ EgtSetInfo( vPartProc[nInd].Id, "Q02", 1)
+ EgtSetInfo( vPartProc[nInd].Id, "Q02A", 1)
+ end
+ local nFlip0, nFlip1 = DoubleCut.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif SawCut.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = SawCut.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif FreeContour.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = FreeContour.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif Mortise.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = Mortise.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif DtMortise.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = DtMortise.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif Mark.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = Mark.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ elseif Text.Identify( vPartProc[nInd]) then
+ local nFlip0, nFlip1 = Text.FlipClassify(vPartProc[nInd], b3Part)
+ if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then
+ table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1})
+ end
+ end
+ end
+
+ return FlipFeatureStates, bLapJoints
+end
+
+
+local function ClassifyRotation( vPartProc)
+
+ local RotateFeatureStates = {}
+ for nInd = 1, #vPartProc do
+ if Drill.Identify( vPartProc[nInd]) then
+ local nRot0, nRot90, nRot180, nRot270 = Drill.RotateClassify(vPartProc[nInd], ValidRotations)
+ if nRot0 and nRot0 >= 0 then
+ table.insert( RotateFeatureStates, { Rot0 = nRot0, Rot90 = nRot90, Rot180 = nRot180, Rot270 = nRot270})
+ end
+ end
+ end
+
+ return RotateFeatureStates
+end
+
+---
+
+local vPartProc = WE.CollectFeatures( NFAR.PARTID)
+local b3Part = EgtGetBBoxGlob( NFAR.PARTID, GDB_BB.STANDARD)
+local bManualFlip = EgtGetInfo( NFAR.PARTID, "MANUALFLIP", 'b')
+local bManualRot = EgtGetInfo( NFAR.PARTID, "MANUALROT", 'b')
+
+-- FLIP
+local FlipFeatureStates, bLapJoints = ClassifyFlip( vPartProc, b3Part)
+
+if not bManualFlip then
+ local bFlip
+ -- analizzo stati flip delle feature
+ local nFlip0Min = 100
+ local nFlip0Cnt = 0
+ local nFlip1Min = 100
+ local nFlip1Cnt = 0
+ -- calcolo punteggio minimo e sua molteplicita' per entrambi i lati
+ for nInd = 1, #FlipFeatureStates do
+ if FlipFeatureStates[nInd].Flip0 < nFlip0Min then
+ nFlip0Min = FlipFeatureStates[nInd].Flip0
+ nFlip0Cnt = 1
+ elseif FlipFeatureStates[nInd].Flip0 == nFlip0Min then
+ nFlip0Cnt = nFlip0Cnt + 1
+ end
+ if FlipFeatureStates[nInd].Flip1 < nFlip1Min then
+ nFlip1Min = FlipFeatureStates[nInd].Flip1
+ nFlip1Cnt = 1
+ elseif FlipFeatureStates[nInd].Flip1 == nFlip1Min then
+ nFlip1Cnt = nFlip1Cnt + 1
+ end
+ end
+ -- calcolo lato con punteggio minore o molteplicita' piu' alta
+ if nFlip0Min == nFlip1Min then
+ if nFlip0Cnt > nFlip1Cnt then
+ bFlip = true
+ elseif nFlip0Cnt < nFlip1Cnt then
+ bFlip = false
+ elseif bLapJoints then
+ -- se equivalenti ma ci sono lap joints, fisso il flip per non avere problemi con le aree di lavorazione nel nesting
+ bFlip = false
+ end
+ elseif nFlip0Min < nFlip1Min then
+ bFlip = true
+ else
+ bFlip = false
+ end
+
+ if bFlip ~= nil then
+ -- se una posizione è più conveniente dell'altra setto info nel pezzo
+ EgtSetInfo( NFAR.PARTID, "NestAllowFlip", false)
+ EgtSetInfo( NFAR.PARTID, "NestFlip", bFlip)
+ else
+ EgtSetInfo( NFAR.PARTID, "NestAllowFlip", true)
+ end
+
+ if bFlip then
+ -- flip pezzo
+ EgtRotate( NFAR.PARTID, b3Part:getCenter(), X_AX(), 180, GDB_RT.GLOB)
+ -- modifico le info del pezzo
+ local nPartFlip = EgtGetInfo( NFAR.PARTID, "INVERTED", 'i') or 0
+ local nTotFlip = EgtIf( nPartFlip == 180, 0, 180)
+ EgtSetInfo( NFAR.PARTID, "INVERTED", nTotFlip)
+ EgtSetInfo( NFAR.PARTID, "FLIPROTMODIFIED", 1)
+ end
+end
+
+-- rimuovo parametri Q
+local b3PartInside = BBox3d( b3Part)
+b3PartInside:expand( - WD.INSIDE_RAW_TOL)
+for nInd = 1, #vPartProc do
+ local Proc = vPartProc[nInd]
+
+ if LapJoint.Identify( Proc) then
+ -- cerco la faccia rivolta verso l'alto e la faccia rivolta verso il basso
+ local nFaceInd = -1
+ local nFaceDownInd = -1
+ for nIdx = 0, Proc.Fct - 1 do
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
+ if vtN:getZ() > 0.95 then
+ nFaceInd = nIdx
+ elseif vtN:getZ() < - 0.95 then
+ nFaceDownInd = nIdx
+ end
+ end
+ -- se è lap joint dall'alto
+ if nFaceInd ~= -1 and nFaceDownInd == -1 then
+ local ptCen = EgtSurfTmFacetCenter( Proc.Id, nFaceInd, GDB_ID.ROOT)
+ -- se all'interno rimuovo info Q
+ if EnclosesPointXY( b3PartInside, ptCen) then
+ -- resetto parametro Q
+ if Proc.Prc == 30 then
+ EgtRemoveInfo( Proc.Id, "Q08")
+ EgtRemoveInfo( Proc.Id, "Q08A")
+ else
+ EgtRemoveInfo( Proc.Id, "Q03")
+ EgtRemoveInfo( Proc.Id, "Q03A")
+ end
+ end
+ end
+
+ elseif DoubleCut.Identify( Proc) then
+ -- verifico se due facce e rivolto verso l'alto
+ if Proc.Fct == 2 then
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+
+ if ( vtN[1]:getZ() >= 0.95 or vtN[2]:getZ() >= 0.95) then
+ local nFaceInd = EgtIf( vtN[1]:getZ() >= 0.95, 0, 1)
+ local ptCen = EgtSurfTmFacetCenter( Proc.Id, nFaceInd, GDB_ID.ROOT)
+ -- se all'interno rimuovo info Q
+ if EnclosesPointXY( b3PartInside, ptCen) then
+ -- resetto parametro Q
+ if Proc.Prc == 12 then
+ EgtRemoveInfo( Proc.Id, "Q02")
+ EgtRemoveInfo( Proc.Id, "Q02A")
+ end
+ end
+ end
+ end
+ end
+end
+
+
+-- ROTATION
+nRotate = 0
+-- venatura
+EgtRemoveInfo( NFAR.PARTID, "HasGrainDirection")
+local bGrain = false
+local sGrainInfo = EgtGetInfo( NFAR.PARTID, "GRAINDIRECTION", 's')
+if sGrainInfo then
+ local sGrainAlign = string.sub( sGrainInfo, 7)
+ local sGrainDir = string.sub( sGrainInfo, 1, 5)
+ if sGrainAlign == "1" and ( sGrainDir == "1,0,0" or sGrainDir == "0,1,0") then
+ EgtSetInfo( NFAR.PARTID, "HasGrainDirection", 1)
+ bGrain = true
+ -- trovo la rotazione ( a meno di 180°) che deve avere il pezzo per essere allineato con la venatura del grezzo
+ local nGrainRot = 0
+ if ( sGrainDir == "1,0,0" and not NFAR.RAW_GRAIN_DIR_X) or ( sGrainDir == "0,1,0" and NFAR.RAW_GRAIN_DIR_X) then
+ nGrainRot = 90
+ end
+
+ local nPartRot = EgtGetInfo( NFAR.PARTID, "ROTATED", 'i') or 0
+ if ( nGrainRot == 0 and ( nPartRot == 90 or nPartRot == 270)) or ( nGrainRot == 90 and ( nPartRot == 0 or nPartRot == 180)) then
+ local b3Part = EgtGetBBoxGlob( NFAR.PARTID, GDB_BB.STANDARD)
+ EgtRotate( NFAR.PARTID, b3Part:getCenter(), Z_AX(), 90, GDB_RT.GLOB)
+ nRotate = 90
+ end
+ end
+end
+
+if not bManualRot then
+
+ local RotateFeatureStates = ClassifyRotation( vPartProc)
+
+ -- analizzo stati rotazione delle feature
+ local nRot0Min = 100
+ local nRot0Cnt = 0
+ local nRot90Min = 100
+ local nRot90Cnt = 0
+ local nRot180Min = 100
+ local nRot180Cnt = 0
+ local nRot270Min = 100
+ local nRot270Cnt = 0
+ -- calcolo punteggio minimo e sua molteplicita' per tutte le rotazioni
+ for nInd = 1, #RotateFeatureStates do
+ if RotateFeatureStates[nInd].Rot0 < nRot0Min then
+ nRot0Min = RotateFeatureStates[nInd].Rot0
+ nRot0Cnt = 1
+ elseif RotateFeatureStates[nInd].Rot0 == nRot0Min then
+ nRot0Cnt = nRot0Cnt + 1
+ end
+ if RotateFeatureStates[nInd].Rot90 < nRot90Min then
+ nRot90Min = RotateFeatureStates[nInd].Rot90
+ nRot90Cnt = 1
+ elseif RotateFeatureStates[nInd].Rot90 == nRot90Min then
+ nRot90Cnt = nRot90Cnt + 1
+ end
+ if RotateFeatureStates[nInd].Rot180 < nRot180Min then
+ nRot180Min = RotateFeatureStates[nInd].Rot180
+ nRot180Cnt = 1
+ elseif RotateFeatureStates[nInd].Rot180 == nRot180Min then
+ nRot180Cnt = nRot180Cnt + 1
+ end
+ if RotateFeatureStates[nInd].Rot270 < nRot270Min then
+ nRot270Min = RotateFeatureStates[nInd].Rot270
+ nRot270Cnt = 1
+ elseif RotateFeatureStates[nInd].Rot270 == nRot270Min then
+ nRot270Cnt = nRot270Cnt + 1
+ end
+ end
+
+ -- se c'e' qualche stato di rotazione
+ local MinList = { { Rot = 0, Score = nRot0Min, ScoreCnt = nRot0Cnt},
+ { Rot = 90, Score = nRot90Min, ScoreCnt = nRot90Cnt},
+ { Rot = 180, Score = nRot180Min, ScoreCnt = nRot180Cnt},
+ { Rot = 270, Score = nRot270Min, ScoreCnt = nRot270Cnt}}
+ local nRotateOpt = 0
+ if #RotateFeatureStates > 0 then
+ -- calcolo lato con punteggio minore o molteplicita' piu' alta
+ local nRotMax = 0
+ local nScoreMax = 0
+ local nScoreCnt = 0
+ for nInd = 1, #MinList do
+ if MinList[nInd].Score > nScoreMax then
+ nRotMax = MinList[nInd].Rot
+ nScoreMax = MinList[nInd].Score
+ nScoreCnt = MinList[nInd].ScoreCnt
+ elseif MinList[nInd].Score == nScoreMax then
+ if MinList[nInd].ScoreCnt > nScoreCnt then
+ nRotMax = MinList[nInd].Rot
+ nScoreMax = MinList[nInd].Score
+ nScoreCnt = MinList[nInd].ScoreCnt
+ end
+ end
+ end
+ nRotateOpt = nRotMax
+ else
+ nRotateOpt = 0
+ end
+
+ local bRotNest = false
+ local nStepRotNest = 0
+ -- se calcolate limitazioni su rotazioni
+ if MinList and #MinList > 0 then
+ -- verifico condizioni da permettere al nesting
+ if MinList[1].Score >= 50 and MinList[2].Score >= 50 and MinList[3].Score >= 50 and MinList[4].Score >= 50 then
+ bRotNest = true
+ nStepRotNest = 90
+ elseif (nRotateOpt == 0 and MinList[3].Score >= 50) or ( nRotateOpt == 90 and MinList[4].Score >= 50) then
+ bRotNest = true
+ nStepRotNest = 180
+ end
+ else
+ -- altrimenti permetto tutto
+ bRotNest = true
+ nStepRotNest = 90
+ end
+
+ -- verifico se ci sono fori lungo Y che bloccano la rotazione
+ local bDrillOnY = ( nStepRotNest == 180)
+
+ local b3Part = EgtGetBBoxGlob( NFAR.PARTID, GDB_BB.STANDARD)
+
+ if bGrain then
+ -- se venatura eseguo rotazione solo se è di 180°
+ if nRotateOpt == 180 then
+ EgtRotate( NFAR.PARTID, b3Part:getCenter(), Z_AX(), nRotateOpt, GDB_RT.GLOB)
+ nRotate = nRotate + nRotateOpt
+ end
+ nStepRotNest = 180
+ else
+ -- eseguo rotazione
+ EgtRotate( NFAR.PARTID, b3Part:getCenter(), Z_AX(), nRotateOpt, GDB_RT.GLOB)
+ nRotate = nRotate + nRotateOpt
+ end
+
+ -- verifico se rotazione è valida ( pezzo contenuto nel grezzo) solo se no venatura
+ if not bGrain then
+ b3Part = EgtGetBBoxGlob( NFAR.PARTID, GDB_BB.STANDARD)
+ local bValidRotationForRaw = b3Part:getDimX() < WD.MAX_LENGTH and b3Part:getDimY() < WD.MAX_WIDTH
+ local bRotatedIsValid = b3Part:getDimY() < WD.MAX_LENGTH and b3Part:getDimX() < WD.MAX_WIDTH
+ if not bValidRotationForRaw and bRotatedIsValid then
+ EgtRotate( NFAR.PARTID, b3Part:getCenter(), Z_AX(), 90, GDB_RT.GLOB)
+ nRotate = nRotate + 90
+ nStepRotNest = 180
+ end
+ end
+
+ -- se no venatura e non ci sono fori verifico se il pezzo cade
+ if not bGrain and not bDrillOnY then
+ b3Part = EgtGetBBoxGlob( NFAR.PARTID, GDB_BB.STANDARD)
+ local bValidRotation = b3Part:getDimX() > ( WD.INTRULLI or 1200)
+ -- verifico se ruotata resta valida
+ local bRotatedIsValid = b3Part:getDimY() > ( WD.INTRULLI or 1200)
+ -- se non è valida ma ruotato lo sarebbe, ruoto
+ if not bValidRotation and bRotatedIsValid and nStepRotNest ~= 180 then
+ EgtRotate( NFAR.PARTID, b3Part:getCenter(), Z_AX(), 90, GDB_RT.GLOB)
+ nRotate = nRotate + 90
+ nStepRotNest = 180
+ elseif bValidRotation and not bRotatedIsValid then
+ -- se fosse valida ma la sua ruotata no, allora blocco lo step nella rotazione del nesting
+ nStepRotNest = 180
+ end
+ end
+
+ -- setto info nel pezzo
+ if nRotate > 0 then
+ local nPartRot = EgtGetInfo( NFAR.PARTID, "ROTATED", 'i') or 0
+ local nTotRot = nPartRot + nRotate
+ nTotRot = EgtIf( nTotRot < 360, nTotRot, nTotRot - 360)
+ EgtSetInfo( NFAR.PARTID, "ROTATED", nTotRot)
+ EgtSetInfo( NFAR.PARTID, "FLIPROTMODIFIED", 1)
+ end
+
+ EgtSetInfo( NFAR.PARTID, "NestStepRot", nStepRotNest)
+ EgtSetInfo( NFAR.PARTID, "NestRot", nRotate)
+ EgtSetInfo( NFAR.PARTID, "NestAllowRot", bRotNest)
+end
+
+
+NFAR.ERR = 0
\ No newline at end of file
diff --git a/ProgettoRestylingWall/Wall/NestProcess.lua b/ProgettoRestylingWall/Wall/NestProcess.lua
new file mode 100644
index 0000000..5787391
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/NestProcess.lua
@@ -0,0 +1,2241 @@
+-- NestProcess.lua by Egaltech s.r.l. 2021/05/25
+-- Gestione nesting automatico pareti
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+-- Per test
+--NEST = {}
+--NEST.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
+--NEST.MACHINE = 'Essetre-90480019_MW'
+--NEST.FLAG = 3
+--NEST.MIN_ANGLE_PNT = 60
+--NEST.DRILL_MACH_AREA = 0
+NEST.LAP_JOINT_U_MACH_AREA = 1 -- 0
+NEST.MACH_AREA_USE_OTHER_DIAM = 1 -- 0
+NEST.MACH_AREA_OTHER_DIAM = 200
+NEST.MACH_AREA_IGNORE_3rdFACE = 1 -- 0
+
+
+local sLog = 'NestProcess : ' .. NEST.FILE .. ', ' .. NEST.MACHINE .. ', ' .. LEN["1"] .. ', ' .. WIDTH["1"]
+EgtOutLog( sLog)
+
+-- Cancello file di log specifico
+local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt')
+EgtEraseFile( sLogFile)
+
+-- Imposto direttorio libreria specializzata per Travi
+local sBaseDir = EgtGetSourceDir()
+EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua')
+
+-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Pareti
+local sMachDir = EgtGetCurrMachineDir()
+if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then
+ NEST.ERR = 12
+ NEST.MSG = 'Error not configured for walls machine : ' .. sMachine
+ WriteErrToLogFile( NEST.ERR, NEST.MSG)
+ PostErrView( NEST.ERR, NEST.MSG)
+ return
+end
+
+-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
+EgtRemoveBaseMachineDirFromPackagePath()
+EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua')
+
+-- Carico le librerie
+_G.package.loaded.WallExec = nil
+local WE = require( 'WallExec')
+_G.package.loaded.WallLib = nil
+local WL = require( 'WallLib')
+_G.package.loaded.WProcessLapJoint = nil
+local LapJoint = require( 'WProcessLapJoint')
+_G.package.loaded.WProcessDrill = nil
+local Drill = require( 'WProcessDrill')
+_G.package.loaded.WProcessDoubleCut = nil
+local DoubleCut = require( 'WProcessDoubleCut')
+_G.package.loaded.WProcessFreeContour = nil
+local FreeContour = require( 'WProcessFreeContour')
+
+-- Carico i dati globali
+local WD = require( 'WallData')
+
+-- lista dei pezzi con flip o rotazione
+local PartStates = {}
+
+-- Funzioni per scrittura su file di log specifico
+local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
+ local hFile = io.open( sLogFile, 'a')
+ hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
+ hFile:write( sMsg .. '\n')
+ hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
+ hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
+ hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
+ hFile:close()
+end
+
+local function WriteTimeToLogFile( dTime)
+ local hFile = io.open( sLogFile, 'a')
+ hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
+ hFile:close()
+end
+
+-- Funzione per gestire visualizzazione dopo errore
+local function PostErrView( nErr, sMsg)
+ if nErr ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
+ EgtSetView( SCE_VD.ISO_SW, false)
+ EgtZoom( SCE_ZM.ALL)
+ EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
+ end
+end
+
+-- Funzione per gestire visualizzazione dopo warning
+local function PostWarnView( nWarn, sMsg)
+ if nWarn ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
+ EgtSetView( SCE_VD.ISO_SW, false)
+ EgtZoom( SCE_ZM.ALL)
+ EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
+ end
+end
+
+-- Funzione per aggiornare dati ausiliari
+local function UpdateAuxData( sAuxFile)
+ local bModif = false
+ -- Se definito LOAD90, aggiorno
+ local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
+ if sLoad90 ~= '' then
+ local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
+ EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
+ bModif = true
+ end
+ return bModif
+end
+
+-- Funzione per trovare nome MachGroup
+local function NewMachGroupName()
+ local nMachGroupId = EgtGetFirstMachGroup()
+ if not nMachGroupId then return 1 end
+ local nMaxMachGroup = 0
+ while nMachGroupId do
+ sMachGroupName = EgtGetMachGroupName(nMachGroupId)
+ local nMachGroupName = tonumber(sMachGroupName)
+ if nMachGroupName > nMaxMachGroup then
+ nMaxMachGroup = nMachGroupName
+ end
+ nMachGroupId = EgtGetNextMachGroup(nMachGroupId)
+ end
+ return nMaxMachGroup + 1
+end
+
+-- Funzione che crea il rettangolo della lavorazione
+local function CreateToolRectangle( ptP1, dValP1, ptP2, dValP2, vtFace, dValFace, nOutlineGrp)
+ local dExtra = 5
+ local vtX = ptP2 - ptP1
+ vtX:normalize()
+ -- creo il rettangolo della lavorazione
+ ptP1 = ptP1 - vtX * ( dValP1 + dExtra)
+ ptP2 = ptP2 + vtX * ( dValP2 + dExtra)
+ ptP2 = ptP2 + vtFace * ( dValFace + dExtra)
+ --local nId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX(), ptP2:getY(), 0), Point3d( ptP1:getX(), ptP1:getY(), 0))
+ local nId = EgtRectangle2P( nOutlineGrp, ptP2, ptP1)
+ return nId
+end
+
+-- Funzione che verifica se la lavorazione è lap joint dal basso ed eventualmente ne calcola l'area di lavorazione
+local function IdentifyLJFromBottom( Proc, bCompute, nOutlineGrp)
+
+ local bLJFromBottom = false
+ local nRectId
+ local vtFace
+
+ local dMinCompZ = 0.95
+ if Proc.Fct == 2 then
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+
+ -- se rivolto verso il basso
+ if ( vtN[1]:getZ() < - dMinCompZ or vtN[2]:getZ() < - dMinCompZ) then
+ vtFace = EgtIf( vtN[1]:getZ() < - dMinCompZ, vtN[2], vtN[1])
+ if not ( vtFace:getZ() > dMinCompZ or vtFace:getZ() < - dMinCompZ) then
+ bLJFromBottom = true
+ if bCompute then
+ local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
+ -- creo il rettangolo della lavorazione
+ nRectId = CreateToolRectangle( ptP1, WD.SIDEMILL_DIAM_DOWN / 2, ptP2, WD.SIDEMILL_DIAM_DOWN / 2, vtFace, WD.SIDEMILL_DIAM_DOWN, nOutlineGrp)
+ end
+ end
+ end
+
+
+ elseif Proc.Fct == 3 then
+ local nFacInd, dElev, nFacInd2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+
+ -- se nel mezzo di una faccia
+ if not nFacInd2 then
+ if nFacInd ~= -2 and nFacInd ~= GDB_ID.NULL then
+ vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+ if not ( vtFace:getZ() > dMinCompZ or vtFace:getZ() < - dMinCompZ) then
+ local nOtherFace = EgtIf( nFacInd == 0, 1, 0)
+ local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nOtherFace, GDB_ID.ROOT)
+ if abs( ptP1:getZ() - ptP2:getZ()) < GEO.EPS_SMALL then
+ bLJFromBottom = true
+ if bCompute then
+ nRectId = CreateToolRectangle( ptP1, WD.SIDEMILL_DIAM_DOWN / 2, ptP2, WD.SIDEMILL_DIAM_DOWN / 2, vtFace, WD.SIDEMILL_DIAM_DOWN, nOutlineGrp)
+ end
+ end
+ end
+ end
+
+ -- se dal basso
+ else
+ local nFaceZ = -1
+ for nIdx = 0, 2 do
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
+ if vtN2:getZ() < - dMinCompZ then
+ nFaceZ = nIdx
+ break
+ end
+ end
+ if nFaceZ ~= -1 then
+ local nFace = EgtIf( nFaceZ == nFacInd, nFacInd2, nFacInd)
+ local nOtherFace = EgtIf( nFaceZ + nFace == 3, 0, EgtIf( nFaceZ + nFace == 2, 1, 2))
+ vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFace, GDB_ID.ROOT)
+ --vtFace[2] = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFace, GDB_ID.ROOT)
+ bLJFromBottom = true
+ if bCompute then
+ local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFace, nFaceZ, GDB_ID.ROOT)
+ local bAdj2, ptP3, ptP4 = EgtSurfTmFacetsContact( Proc.Id, nFace, nOtherFace, GDB_ID.ROOT)
+ if AreSamePointApprox( ptP2, ptP3) or AreSamePointApprox( ptP2, ptP4) then
+ ptP1, ptP2 = ptP2, ptP1
+ end
+ local dVal = EgtIf( NEST.MACH_AREA_IGNORE_3rdFACE == 1, WD.SIDEMILL_DIAM_DOWN / 2, 0)
+ nRectId = CreateToolRectangle( ptP1, dVal, ptP2, WD.SIDEMILL_DIAM_DOWN / 2, vtFace, WD.SIDEMILL_DIAM_DOWN, nOutlineGrp)
+ end
+ end
+ end
+
+ elseif Proc.Fct == 4 then
+ local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+ if nFacInd ~= -2 and nFacInd ~= GDB_ID.NULL then
+ vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+
+ if not ( vtFace:getZ() > dMinCompZ or vtFace:getZ() < - dMinCompZ) then
+ local nOtherFace = -1
+ for nIdx = 0, 3 do
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
+ if vtN2:getZ() > dMinCompZ or vtN2:getZ() < - dMinCompZ then
+ nOtherFace = nIdx
+ break
+ end
+ end
+ if nOtherFace ~= -1 and nOtherFace ~= nFacInd and nOtherFace ~= nFacInd2 then
+ bLJFromBottom = true
+ if bCompute then
+ local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nOtherFace, GDB_ID.ROOT)
+ local bAdj2, ptP3, ptP4 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacInd2, GDB_ID.ROOT)
+ if AreSamePointApprox( ptP2, ptP3) or AreSamePointApprox( ptP2, ptP4) then
+ ptP1, ptP2 = ptP2, ptP1
+ end
+ nRectId = CreateToolRectangle( ptP1, 0, ptP2, WD.SIDEMILL_DIAM_DOWN / 2, vtFace, WD.SIDEMILL_DIAM_DOWN, nOutlineGrp)
+ end
+ end
+ end
+
+ if nFacInd2 and nFacInd2 ~= GDB_ID.NULL then
+ local vtFace2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT)
+ if ( vtFace2:getZ() < - dMinCompZ or vtFace:getZ() < - dMinCompZ) then
+ bLJFromBottom = true
+ if vtFace:getZ() < -dMinCompZ then vtFace = vtFace2 end
+ if bCompute then
+ local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacInd2, GDB_ID.ROOT)
+ nRectId = CreateToolRectangle( ptP1, 0, ptP2, 0, vtFace, WD.SIDEMILL_DIAM_DOWN, nOutlineGrp)
+ end
+ end
+ end
+
+ end
+ end
+
+ if bLJFromBottom then
+ return vtFace, nRectId
+ else
+ return
+ end
+end
+
+-- Funzione che verifica se la lavorazione è lap joint da sopra ed eventualmente ne calcola l'area di lavorazione
+local function IdentifyLJFromTop( Proc, bCompute, nOutlineGrp)
+
+ local bLJFromTop = false
+ local vtFace, nRectId
+
+ if not WD.SIDEMILL_DIAM_UP or WD.SIDEMILL_DIAM_UP < GEO.EPS_SMALL then return end
+
+ local dMinComp = 0.95
+ if Proc.Fct == 2 then
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+
+ -- se rivolto verso l'alto
+ if (vtN[1]:getZ() > dMinComp or vtN[2]:getZ() > dMinComp) then
+ bLJFromTop = true
+ vtFace = EgtIf( vtN[1]:getZ() > dMinComp, vtN[2], vtN[1])
+ if bCompute then
+ local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
+ local b3Face = EgtSurfTmGetFacetBBoxGlob( Proc.Id, EgtIf( vtN[1]:getZ() > dMinComp, 0, 1), GDB_BB.STANDARD)
+ local dDim = 0
+ if vtFace:getX() > dMinComp or vtFace:getX() < - dMinComp then
+ dDim = b3Face:getDimX()
+ elseif vtFace:getY() > dMinComp or vtFace:getY() < - dMinComp then
+ dDim = b3Face:getDimY()
+ end
+ local dValFace = max( dDim + WD.SIDEMILL_DIAM_UP / 2, WD.SIDEMILL_DIAM_UP)
+ local dVal = WD.SIDEMILL_DIAM_UP / 2
+ if NEST.MACH_AREA_USE_OTHER_DIAM == 1 then
+ dVal = NEST.MACH_AREA_OTHER_DIAM / 2
+ end
+ nRectId = CreateToolRectangle( ptP1, dVal, ptP2, dVal, vtFace, dValFace, nOutlineGrp)
+ end
+ end
+
+ -- caso 3 facce
+ elseif Proc.Fct == 3 then
+ local nFacInd, dElev, nFacInd2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
+
+ -- forma ad U
+ if not nFacInd2 and nFacInd ~= GDB_ID.NULL and NEST.LAP_JOINT_U_MACH_AREA == 1 then
+ local vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
+ if vtFace:getZ() > dMinComp then
+ bLJFromTop = true
+ if bCompute then
+ local b3Face = EgtSurfTmGetFacetBBoxGlob( Proc.Id, nFacInd, GDB_BB.STANDARD)
+ local nOtherFace = EgtIf( nFacInd == 0, 1, 0)
+ local vtNOther = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFace, GDB_ID.ROOT)
+ local vtDir = EgtIf( AreSameOrOppositeVectorApprox( vtNOther, X_AX()), Y_AX(), X_AX())
+ local dVal = WD.SIDEMILL_DIAM_UP / 2 + 5
+ local ptMin = b3Face:getMin() - dVal * vtDir
+ local ptMax = b3Face:getMax() + dVal * vtDir
+ -- nRectId = EgtRectangle2P( nOutlineGrp, Point3d(ptMax:getX(), ptMax:getY(), 0), Point3d( ptMin:getX(), ptMin:getY(), 0))
+ nRectId = EgtRectangle2P( nOutlineGrp, ptMax, ptMin)
+ end
+ end
+
+ elseif nFacInd2 then
+ local nFaceZ = -1
+ for nIdx = 0, 2 do
+ local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
+ if vtN2:getZ() > dMinComp then
+ nFaceZ = nIdx
+ break
+ end
+ end
+ if nFaceZ ~= -1 then
+ local nFace = EgtIf( nFaceZ == nFacInd, nFacInd2, nFacInd)
+ local nOtherFace = EgtIf( nFaceZ + nFace == 3, 0, EgtIf( nFaceZ + nFace == 2, 1, 2))
+ local vtFace = {}
+ vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFace, GDB_ID.ROOT)
+ --vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFace, GDB_ID.ROOT)
+ bLJFromTop = true
+ if bCompute then
+ local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFace, nFaceZ, GDB_ID.ROOT)
+ local bAdj2, ptP3, ptP4 = EgtSurfTmFacetsContact( Proc.Id, nFace, nOtherFace, GDB_ID.ROOT)
+ if AreSamePointApprox( ptP2, ptP3) or AreSamePointApprox( ptP2, ptP4) then
+ ptP1, ptP2 = ptP2, ptP1
+ end
+
+ local b3Face = EgtSurfTmGetFacetBBoxGlob( Proc.Id, nFaceZ, GDB_BB.STANDARD)
+ local dDim = 0
+ if vtFace:getX() > dMinComp or vtFace:getX() < - dMinComp then
+ dDim = b3Face:getDimX()
+ elseif vtFace:getY() > dMinComp or vtFace:getY() < - dMinComp then
+ dDim = b3Face:getDimY()
+ end
+ local dValFace = max( dDim + WD.SIDEMILL_DIAM_UP / 2, WD.SIDEMILL_DIAM_UP)
+ local dVal = WD.SIDEMILL_DIAM_UP / 2
+ if NEST.MACH_AREA_USE_OTHER_DIAM == 1 then
+ dVal = NEST.MACH_AREA_OTHER_DIAM / 2
+ end
+ nRectId = CreateToolRectangle( ptP1, 0, ptP2, dVal, vtFace, dValFace, nOutlineGrp)
+ end
+ end
+ end
+ end
+
+ if bLJFromTop then
+ return vtFace, nRectId
+ else
+ return
+ end
+end
+
+-- Funzione che crea le regioni occupate dalle lavorazioni
+local function ComputeToolOutlines( nPartId)
+
+ local ToolOutlineId = {}
+ EgtRemoveInfo( nPartId, "ToolOutlines")
+
+ -- recupero il gruppo con gli outlines degli utensili
+ local nOutlineGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "ToolOutlines")
+ if not nOutlineGrp or nOutlineGrp == GDB_ID.NULL then
+ nOutlineGrp = EgtGroup( GDB_ID.ROOT)
+ EgtSetName( nOutlineGrp, "ToolOutlines")
+ EgtSetStatus( nOutlineGrp, GDB_ST.OFF)
+ end
+
+ local vPartProc = WE.CollectFeatures( nPartId, b3Raw)
+ for nInd = 1, #vPartProc do
+
+ local Proc = vPartProc[nInd]
+
+ -- lap joint
+ if LapJoint.Identify( Proc) then
+ -- verifico se dal basso
+ local _ , nRectId = IdentifyLJFromBottom( Proc, true, nOutlineGrp)
+ if nRectId then
+ EgtSetColor( nRectId, EgtStdColor("BLUE"))
+ table.insert( ToolOutlineId, nRectId)
+ else
+ -- verifico se dall'alto
+ local _ , nRectId = IdentifyLJFromTop( Proc, true, nOutlineGrp)
+ if nRectId then
+ EgtSetColor( nRectId, EgtStdColor("AQUA"))
+ local nPrId = EgtGetInfo( Proc.Id, "PRID", 'i')
+ EgtSetInfo( nRectId, "PRID", nPrId)
+ table.insert( ToolOutlineId, nRectId)
+ end
+ end
+ end
+
+ -- fori
+ if NEST.DRILL_MACH_AREA == 1 and Drill.Identify( Proc) then
+ -- recupero dati del foro
+ local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + Proc.Id end
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
+ local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0)
+ local dDiam = 2 * EgtArcRadius( AuxId)
+
+ -- verifico se la lunghezza del foro è maggiore della lunghezza della punta
+ if bOpen and AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) and dLen > WD.HOR_DRILL_LEN - 1 then
+ local ptP1 = Proc.Box:getMin()
+ local ptP2 = Proc.Box:getMax()
+ local dExtra = 10
+ ptP1 = ptP1 - ( WD.MAX_WIDTH - dLen + dExtra) * Y_AX()
+ ptP2 = ptP2 + ( WD.MAX_WIDTH - dLen + dExtra) * Y_AX()
+
+ --local nId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX(), ptP2:getY(), 0), Point3d( ptP1:getX(), ptP1:getY(), 0))
+ local nId = EgtRectangle2P( nOutlineGrp, ptP2, ptP1)
+ EgtSetColor( nId, EgtStdColor("AQUA"))
+ if nId ~= GDB_ID.NULL then table.insert(ToolOutlineId, nId) end
+ end
+ end
+
+ -- lati inclinati free contour
+ if FreeContour.Identify( Proc) then
+ local bPocket = EgtGetInfo( Proc.Id, 'PCKT', 'b')
+ if not bPocket then
+ for nInd = 0, Proc.Fct - 1 do
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nInd, GDB_ID.ROOT)
+ -- se inclinato
+ if abs( vtN:getZ()) > GEO.EPS_SMALL then
+ local bUnderCut = vtN:getZ() < - GEO.EPS_SMALL
+
+ local dCosAlpha = (vtN ^ Z_AX()):len()
+ local dVal
+ if bUnderCut then
+ dVal = ( NEST.OFFSET + 0.1) / dCosAlpha
+ else
+ dVal = ( NEST.OFFSET + 0.1) * dCosAlpha
+ end
+
+ local frLoc, dDimX, dDimY = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nInd, GDB_ID.ROOT)
+ local b3Face = EgtSurfTmGetFacetBBoxRef( Proc.Id, nInd, GDB_BB.STANDARD, frLoc)
+ local ptA = b3Face:getMin()
+ local ptC = b3Face:getMax()
+ local ptB = ptA + dDimY * Y_AX()
+ local ptD = ptA + dDimX * X_AX()
+ ptA:toGlob( frLoc)
+ ptB:toGlob( frLoc)
+ ptC:toGlob( frLoc)
+ ptD:toGlob( frLoc)
+
+ local ptP1, ptP2
+ if bUnderCut then
+ ptP1 = EgtIf( ptA:getZ() > ptC:getZ(), ptA, ptC)
+ ptP2 = EgtIf( ptB:getZ() > ptD:getZ(), ptB, ptD)
+ else
+ ptP1 = EgtIf( ptA:getZ() < ptC:getZ(), ptA, ptC)
+ ptP2 = EgtIf( ptB:getZ() < ptD:getZ(), ptB, ptD)
+ end
+
+ local vtDir = ptP2 - ptP1
+ vtDir:normalize()
+ ptP1 = ptP1 - vtDir * 0.5 * NEST.OFFSET
+ ptP2 = ptP2 + vtDir * 0.5 * NEST.OFFSET
+ local vtNxy = Vector3d( vtN:getX(), vtN:getY(), 0)
+ vtNxy:normalize()
+ local ptP4 = ptP2 + dVal * vtNxy
+
+ local nRectId = EgtRectangle3P( nOutlineGrp, ptP1, ptP4, ptP2)
+ EgtSetColor( nRectId, EgtStdColor("AQUA"))
+ if nRectId ~= GDB_ID.NULL then table.insert( ToolOutlineId, nRectId) end
+
+ end
+ end
+ end
+ end
+
+ end
+
+ return ToolOutlineId
+end
+
+
+local function ClassifyDrillsOnLateralFaces( nPartId, dMinSheetWidth)
+
+ local dDeltaRaw = WD.MAX_WIDTH - dMinSheetWidth + NEST.KERF
+ local DrillClassif
+ local DrillOnFaces = { F = {nbr = 0, closed = false, long = false, OnlyOnRef = false}, B = {nbr = 0, closed = false, long = false, OnlyOnRef = false},
+ L = {nbr = 0, closed = false, long = false, OnlyOnRef = false}, R = {nbr = 0, closed = false, long = false, OnlyOnRef = false}}
+ local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+ local ptPartMin = b3Part:getMin()
+ local ptPartMax = b3Part:getMax()
+
+ local vPartProc = WE.CollectFeatures( nPartId)
+ for nInd = 1, #vPartProc do repeat
+
+ if Drill.Identify( vPartProc[nInd]) then
+
+ -- identifico su quali facce si trova il foro
+ local bOpen = ( vPartProc[nInd].Fcs ~= 0 and vPartProc[nInd].Fce ~= 0)
+ local AuxId = EgtGetInfo( vPartProc[nInd].Id, 'AUXID', 'i') or 0
+ if AuxId then AuxId = AuxId + vPartProc[nInd].Id end
+ if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then break end
+ local ptDrill = EgtCP( AuxId, GDB_RT.GLOB)
+ local dLen = abs( EgtCurveThickness( AuxId))
+ local bLong = dLen > WD.HOR_DRILL_LEN - 1
+ local bOnlyOnRef = dLen + dDeltaRaw > WD.HOR_DRILL_LEN - GEO.EPS_SMALL and not bLong
+
+ -- faccia Front
+ local dTol = GEO.EPS_SMALL
+ if ( abs( ptDrill:getY() - ptPartMin:getY()) < dTol) then
+ DrillOnFaces.F.nbr = DrillOnFaces.F.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.F.OnlyOnRef = true end
+ if bOpen then
+ DrillOnFaces.B.nbr = DrillOnFaces.B.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.B.OnlyOnRef = true end
+ else
+ DrillOnFaces.F.closed = true
+
+ end
+ if bLong then
+ DrillOnFaces.F.long = true
+ if bOpen then DrillOnFaces.B.long = true end
+ end
+
+ -- faccia Back
+ elseif ( abs( ptDrill:getY() - ptPartMax:getY()) < dTol) then
+ DrillOnFaces.B.nbr = DrillOnFaces.B.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.B.OnlyOnRef = true end
+ if bOpen then
+ DrillOnFaces.F.nbr = DrillOnFaces.F.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.F.OnlyOnRef = true end
+ else
+ DrillOnFaces.B.closed = true
+ end
+ if bLong then
+ DrillOnFaces.B.long = true
+ if bOpen then DrillOnFaces.F.long = true end
+ end
+
+ -- faccia Left
+ elseif ( abs( ptDrill:getX() - ptPartMin:getX()) < dTol) then
+ DrillOnFaces.L.nbr = DrillOnFaces.L.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.L.OnlyOnRef = true end
+ if bOpen then
+ DrillOnFaces.R.nbr = DrillOnFaces.R.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.R.OnlyOnRef = true end
+ else
+ DrillOnFaces.L.closed = true
+ end
+ if bLong then
+ DrillOnFaces.L.long = true
+ if bOpen then DrillOnFaces.R.long = true end
+ end
+
+ -- faccia Right
+ elseif ( abs( ptDrill:getX() - ptPartMax:getX()) < dTol) then
+ DrillOnFaces.R.nbr = DrillOnFaces.R.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.R.OnlyOnRef = true end
+ if bOpen then
+ DrillOnFaces.L.nbr = DrillOnFaces.L.nbr + 1
+ if bOnlyOnRef then DrillOnFaces.L.OnlyOnRef = true end
+ else
+ DrillOnFaces.R.closed = true
+ end
+ if bLong then
+ DrillOnFaces.R.long = true
+ if bOpen then DrillOnFaces.L.long = true end
+ end
+ end
+ end
+
+ until true
+ end
+
+ -- identifico la faccia da mettere sul lato del grezzo
+ local sDrillFace, nMax = '', -100
+ for k, v in pairs( DrillOnFaces) do
+ if v.nbr > nMax or ( v.nbr == nMax and not DrillOnFaces[sDrillFace].OnlyOnRef and v.OnlyOnRef) then
+ sDrillFace, nMax = k, v.nbr
+ end
+ end
+
+ local sDrillFace2
+ if nMax > 0 then
+ if sDrillFace == 'F' or sDrillFace == 'B' then
+ -- cerco chi vince tra faccia left e right
+ if DrillOnFaces.L.nbr > DrillOnFaces.R.nbr then
+ sDrillFace2 = 'L'
+ elseif DrillOnFaces.L.nbr < DrillOnFaces.R.nbr then
+ sDrillFace2 = 'R'
+ elseif DrillOnFaces.L.nbr == DrillOnFaces.R.nbr and DrillOnFaces.L.nbr > 0 then
+ if DrillOnFaces.L.OnlyOnRef then
+ sDrillFace2 = 'L'
+ else
+ sDrillFace2 = 'R'
+ end
+ end
+
+ else
+ -- cerco chi vince tra faccia front e back
+ if DrillOnFaces.F.nbr > DrillOnFaces.B.nbr then
+ sDrillFace2 = 'F'
+ elseif DrillOnFaces.F.nbr < DrillOnFaces.B.nbr then
+ sDrillFace2 = 'B'
+ elseif DrillOnFaces.F.nbr == DrillOnFaces.B.nbr and DrillOnFaces.F.nbr > 0 then
+ if DrillOnFaces.F.OnlyOnRef then
+ sDrillFace2 = 'F'
+ else
+ sDrillFace2 = 'B'
+ end
+ end
+ end
+ end
+
+
+ if NEST.DRILL_MACH_AREA == 0 then
+ DrillOnFaces[sDrillFace].long = false
+ end
+
+ if nMax > 0 then
+ DrillClassif = { sCase = sDrillFace, bClosed = DrillOnFaces[sDrillFace].closed, bLong = DrillOnFaces[sDrillFace].long, bOnlyOnRef = DrillOnFaces[sDrillFace].OnlyOnRef }
+ end
+
+ local DrillClassif2
+ if sDrillFace2 then
+ if NEST.DRILL_MACH_AREA == 0 then
+ DrillOnFaces[sDrillFace2].long = false
+ end
+ DrillClassif2 = { sCase = sDrillFace2, bClosed = DrillOnFaces[sDrillFace2].closed, bLong = DrillOnFaces[sDrillFace2].long, bOnlyOnRef = DrillOnFaces[sDrillFace2].OnlyOnRef }
+ end
+
+
+ return DrillClassif, DrillClassif2
+end
+
+local function ClassifyLapJointsFromBottom( nPartId)
+
+ local res = { Nbr = 0, sCase = '', bParall = false}
+
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local ptPartMin = b3Part:getMin()
+ local ptPartMax = b3Part:getMax()
+
+ local vtLapJoints = {}
+ local dMinComponentVal = 0.95
+ local vPartProc = WE.CollectFeatures( nPartId)
+ for nInd = 1, #vPartProc do
+
+ if LapJoint.Identify( vPartProc[nInd]) then
+ -- verifico se LJ da sotto
+ local vtFace = IdentifyLJFromBottom( vPartProc[nInd], false)
+ if vtFace then
+ if vtFace:getX() > dMinComponentVal then
+ vtLapJoints["R"] = 1
+ elseif vtFace:getX() < - dMinComponentVal then
+ vtLapJoints["L"] = 1
+ elseif vtFace:getY() > dMinComponentVal then
+ vtLapJoints["B"] = 1
+ elseif vtFace:getY() < - dMinComponentVal then
+ vtLapJoints["F"] = 1
+ end
+ end
+ end
+ end
+
+ local nCnt = 0
+ for _ in pairs(vtLapJoints) do nCnt = nCnt + 1 end
+
+ if nCnt == 1 then
+ res.Nbr = 1
+ for k, _ in pairs( vtLapJoints) do
+ res.sCase = k
+ end
+
+ elseif nCnt == 2 then
+ res.Nbr = 2
+ if vtLapJoints["F"] and vtLapJoints["B"] then
+ res.bParall = true
+ res.sCase = "F"
+ elseif vtLapJoints["R"] and vtLapJoints["L"] then
+ res.bParall = true
+ res.sCase = "R"
+ else
+ res.bParall = false
+ if vtLapJoints["B"] and vtLapJoints["R"] then
+ res.sCase = 'BR'
+ elseif vtLapJoints["B"] and vtLapJoints["L"] then
+ res.sCase = 'BL'
+ elseif vtLapJoints["F"] and vtLapJoints["R"] then
+ res.sCase = 'FR'
+ elseif vtLapJoints["F"] and vtLapJoints["L"] then
+ res.sCase = 'FL'
+ end
+ end
+
+ elseif nCnt == 3 then
+ res.Nbr = 3
+ if not vtLapJoints["F"] then
+ res.sCase = "F"
+ elseif not vtLapJoints["B"] then
+ res.sCase = "B"
+ elseif not vtLapJoints["R"] then
+ res.sCase = "R"
+ elseif not vtLapJoints["L"] then
+ res.sCase = "L"
+ end
+
+ elseif nCnt == 4 then
+ res.Nbr = 4
+ elseif nCnt ~= 0 then
+ return
+ end
+
+ return res
+
+end
+
+
+local function CreateDefectOnAngle( nPartId, RawPart, bDrillLong, bOnOppositeAng)
+
+ local PartTab = {}
+ -- recupero il gruppo dove salvo i defects
+ local nOutlineGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "SheetDefects")
+ if not nOutlineGrp or nOutlineGrp == GDB_ID.NULL then
+ nOutlineGrp = EgtGroup( GDB_ID.ROOT)
+ EgtSetName( nOutlineGrp, "SheetDefects")
+ EgtSetStatus( nOutlineGrp, GDB_ST.OFF)
+ end
+
+ local dExtraMachArea = WD.SIDEMILL_DIAM_DOWN -- per tenere conto dell'area di lavorazione
+ local dExtra = NEST.KERF
+
+ -- local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+ local b3PartX = b3Part:getDimX()
+ local b3PartY = b3Part:getDimY()
+ -- se ho fori lunghi devo riservare tutto lo spazio
+ if bDrillLong then
+ b3PartY = RawPart.Width
+ end
+
+ -- calcolo i punti che definiscono il rettangolo
+ local ptP1, ptP2
+ if ( WD.ORIG_CORNER == 'TL' and not bOnOppositeAng) or ( WD.ORIG_CORNER == 'BL' and bOnOppositeAng) then
+ -- angolo TL
+ ptP1 = Point3d( 0, RawPart.Width - b3PartY - dExtra, 0)
+ ptP2 = Point3d( b3PartX + dExtra, RawPart.Width, 0)
+ PartTab.posX = NEST.KERF
+ PartTab.posY = RawPart.Width - b3Part:getDimY() - NEST.KERF
+ elseif ( WD.ORIG_CORNER == 'BL' and not bOnOppositeAng) or ( WD.ORIG_CORNER == 'TL' and bOnOppositeAng) then
+ -- angolo BL
+ ptP1 = Point3d( 0, 0, 0)
+ ptP2 = Point3d( b3PartX + dExtra, b3PartY + dExtra, 0)
+ PartTab.posX = NEST.KERF
+ PartTab.posY = NEST.KERF
+ elseif ( WD.ORIG_CORNER == 'TR' and not bOnOppositeAng) or ( WD.ORIG_CORNER == 'BR' and bOnOppositeAng) then
+ -- angolo TR
+ ptP1 = Point3d( RawPart.Len - b3PartX - dExtra, RawPart.Width - b3PartY - dExtra, 0)
+ ptP2 = Point3d( RawPart.Len, RawPart.Width, 0)
+ PartTab.posX = RawPart.Len - b3Part:getDimX() - NEST.KERF
+ PartTab.posY = RawPart.Width - b3Part:getDimY() - NEST.KERF
+ elseif ( WD.ORIG_CORNER == 'BR' and not bOnOppositeAng) or ( WD.ORIG_CORNER == 'TR' and bOnOppositeAng) then
+ -- angolo BR
+ ptP1 = Point3d( RawPart.Len - b3PartX - dExtra, 0, 0)
+ ptP2 = Point3d( RawPart.Len, b3PartY + dExtra, 0)
+ PartTab.posX = RawPart.Len - b3Part:getDimX() - NEST.KERF
+ PartTab.posY = NEST.KERF
+ end
+
+ PartTab.Id = tonumber(nPartId)
+ PartTab.DefectId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX() + dExtraMachArea, ptP2:getY() + dExtraMachArea , 0), Point3d( ptP1:getX() - dExtraMachArea , ptP1:getY() - dExtraMachArea, 0))
+ EgtSetName( PartTab.DefectId, "Defect")
+
+ return PartTab
+
+end
+
+
+local function RotateOptimalCase( nPartId, nAngle, nAngleValidRot, RawPart, nPnt1, nPnt2)
+
+ local bOptimal = false
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), nAngle, GDB_RT.GLOB)
+ local nRotate = nAngle
+ local nAnglePnt
+ local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+ -- b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local bIsValidRotation = b3Part:getDimX() < RawPart.Len - 2 * NEST.KERF + GEO.EPS_SMALL and b3Part:getDimY() < RawPart.Width - 2 * NEST.KERF + GEO.EPS_SMALL
+ if bIsValidRotation then
+ bOptimal = true
+ nAnglePnt = nPnt1
+ else
+ bOptimal = false
+ -- ruoto nella migliore posizione ammissibile
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), nAngleValidRot, GDB_RT.GLOB)
+ nRotate = nRotate + nAngleValidRot
+ nAnglePnt = nPnt2
+ end
+
+ if nRotate >= 360 then
+ nRotate = nRotate - 360
+ end
+
+ return nAnglePnt, nRotate, bOptimal
+
+end
+
+local function RotateOptimalCaseDrill( nPartId, bCanRotate, nPnt1, nPnt2)
+
+ local nRotate = 0
+ local nAnglePnt
+
+ if bCanRotate then
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), 180, GDB_RT.GLOB)
+ nRotate = 180
+ nAnglePnt = nPnt1
+ else
+ nAnglePnt = nPnt2
+ end
+
+ return nAnglePnt, nRotate
+end
+
+
+-- Funzione che classifica i pezzi in base alla loro necessità di stare negli angoli
+local function ClassifyAngles( nPartId, RawPart, sRefOrig, bLockedRot, dMinSheetWidth)
+
+ -- elimino eventuali info
+ EgtSetInfo( nPartId, "NestOnEdge", 0)
+ EgtSetInfo( nPartId, "NestOnAngle", 0)
+ EgtSetInfo( nPartId, "OnlyOnRefSide", 0)
+
+ local nAngle
+ local nRotate = 0
+ local bOptimal
+ local bManual = false
+ local bOnly180Rot = EgtGetInfo( nPartId, "HasGrainDirection", 'b') or false
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+
+ -- fori
+ local DrillClassif, DrillClassif2 = ClassifyDrillsOnLateralFaces( nPartId, dMinSheetWidth)
+ local bDrill = false
+ local bDrillOpen = false
+ local bLongDrill = false
+
+ if DrillClassif then
+ bDrill = true
+ bDrillOpen = not DrillClassif.bClosed
+ bLongDrill = DrillClassif.bLong
+ if DrillClassif.bOnlyOnRef then
+ EgtSetInfo( nPartId, "OnlyOnRefSide", 1)
+ end
+ end
+
+ -- oriento il pezzo in base al foro
+ if bDrill and not bLockedRot then
+ local RotationAngles
+ if sRefOrig == 'TL' or sRefOrig == 'TR' then
+ RotationAngles = { F = 180, B = 0, L = 270, R = 90}
+ else
+ RotationAngles = { F = 0, B = 180, L = 90, R = 270}
+ end
+
+ -- se rotazione è libera
+ if not bOnly180Rot then
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif.sCase], GDB_RT.GLOB)
+ nRotate = nRotate + RotationAngles[DrillClassif.sCase]
+
+ -- verifico se la rotazione è valida
+ local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+ -- b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local bIsValidRotation = b3Part:getDimX() < RawPart.Len - 2 * NEST.KERF + GEO.EPS_SMALL and b3Part:getDimY() < RawPart.Width - 2 * NEST.KERF + GEO.EPS_SMALL
+ if not bIsValidRotation then
+ -- ritorno nella posizione originaria
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), - RotationAngles[DrillClassif.sCase], GDB_RT.GLOB)
+ nRotate = nRotate - RotationAngles[DrillClassif.sCase]
+ -- se ho un'altra posizione possibile ruoto in quella
+ if DrillClassif2 then
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif2.sCase], GDB_RT.GLOB)
+ nRotate = nRotate + RotationAngles[DrillClassif2.sCase]
+ bDrillOpen = not DrillClassif2.bClosed
+ bLongDrill = DrillClassif2.bLong
+ if DrillClassif2.bOnlyOnRef then
+ EgtSetInfo( nPartId, "OnlyOnRefSide", 1)
+ end
+ else
+ -- dimentico di avere il foro
+ bDrill = false
+ end
+ end
+
+ -- se posso ruotare solo di 180° per venatura
+ else
+ if RotationAngles[DrillClassif.sCase] == 0 or RotationAngles[DrillClassif.sCase] == 180 then
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif.sCase], GDB_RT.GLOB)
+ nRotate = nRotate + RotationAngles[DrillClassif.sCase]
+ else
+ -- vedo se ho un'altra posizione possibile
+ if DrillClassif2 and ( RotationAngles[DrillClassif2.sCase] == 0 or RotationAngles[DrillClassif2.sCase] == 180) then
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif2.sCase], GDB_RT.GLOB)
+ nRotate = nRotate + RotationAngles[DrillClassif2.sCase]
+ bDrillOpen = not DrillClassif2.bClosed
+ bLongDrill = DrillClassif2.bLong
+ if DrillClassif2.bOnlyOnRef then
+ EgtSetInfo( nPartId, "OnlyOnRefSide", 1)
+ end
+ else
+ -- dimentico di avere il foro
+ bDrill = false
+ end
+ end
+ end
+ end
+
+ -- se non ho venature e fori scelgo una posizione che non faccia cadere il pezzo
+ if not bDrill and not bOnly180Rot and not bLockedRot then
+ b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local bIsValid = b3Part:getDimX() > ( WD.INTRULLI or 1200)
+ local bRotatedIsValid = b3Part:getDimY() > ( WD.INTRULLI or 1200)
+ if not bIsValid and not bRotatedIsValid then
+ EgtSetInfo( nPartId, "REDUCECUT", 1)
+ elseif not bIsValid or not bRotatedIsValid then
+ bOnly180Rot = true
+ EgtSetInfo( nPartId, "NestStepRot", 180)
+ end
+ if not bIsValid and bRotatedIsValid then
+ EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), 90, GDB_RT.GLOB)
+ nRotate = nRotate + 90
+ end
+ end
+
+
+ -- lap joints
+ local ResLapJoints = ClassifyLapJointsFromBottom( nPartId)
+ b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local bAdd = true
+
+ if ResLapJoints.Nbr > 0 and bLockedRot then
+ b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ if b3Part:getDimX() > ( WD.INTRULLI or 1200) then
+ EgtSetInfo( nPartId, "REDUCECUT", 1)
+ end
+ local PartAngleClassification = { PartId = tostring( nPartId), Angle = 100, nRotate = 0, bDrill = true, bLongDrill = true}
+ return PartAngleClassification
+ end
+
+ -- se anche fori oppure possibile solo rotazione di 180° per non far cadere il pezzo
+ if bDrill or bOnly180Rot then
+ local bCanRotate = not bDrill or ( bDrill and bDrillOpen)
+
+ if ResLapJoints.Nbr == 0 then
+ nAngle = 0
+ if not bDrill then bAdd = false end
+
+ elseif ResLapJoints.Nbr == 1 then
+ if (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'B' ) or
+ (( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'F' ) then
+ nAngle = 20
+ elseif (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'F' ) or
+ (( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'B' ) then
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 20, 100)
+ nRotate = nRotate + nRotate2
+ elseif ResLapJoints.sCase == 'R' then
+ if bCanRotate then bManual = true end
+ if sRefOrig == 'TL' or sRefOrig == 'BL'then
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 40, 0)
+ nRotate = nRotate + nRotate2
+ else
+ nAngle = 40
+ end
+ elseif ResLapJoints.sCase == 'L' then
+ if bCanRotate then bManual = true end
+ if sRefOrig == 'TR' or sRefOrig == 'BR' then
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 40, 0)
+ nRotate = nRotate + nRotate2
+ else
+ nAngle = 40
+ end
+ end
+
+ elseif ResLapJoints.Nbr == 2 then
+ if ResLapJoints.bParall then
+ if ResLapJoints.sCase == 'F' then
+ nAngle = 100
+ else
+ nAngle = 80
+ end
+ else
+ if (( sRefOrig == 'TL' or sRefOrig == 'TR') and (ResLapJoints.sCase == 'BL' or ResLapJoints.sCase == 'BR')) or
+ (( sRefOrig == 'BL' or sRefOrig == 'BR') and (ResLapJoints.sCase == 'FL' or ResLapJoints.sCase == 'FR')) then
+ nAngle = 40
+ else
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 40, 100)
+ nRotate = nRotate + nRotate2
+ end
+ end
+
+ elseif ResLapJoints.Nbr == 3 then
+ if (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'F' ) or
+ (( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'B' ) then
+ nAngle = 80
+ elseif (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'B' ) or
+ (( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'F' ) then
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 80, 100)
+ nRotate = nRotate + nRotate2
+ elseif ResLapJoints.sCase == 'R' then
+ if bCanRotate then bManual = true end
+ if sRefOrig == 'TR' or sRefOrig == 'BR' then
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 100, 100)
+ nRotate = nRotate + nRotate2
+ end
+ nAngle = 100
+ elseif ResLapJoints.sCase == 'L' then
+ if bCanRotate then bManual = true end
+ if sRefOrig == 'TL' or sRefOrig == 'BL' then
+ nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 100, 100)
+ nRotate = nRotate + nRotate2
+ end
+ nAngle = 100
+ end
+
+ elseif ResLapJoints.Nbr == 4 then
+ nAngle = 100
+ end
+
+
+ -- no fori
+ else
+ if ResLapJoints.Nbr == 0 then
+ bAdd = false
+
+ elseif ResLapJoints.Nbr == 1 then
+ if sRefOrig == 'TL' or sRefOrig == 'TR' then
+ RotationAngles = { F = 180, B = 0, R = 90, L = 270}
+ elseif sRefOrig == 'BL'or sRefOrig == 'BR' then
+ RotationAngles = { F = 0, B = 180, R = 270, L = 90}
+ end
+ local nAngleValidRot = EgtIf( sRefOrig == 'TL' or sRefOrig == 'BR', 90, 270)
+ nAngle, nRotate2, bOptimal = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], nAngleValidRot, RawPart, 20, 40)
+ nRotate = nRotate + nRotate2
+ if not bOptimal then bManual = true end
+
+ elseif ResLapJoints.Nbr == 2 then
+ if ResLapJoints.bParall then
+ -- se lap joints su lati paralleli
+ RotationAngles = { F = 90, R = 0}
+ nAngle, nRotate2 = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], 90, RawPart, 80, 100)
+ nRotate = nRotate + nRotate2
+ else
+ -- se lap joints su lati adiacenti
+ if sRefOrig == 'TR' then
+ RotationAngles = { FR = 90, BR = 0, BL = 270, FL = 180}
+ elseif sRefOrig == 'TL' then
+ RotationAngles = { FR = 180, BR = 90, BL = 0, FL = 270}
+ elseif sRefOrig == 'BR' then
+ RotationAngles = { FR = 0, BR = 270, BL = 180, FL = 90}
+ elseif sRefOrig == 'BL' then
+ RotationAngles = { FR = 270, BR = 180, BL = 90, FL = 0}
+ end
+ local nAngleValidRot = EgtIf( sRefOrig == 'TL' or sRefOrig == 'BR', 270, 90)
+ nAngle, nRotate2, bOptimal = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], nAngleValidRot, RawPart, 40, 40)
+ nRotate = nRotate + nRotate2
+
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local bCanRotate = b3Part:getDimX() < RawPart.Width
+ if bOptimal and bCanRotate then bManual = true end
+ end
+
+ elseif ResLapJoints.Nbr == 3 then
+ if sRefOrig == 'TL' or sRefOrig == 'TR' then
+ RotationAngles = { F = 0, B = 180, R = 270, L = 90}
+ elseif sRefOrig == 'BL' or sRefOrig == 'BR' then
+ RotationAngles = { F = 180, B = 0, R = 90, L = 270}
+ end
+ local nAngleValidRot = EgtIf( sRefOrig == 'TL' or sRefOrig == 'BR', 90, 270)
+ nAngle, nRotate2, bOptimal = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], nAngleValidRot, RawPart, 80, 100)
+ nRotate = nRotate + nRotate2
+ if not bOptimal then bManual = true end
+
+ elseif ResLapJoints.Nbr == 4 then
+ nAngle, nRotate2 = RotateOptimalCase( nPartId, 0, 90, RawPart, 100, 100)
+ nRotate = nRotate + nRotate2
+ end
+
+ end
+
+
+ -- aggiorno le info di rotazione del pezzo
+ if nRotate >= 360 then
+ nRotate = nRotate - 360
+ end
+ if nRotate > 0 then
+ local nPartRot = EgtGetInfo( nPartId, "ROTATED", 'i') or 0
+ local nTotRot = nPartRot + nRotate
+ nTotRot = EgtIf( nTotRot < 360, nTotRot, nTotRot - 360)
+ EgtSetInfo( nPartId, "ROTATED", nTotRot)
+ EgtSetInfo( nPartId, "MODIFIEDFORNEST", 1)
+ end
+
+ if not bAdd then
+ return
+ end
+
+ local PartAngleClassification = { PartId = tostring( nPartId), Angle = nAngle, nRotate = nRotate, bDrill = bDrill, bLongDrill = bLongDrill, bManual = bManual}
+
+ local bCanBeOnOtherEdge = not bDrill or ( bDrill and RawPart.Width >= WD.MINRAWY_HOR_DRILL)
+ if bOnly180Rot then
+ if bCanBeOnOtherEdge then
+ EgtSetInfo( nPartId, "NestAllowRot", 1)
+ EgtSetInfo( nPartId, "NestStepRot", 180)
+ else
+ EgtSetInfo( nPartId, "NestAllowRot", 0)
+ EgtSetInfo( nPartId, "NestStepRot", 0)
+ end
+ end
+
+ -- verifico se il pezzo cade (caso di foro)
+ b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ if b3Part:getDimX() > ( WD.INTRULLI or 1200) then
+ EgtSetInfo( nPartId, "REDUCECUT", 1)
+ end
+
+ return PartAngleClassification
+end
+
+
+local function ComputeRestrictedZones( RawParts)
+
+ local dTotArea = 0
+ -- area totale dei pezzi
+ for nPartId, nCount in pairs( PART) do
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+ local dPartArea = b3Part:getDimX() * b3Part:getDimY()
+ dTotArea = dTotArea + dPartArea * nCount
+ end
+
+ -- stimo il numero di angoli disponibili
+ local vSheetNbrEstimate = {}
+ local nSheetNbrEstimate = 0
+ local nSheetNbrCorrection = - 2
+ local nAnglesNbrEstimate = 0
+ local nAngelsNbrCorrection = 0
+
+ local vRawDistrib = {}
+ if #RawParts == 1 then
+ vRawDistrib = {1}
+ elseif #RawParts == 2 then
+ vRawDistrib = {0.7, 0.3}
+ else
+ for nInd = 1, #RawParts do
+ table.insert( vRawDistrib, 1 / #RawParts)
+ end
+ end
+
+ local dMaxSheetWidth = -100
+ local nMaxSheet = 1
+ local dMinSheetWidth = WD.MAX_WIDTH
+ for nInd = 1, #RawParts do
+ local dSheetArea = RawParts[nInd].Len * RawParts[nInd].Width
+ if RawParts[nInd].Width > dMaxSheetWidth + GEO.EPS_SMALL then
+ dMaxSheetWidth = RawParts[nInd].Width
+ nMaxSheet = nInd
+ elseif abs( RawParts[nInd].Width - dMaxSheetWidth) < GEO.EPS_SMALL then
+ if RawParts[nInd].Len > RawParts[nMaxSheet].Len then
+ nMaxSheet = nInd
+ end
+ end
+ if RawParts[nInd].Width < dMinSheetWidth then
+ dMinSheetWidth = RawParts[nInd].Width
+ end
+
+ vSheetNbrEstimate[nInd] = min( ceil( dTotArea * vRawDistrib[nInd] / dSheetArea) + nSheetNbrCorrection, RawParts[nInd].Qty)
+ if vSheetNbrEstimate[nInd] <= 0 then
+ vSheetNbrEstimate[nInd] = min( RawParts[nInd].Qty, 1)
+ end
+
+ nSheetNbrEstimate = nSheetNbrEstimate + vSheetNbrEstimate[nInd]
+ nAnglesNbrEstimate = nAnglesNbrEstimate + vSheetNbrEstimate[nInd] * 2
+ end
+ nAnglesNbrEstimate = nAnglesNbrEstimate + nAngelsNbrCorrection
+
+
+ -- classificazione dei pezzi in base alla loro necessità di stare negli angoli
+ local nTotParts = 0
+ for _ in pairs( PART) do nTotParts = nTotParts + 1 end
+ local nPartIndex = 0
+ local AngleClassification = {}
+ for nPartId, nCount in pairs( PART) do
+ nPartIndex = nPartIndex + 1
+ local bManualRot = EgtGetInfo( nPartId, "MANUALROT", 'b')
+ local PartClassif = ClassifyAngles(tonumber(nPartId), RawParts[nMaxSheet], WD.ORIG_CORNER, bManualRot, dMinSheetWidth)
+ if PartClassif then
+ for nI = 1, nCount do
+ local newTab = {PartId = PartClassif.PartId, Angle = PartClassif.Angle, nRotate = PartClassif.nRotate, bDrill = PartClassif.bDrill, bLongDrill = PartClassif.bLongDrill, bManual = PartClassif.bManual}
+ table.insert( AngleClassification, newTab)
+ end
+ end
+
+ if EgtProcessEvents( nPartIndex / nTotParts * 100, 0) == 1 then
+ return false
+ end
+ end
+
+ table.sort( AngleClassification, function(a, b) return a.Angle > b.Angle end)
+
+
+ local vManuallyDone = {}
+ local vPartsManuallyDone = {}
+ for nInd = 1, #vSheetNbrEstimate do
+ for nInd2 = 1, vSheetNbrEstimate[nInd] do
+ table.insert( vManuallyDone, { RawPartId = nInd, Done = 0, Parts = {}})
+ end
+ end
+ local nSheetNbr = #vManuallyDone
+ local vFilledSheets = {}
+ for nInd = 1, #vSheetNbrEstimate do
+ for nInd2 = 1, vSheetNbrEstimate[nInd] do
+ table.insert( vFilledSheets, { Width = RawParts[nInd].Width, OrigWidth = RawParts[nInd].Width})
+ end
+ end
+
+ for nInd = 1, #AngleClassification do
+
+ if AngleClassification[nInd].Angle >= NEST.MIN_ANGLE_PNT and AngleClassification[nInd].Angle > 0 then
+
+ -- verifico di avere ancora angoli a disposizione secondo la stima dei grezzi
+ local bFound = false
+ local nBoxLayerId = EgtGetFirstNameInGroup( AngleClassification[nInd].PartId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+ local dPartWidth = b3Part:getDimY() + NEST.KERF
+ for nInd2 = 1, #vFilledSheets do
+ if dPartWidth < vFilledSheets[nInd2].Width then
+ -- verifico se il grezzo aveva già un pezzo in un angolo
+ if abs( vFilledSheets[nInd2].Width - vFilledSheets[nInd2].OrigWidth) < GEO.EPS_SMALL then
+ vFilledSheets[nInd2].Width = vFilledSheets[nInd2].Width - dPartWidth - WD.SIDEMILL_DIAM_DOWN
+ else
+ -- se il grezzo aveva già un pezzo nell'angolo, dopo il pezzo corrente non ne posso mettere altri
+ vFilledSheets[nInd2].Width = 0
+ end
+ bFound = true
+ break
+ end
+ end
+
+ -- se ho ancora angoli a disposizione oppure il pezzo deve stare necessariamente sull'angolo per essere lavorato
+ if bFound or AngleClassification[nInd].Angle == 100 then
+ -- verifico se va nestato manualmente
+ if AngleClassification[nInd].bManual then
+
+ -- trovo il punto della lista dove inserirlo
+ local nIdx = -1
+ local bOnOppositeSide = false
+ for nInd2 = 1, #vManuallyDone do
+ -- verifico se il pezzo può stare sull'altro angolo
+ local bOnlyOnRef = EgtGetInfo( AngleClassification[nInd].PartId, "OnlyOnRefSide", 'b')
+ local bCanBeOnOtherAngle = not bOnlyOnRef and
+ ( not AngleClassification[nInd].bDrill or
+ ( AngleClassification[nInd].bDrill and not AngleClassification[nInd].bLongDrill and RawParts[vManuallyDone[nInd2].RawPartId].Width >= WD.MINRAWY_HOR_DRILL))
+
+ if #(vManuallyDone[nInd2].Parts) == 0 then
+ -- verifico che il pezzo stia in questo grezzo
+ local b3Part = EgtGetBBoxGlob( AngleClassification[nInd].PartId, GDB_BB.STANDARD)
+ if b3Part:getDimX() < RawParts[vManuallyDone[nInd2].RawPartId].Len and b3Part:getDimY() < RawParts[vManuallyDone[nInd2].RawPartId].Width then
+ nIdx = nInd2
+ break
+ end
+
+ elseif #(vManuallyDone[nInd2].Parts) == 1 and bCanBeOnOtherAngle then
+ -- verifico se il pezzo già posizionato nell'angolo non ha fori lunghi
+ if not vManuallyDone[nInd2].Parts[1].bLongDrill then
+ -- oriento il pezzo in modo ottimale per andare su quell'angolo
+ local sRefOrig
+ if WD.ORIG_CORNER == 'TL' then sRefOrig = 'BL' end
+ if WD.ORIG_CORNER == 'BL' then sRefOrig = 'TL' end
+ if WD.ORIG_CORNER == 'TR' then sRefOrig = 'BR' end
+ if WD.ORIG_CORNER == 'BR' then sRefOrig = 'TR' end
+ local bManTmp
+ local res = ClassifyAngles( AngleClassification[nInd].PartId, RawParts[vManuallyDone[nInd2].RawPartId], sRefOrig, bManTmp, dMinSheetWidth)
+ -- verifico sia compatibile con pezzo già inserito
+ local b3OtherPart = EgtGetBBoxGlob( vManuallyDone[nInd2].Parts[1].Id, GDB_BB.STANDARD)
+ local b3Part = EgtGetBBoxGlob( AngleClassification[nInd].PartId, GDB_BB.STANDARD)
+ local dExtra = 2 * NEST.KERF + WD.SIDEMILL_DIAM_DOWN + 1
+ -- se è compatibile assegno questa rotazione al pezzo
+ if b3Part:getDimY() + b3OtherPart:getDimY() + dExtra < RawParts[vManuallyDone[nInd2].RawPartId].Width then
+ nIdx = nInd2
+ bOnOppositeSide = true
+ -- aggiorno le info di rotazione
+ if res.nRotate > 0 then
+ local nPartRot = EgtGetInfo( AngleClassification[nInd].PartId, "ROTATED", 'i') or 0
+ local nTotRot = nPartRot + res.nRotate
+ nTotRot = EgtIf( nTotRot < 360, nTotRot, nTotRot - 360)
+ EgtSetInfo( AngleClassification[nInd].PartId, "ROTATED", nTotRot)
+ EgtSetInfo( AngleClassification[nInd].PartId, "MODIFIEDFORNEST", 1)
+ end
+ break
+ end
+ -- altrimenti lo riporto nella sua posizione originaria
+ EgtRotate( AngleClassification[nInd].PartId, b3Part:getCenter(), Z_AX(), - res.nRotate, GDB_RT.GLOB)
+ end
+ end
+ end
+
+ -- nesto il pezzo a mano
+ if nIdx ~= -1 then
+ -- aree di lavorazione
+ local nToolOutlineIds = ComputeToolOutlines( AngleClassification[nInd].PartId)
+ local sInfo = ""
+ for nInd = 1, #nToolOutlineIds do
+ sInfo = sInfo .. tostring(nToolOutlineIds[nInd]) .. ","
+ end
+ -- salvo tra le info del pezzo gli id delle sue aree di lavorazione
+ if sInfo ~= "" then
+ EgtSetInfo( AngleClassification[nInd].PartId, "ToolOutlines", sInfo)
+ end
+
+ -- calcolo defect corrispondente al pezzo
+ local PartTab = CreateDefectOnAngle( AngleClassification[nInd].PartId, RawParts[vManuallyDone[nIdx].RawPartId], AngleClassification[nInd].bLongDrill, bOnOppositeSide)
+ PartTab.bLongDrill = AngleClassification[nInd].bLongDrill
+ table.insert( vManuallyDone[nIdx].Parts, PartTab)
+ table.insert( vPartsManuallyDone, tonumber( AngleClassification[nInd].PartId))
+
+ else
+ -- aggiungo info per il nesting per ricordare che andrà su angolo
+ EgtSetInfo( AngleClassification[nInd].PartId, "NestOnAngle", 1)
+ end
+ else
+ -- se non va nestato manualmente segno info per nesting
+ EgtSetInfo( AngleClassification[nInd].PartId, "NestOnAngle", 1)
+ end
+
+ else
+ -- se non ho più angoli a disposizione lo metto sul lato
+ EgtSetInfo(AngleClassification[nInd].PartId, "NestOnEdge", 1)
+ end
+
+ else
+ EgtSetInfo(AngleClassification[nInd].PartId, "NestOnEdge", 1)
+ end
+
+ end
+
+ local nInd = 1
+ while nInd <= #vManuallyDone do
+ if #(vManuallyDone[nInd].Parts) == 0 then
+ table.remove( vManuallyDone, nInd)
+ else
+ nInd = nInd + 1
+ end
+ end
+
+ return vManuallyDone, vPartsManuallyDone
+end
+
+
+
+-- Funzione che sposta e aggiunge pezzi per nesting
+local function AddRawParts(RawParts, vDoneManually)
+
+ local OUTLINE = "Outline"
+ for nIndex = 1, #RawParts do
+ RawParts[nIndex].PartId = {}
+
+ -- pannelli con pezzi inseriti manualmente
+ local nTotSheetWithDefects = 0
+ for nInd = 1, #vDoneManually do
+ if vDoneManually[nInd].RawPartId == nIndex then
+ -- creo pannello del materiale
+ local SheetPartId = EgtGroup(GDB_ID.ROOT)
+ table.insert( RawParts[nIndex].PartId, SheetPartId)
+ EgtSetName(SheetPartId, "Sheet")
+ local SheetLayerId = EgtGroup(SheetPartId)
+ EgtSetName(SheetLayerId, OUTLINE)
+ local SheetOutlineId = EgtRectangle2P(SheetLayerId, Point3d(0,0,0), Point3d(RawParts[nIndex].Len + 0.1, RawParts[nIndex].Width + 0.1, 0), GDB_RT.GLOB)
+ EgtSetName(SheetOutlineId, OUTLINE)
+ -- creo foglio per nesting
+ EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, NEST.KERF, 0, 1)
+ -- aggiungo defects
+ for nInd2 = 1, #(vDoneManually[nInd].Parts) do
+ EgtAutoNestAddDefectToSheet( SheetPartId, vDoneManually[nInd].Parts[nInd2].DefectId)
+ end
+ vDoneManually[nInd].SheetId = SheetPartId
+ nTotSheetWithDefects = nTotSheetWithDefects + 1
+ end
+ end
+
+ -- pannelli senza pezzi inseriti manualmente
+ local SheetPartId = EgtGroup(GDB_ID.ROOT)
+ table.insert( RawParts[nIndex].PartId, SheetPartId)
+ EgtSetName(SheetPartId, "Sheet")
+ local SheetLayerId = EgtGroup(SheetPartId)
+ EgtSetName(SheetLayerId, OUTLINE)
+ local SheetOutlineId = EgtRectangle2P(SheetLayerId, Point3d(0,0,0), Point3d(RawParts[nIndex].Len + 0.1, RawParts[nIndex].Width + 0.1, 0), GDB_RT.GLOB)
+ -- EgtModifyCurveThickness(SheetOutlineId, -Material.T_mm)
+ EgtSetName(SheetOutlineId, OUTLINE)
+
+ -- creo foglio per nesting
+ EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, NEST.KERF, 1, RawParts[nIndex].Qty - nTotSheetWithDefects) -- EgtAutoNestAddSheet( SheetId, OutlineId, dKerf, nPriority, nCount)
+ end
+end
+
+
+
+local function AddParts(RawParts, vPartsDoneManually)
+
+ -- cerco la width massima dei grezzi
+ local dRawMaxWidth = - 100
+ for nIndex = 1, #RawParts do
+ if RawParts[nIndex].Width > dRawMaxWidth then
+ dRawMaxWidth = RawParts[nIndex].Width
+ end
+ end
+
+ -- valori correttivi per vincoli StripX e StripY
+ local dStripYCorr = GEO.EPS_SMALL
+ local dStripXCorr = GEO.EPS_SMALL
+ if NEST.CORNER == NST_CORNER.TL or NEST.CORNER == NST_CORNER.TR then
+ dStripYCorr = 0.1 - GEO.EPS_SMALL
+ end
+ if NEST.CORNER == NST_CORNER.BR or NEST.CORNER == NST_CORNER.TR then
+ dStripXCorr = 0.1 - GEO.EPS_SMALL
+ end
+
+ local nTotParts = 0
+ for _ in pairs( PART) do nTotParts = nTotParts + 1 end
+ local nPartIndex = 0
+ -- ciclo su pezzi per aggiungerli al nesting
+ for nPartId, nCount in pairs( PART) do repeat
+
+ -- conto quanti pezzi di questo tipo sono già stati posizionati a mano
+ nManuallyDone = 0
+ for nJ = 1, #vPartsDoneManually do
+ if vPartsDoneManually[nJ] == tonumber( nPartId) then
+ nManuallyDone = nManuallyDone + 1
+ end
+ end
+
+ if nManuallyDone == nCount then
+ -- se tutti posizionati passo al pezzo successivo
+ break
+ else
+ -- posiziono con il nesting solo quelli mancanti
+ nCount = nCount - nManuallyDone
+ end
+
+ nPartIndex = nPartIndex + 1
+
+ -- calcolo bbox pezzo per rotazioni
+ local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
+
+ -- recupero eventuali stati di flip e rotazione dalle info del pezzo
+ local bFlipNest = true
+ local bFlip = false
+ local bRotNest = true
+ local nStepRotNest = 90
+ local nRotate = 0
+
+ -- flip
+ local bManualFlip = EgtGetInfo( nPartId, "MANUALFLIP", 'b')
+ if bManualFlip then
+ bFlipNest = false
+ elseif EgtExistsInfo( nPartId, "NestFlip") then
+ bFlipNest = EgtGetInfo( nPartId, "NestAllowFlip", 'b')
+ bFlip = EgtGetInfo( nPartId, "NestFlip", 'b')
+ end
+
+ -- rotation
+ local bManualRot = EgtGetInfo( nPartId, "MANUALROT", 'b')
+ if bManualRot then
+ bRotNest = false
+ elseif EgtExistsInfo( nPartId, "NestRot") then
+ nStepRotNest = EgtGetInfo( nPartId, "NestStepRot", 'i')
+ nRotate = EgtGetInfo( nPartId, "NestRot", 'i')
+ bRotNest = EgtGetInfo( nPartId, "NestAllowRot", 'b')
+ -- verifico se rotazione è valida (pezzo è contenuto nel grezzo)
+ local bValidRotationInRaw = b3Part:getDimX() < RawParts[1].Len - 2 * NEST.KERF + GEO.EPS_SMALL and b3Part:getDimY() < dRawMaxWidth - 2 * NEST.KERF + GEO.EPS_SMALL
+ if not bValidRotationInRaw then
+ bRotNest = true
+ nStepRotNest = 90
+ end
+ end
+
+ -- aggiungo stato a lista stati del pezzo
+ -- table.insert( PartStates, { PartId = tonumber(nPartId), Flip = bFlip, Rotate = nRotate})
+
+
+-- local bFtDown = false
+-- local vPartProc = WE.CollectFeatures( nPartId, b3Raw)
+-- for nInd = 1, #vPartProc do
+-- if LapJoint.Identify( vPartProc[nInd]) then
+-- local nFacOpt, dMinElev, nFacOpt2, dMinElev2 = WL.GetFaceWithMostAdj( vPartProc[nInd].Id, vPartProc[nInd].PartId)
+-- if nFacOpt >= 0 then
+-- local vtN = EgtSurfTmFacetNormVersor( vPartProc[nInd].Id, nFacOpt, GDB_ID.ROOT)
+-- if vtN:getZ() < -0.09 then
+-- bFtDown = true
+-- break
+-- end
+-- end
+-- end
+-- LapJoint.FlipClassify(vPartProc[nInd])
+-- end
+-- -- ruoto se necessario
+-- if bFtDown then
+-- local b3Solid = EgtGetBBoxGlob(nPartId, GDB_BB.IGNORE_TEXT)
+-- local ptRotCen = b3Solid:getCenter()
+-- EgtRotate( nPartId, ptRotCen, X_AX(), 180, GDB_RT.GLOB)
+-- end
+
+-- -- recupero le feature di lavorazione della parete
+-- local bFtDown = false
+-- local vPartProc = WE.CollectFeatures( nPartId, b3Raw)
+-- for nInd = 1, #vPartProc do
+-- if LapJoint.Identify( vPartProc[nInd]) then
+-- local nFacOpt, dMinElev, nFacOpt2, dMinElev2 = WL.GetFaceWithMostAdj( vPartProc[nInd].Id, vPartProc[nInd].PartId)
+-- if nFacOpt >= 0 then
+-- local vtN = EgtSurfTmFacetNormVersor( vPartProc[nInd].Id, nFacOpt, GDB_ID.ROOT)
+-- if vtN:getZ() < -0.09 then
+-- bFtDown = true
+-- break
+-- end
+-- end
+-- end
+-- end
+-- -- ruoto se necessario
+-- if bFtDown then
+-- local b3Solid = EgtGetBBoxGlob(nPartId, GDB_BB.IGNORE_TEXT)
+-- local ptRotCen = b3Solid:getCenter()
+-- EgtRotate( nPartId, ptRotCen, X_AX(), 180, GDB_RT.GLOB)
+-- end
+
+ -- recupero vecchio contorno se già presente
+ local nOutlineLayer = EgtGetFirstNameInGroup(nPartId, "Outline")
+ local nOldOutline = EgtGetFirstNameInGroup(nOutlineLayer, 'ON_TMP')
+ local nOutline, nCnt
+
+ -- se l'outline non è stato calcolato oppure il pezzo è stato modificato, lo ricalcolo
+ local bPartIsModified = EgtGetInfo( nPartId, "MODIFIEDFORNEST", 'b')
+ if not nOldOutline or bPartIsModified then
+
+ -- elimino il vecchio contorno se pesente
+ while ( nOldOutline) do
+ EgtErase(nOldOutline or GDB_ID.NULL)
+ nOldOutline = EgtGetFirstNameInGroup( nOutlineLayer, 'ON_TMP')
+ end
+
+ -- Recupero o ricalcolo il solido
+ local SolidId = EgtBeamGetSolid( nPartId)
+ if not SolidId or not EgtGetInfo( SolidId, 'VALID') then
+ EgtBeamCalcSolid( nPartId, true)
+ SolidId = EgtBeamGetSolid( nPartId)
+ end
+ nOutline, nCnt = EgtGetSurfTmSilhouette( SolidId, Z_AX(), 10, nOutlineLayer, GDB_RT.GLOB)
+ EgtBeamShowSolid( nPartId, false)
+
+ for nInd = 0, nCnt - 1 do
+ EgtSetName( nOutline + nInd, 'ON_TMP')
+ EgtSetStatus( nOutline + nInd, 0)
+ end
+
+ local nCurrOutline = nOutline
+ if nCnt > 0 then
+ local frSum
+ EgtScale( nOutline, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB)
+ EgtModifyCurveExtrusion( nOutline, Z_AX(), GDB_RT.GLOB)
+
+ -- verifico che la prima curva sia l'unico loop esterno
+ local vCrvRef = EgtCurveArea( nOutline)
+ for nInd = 1, nCnt - 1 do
+ local vCrv = EgtCurveArea( nOutline + nInd)
+ -- se trovo più loop esterni uso come contorno quello del box (quindi forzo nCurrOutline a nil)
+ if abs( vCrv * vCrvRef - 1) < GEO.EPS_SMALL then
+ nCurrOutline = nil
+ for nInd2 = 0, nCnt - 1 do
+ EgtErase( nOutline + nInd2)
+ end
+ nCnt = 1
+ break
+ end
+ end
+
+ --local frSum = EgtSurfFlatRegion(nOutlineLayer, nOutline)
+ --EgtSaveFile("c:\\Temp\\ProvaNesting.nge")
+ -- -- per ogni contorno creo flat region e le sommo
+ -- for nIndex = 0, nCnt - 1 do
+ -- EgtScale( nOutline + nIndex, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB)
+ -- EgtModifyCurveExtrusion( nOutline + nIndex, Z_AX(), GDB_RT.GLOB)
+ -- local frCurr = EgtSurfFlatRegion(nOutlineLayer, nOutline + nIndex)
+ -- if frCurr then
+ -- if frSum then
+ -- EgtSurfFrAdd(frSum, frCurr)
+ -- else
+ -- frSum = frCurr
+ -- end
+ -- end
+ -- EgtErase(frCurr)
+ -- end
+ -- --EgtSaveFile("c:/Temp/ProvaNesting.nge")
+ -- -- calcolo contorno della flat region somma
+ -- nCurrOutline = EgtExtractSurfFrChunkLoops(frSum, 0, nOutlineLayer)
+ -- EgtErase(frSum)
+ -- -- cancello contorni
+ -- for nIndex = 0, nCnt do
+ -- EgtErase(nOutline + nIndex)
+ -- end
+ end
+
+ if nCurrOutline and nCurrOutline ~= GDB_ID.NULL then
+ nOutline = nCurrOutline
+ else
+ -- se non ho trovato contorno, lo recupero dal Box
+ local nBoxLayer = EgtGetFirstNameInGroup(nPartId, "Box")
+ local nBox = EgtGetFirstNameInGroup(nBoxLayer, "Box")
+ local BBox = EgtGetBBoxGlob(nBox, GDB_BB.STANDARD)
+ nOutline = EgtRectangle2P(nOutlineLayer, Point3d( BBox:getMin():getX(), BBox:getMin():getY(), 0), Point3d( BBox:getMax():getX(), BBox:getMax():getY(), 0), GDB_RT.GLOB)
+ EgtOutLog("Impossible creating silhouette for part " .. tostring(nPartId))
+ nCnt = 1
+ end
+ --if nCnt == 0 then
+ -- -- se non ho trovato contorno, lo recupero dal Box
+ -- local nBoxLayer = EgtGetFirstNameInGroup(nPartId, "Box")
+ -- local nBox = EgtGetFirstNameInGroup(nBoxLayer, "Box")
+ -- local BBox = EgtGetBBoxGlob(nBox, GDB_BB.STANDARD)
+ -- nOutline = EgtRectangle2P(nOutlineLayer, Point3d( BBox:getMin():getX(), BBox:getMin():getY(), 0), Point3d( BBox:getMax():getX(), BBox:getMax():getY(), 0), GDB_RT.GLOB)
+ -- EgtOutLog("Impossible creating silhouette for part " .. tostring(nPartId))
+ --else
+ -- --EgtScale( nOutline, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB)
+ -- --EgtModifyCurveExtrusion( nOutline, Z_AX(), GDB_RT.GLOB)
+ -- --EgtSaveFile("c:/Temp/ProvaNesting.nge")
+ -- EgtScale( nOutline, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB)
+ -- EgtModifyCurveExtrusion( nOutline, Z_AX(), GDB_RT.GLOB)
+ -- local frSum = EgtSurfFlatRegion(nOutlineLayer, nOutline)
+ -- EgtSaveFile("c:\\Temp\\ProvaNesting.nge")
+ -- -- per ogni contorno creo flat region e le sommo
+ -- for nIndex = 1, nCnt - 1 do
+ -- EgtScale( nOutline + nIndex, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB)
+ -- EgtModifyCurveExtrusion( nOutline + nIndex, Z_AX(), GDB_RT.GLOB)
+ -- local frCurr = EgtSurfFlatRegion(nOutlineLayer, nOutline + nIndex)
+ -- if frCurr then
+ -- EgtSurfFrAdd(frSum, frCurr)
+ -- end
+ -- end
+ -- -- calcolo contorno della flat region somma
+ -- nOutline = EgtExtractSurfFrChunkLoops(frSum, 0, nOutlineLayer)
+ -- -- cancello contorni successivi
+ -- for nIndex = 1, nCnt do
+ -- EgtErase(nOutline + nIndex)
+ -- end
+ --end
+
+ EgtSetName( nOutline, 'ON_TMP')
+ EgtSetStatus( nOutline, 0)
+
+ else
+ -- altrimenti uso l'outline già calcolato
+ nOutline = nOldOutline
+ -- recupero il valore di nCnt
+ local vOutlinesIds = EgtGetNameInGroup( nOutlineLayer, 'ON_TMP')
+ nCnt = #vOutlinesIds
+ end
+
+
+ --[[ local nOutline
+ local nTrimesh
+ local bFirst = true
+ local bSecond = false
+ local bUseBox = false
+ nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "1-Out")
+ if not nTrimesh then
+ nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "2-Out")
+ end
+ if not nTrimesh then
+ nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "3-Out")
+ end
+ if not nTrimesh then
+ nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "4-Out")
+ end
+ -- se trovato contorno
+ if nTrimesh then
+ -- recupero la curva associata
+ local nAuxId = EgtGetInfo(nTrimesh, "AUXID", 'i')
+ nOutline = nTrimesh + nAuxId
+ -- verifico che il contorno sia verticale
+ local nFacetCount = EgtSurfTmFacetCount(nTrimesh)
+ for nIndex = 0, nFacetCount - 1 do
+ local vtNorm = EgtSurfTmFacetNormVersor(nTrimesh, nIndex, GDB_ID.ROOT)
+ if abs( vtNorm:getZ()) > 10 * GEO.EPS_SMALL then
+ bUseBox = true
+ break
+ end
+ end
+ -- se due compo o una e lati inclinati
+ if bUseBox then
+ -- calcolo box della trimesh
+ local b3Outline = EgtGetBBoxGlob(nTrimesh, GDB_BB.IGNORE_TEXT)
+ local ptP1 = Point3d( b3Outline:getMin():getX(), b3Outline:getMin():getY(), 0)
+ local ptP2 = Point3d( b3Outline:getMax():getX(), b3Outline:getMax():getY(), 0)
+ -- creo outline del box
+ nOutline = EgtRectangle2P(nOutlineLayer, ptP1, ptP2, GDB_RT.GLOB)
+ EgtSetStatus(nOutline, GDB_ST.OFF)
+ end
+ -- altrimenti cerco la regione sopra
+ else
+ -- cancello precedenti contorni calcolati
+ local nOldONId = EgtGetFirstNameInGroup( nOutlineLayer, 'ON_TMP')
+ if nOldONId then
+ EgtErase( nOldONId)
+ end
+ -- cerco la regione sopra
+ local nReg
+ for i = 1, 4 do
+ local sRegName = string.format( '%d-Top', i)
+ nReg = EgtGetFirstNameInGroup( nOutlineLayer, sRegName)
+ if nReg then
+ local vtNorm = EgtSurfFrNormVersor( nReg, GDB_ID.ROOT)
+ if vtNorm:getZ() > 0.99 then break end
+ end
+ end
+ if not nReg then
+ EgtOutLog("Errore: regione superiore non trovata")
+ end
+ -- recupero contorno della regione
+ local OutId, nCnt = EgtExtractSurfFrChunkLoops( nReg, 0, nOutlineLayer)
+ if OutId and nCnt > 1 then
+ for i = 2, nCnt do
+ EgtErase( OutId + i - 1)
+ end
+ end
+ if OutId then
+ EgtSetName( OutId, 'ON_TMP')
+ nOutline = OutId
+ end
+ end
+ ]]--
+
+
+ -- calcolo aree lavorazione
+ local nToolOutlineIds = ComputeToolOutlines( nPartId)
+ if bFlipNest and #nToolOutlineIds > 0 then
+ bFlipNest = false
+ end
+
+ if nOutline then
+ -- aggiungo pezzo al nesting
+ EgtAutoNestAddPart( nPartId, nOutline, bFlipNest, bRotNest, nStepRotNest, 0, nCount)
+ -- EgtAutoNestAddPart( PartId, OutlineId, bCanFlip, bCanRotate, dRotStep, nPriority, nCount)
+ end
+ -- aggiungo finestre
+ for nInd = 1, nCnt - 1 do
+ local tmp1, tmp2, area = EgtCurveArea( nOutline + nInd)
+ if area > WD.NEST_HOLE_MIN_AREA then
+ EgtModifyCurveExtrusion( nOutline + nInd, Z_AX(), GDB_RT.GLOB)
+ EgtAutoNestAddHoleToPart( nPartId, nOutline + nInd)
+ end
+ end
+
+ -- aggiungo aree di lavorazione del pezzo
+ local sInfo = ""
+ for nInd = 1, #nToolOutlineIds do
+ EgtAutoNestAddToolOutlineToPart( nPartId, nToolOutlineIds[nInd])
+ sInfo = sInfo .. tostring(nToolOutlineIds[nInd]) .. ","
+ end
+ -- salvo tra le info del pezzo gli id delle sue aree di lavorazione
+ if sInfo ~= "" then
+ EgtSetInfo( nPartId, "ToolOutlines", sInfo)
+ end
+
+ -- Eventuali vincoli StripX e StripY
+ local bOnEdge = EgtGetInfo(nPartId, "NestOnEdge", 'b')
+ local bOnAngle = EgtGetInfo(nPartId, "NestOnAngle", 'b')
+ if bOnEdge or bOnAngle then
+ local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+
+ -- punto di riferimento sul pezzo
+ local ptRef
+ local dval = 10
+ if ( WD.ORIG_CORNER == 'TL' or WD.ORIG_CORNER == 'TR') then
+ ptRef = Point3d( b3Part:getMax():getX() - b3Part:getDimX() / 2, b3Part:getMax():getY() - dval, 0)
+ else
+ ptRef = Point3d( b3Part:getMin():getX() + b3Part:getDimX() / 2, b3Part:getMin():getY() + dval, 0)
+ end
+
+ -- vincolo StripY
+ local bOnlyOnRefSide = EgtGetInfo( nPartId, "OnlyOnRefSide", 'b')
+ if bOnlyOnRefSide then
+ if WD.ORIG_CORNER == 'BL' or WD.ORIG_CORNER == 'BR' then
+ EgtAutoNestSetStripYconstraintToPart( nPartId, ptRef, NEST.KERF + dval + dStripYCorr, 100000)
+ else
+ EgtAutoNestSetStripYconstraintToPart( nPartId, ptRef, - 1000, dRawMaxWidth + 1000 - ( NEST.KERF + dval - dStripYCorr))
+ end
+ else
+ EgtAutoNestSetStripYconstraintToPart( nPartId, ptRef, NEST.KERF + dval + dStripYCorr, dRawMaxWidth - 2 * ( NEST.KERF + dval))
+ end
+
+ -- se sull'angolo aggiungo anche vincolo StripX
+ if bOnAngle then
+ if WD.ORIG_CORNER == 'TL' or WD.ORIG_CORNER == 'BL' then
+ EgtAutoNestSetStripXconstraintToPart( nPartId, ptRef, NEST.KERF + b3Part:getDimX() / 2 + dStripXCorr, 100000)
+ else
+ EgtAutoNestSetStripXconstraintToPart( nPartId, ptRef, -100, RawParts[1].Len + 100 - NEST.KERF - b3Part:getDimX() / 2 + dStripXCorr)
+ end
+ end
+ end
+
+ -- verifico se anullato nesting
+ if EgtProcessEvents( 100 + ( nPartIndex / nTotParts * 100), 0) == 1 then
+ return false
+ end
+ until true
+ end
+
+ return true
+end
+
+-- Inizializzo contatori errori e avvisi
+local nErrCnt = 0
+local nWarnCnt = 0
+local bOk = true
+NEST.ERR = 0
+
+-- resetto gruppo di lavorazione corrente
+EgtResetCurrMachGroup()
+
+-- inizio nesting automatico
+EgtAutoNestStart()
+
+-- lista dei grezzi
+local RawParts = {}
+-- creo tabella dei grezzi
+for sIndex, dLen in pairs( LEN) do
+ RawParts[tonumber(sIndex)] = { Len = dLen}
+end
+for sIndex, dWidth in pairs( WIDTH) do
+ RawParts[tonumber(sIndex)].Width = dWidth
+end
+for sIndex, nQty in pairs( QTY) do
+ RawParts[tonumber(sIndex)].Qty = nQty
+end
+for sIndex, sMaterial in pairs( MATERIAL) do
+ RawParts[tonumber(sIndex)].Material = sMaterial
+end
+
+--
+local vDoneManually, vPartsDoneManually = ComputeRestrictedZones( RawParts)
+
+-- creo grezzi e li aggiungo al nesting
+AddRawParts(RawParts, vDoneManually)
+
+if not bOk then
+ EgtOutLog("Interruzione nesting")
+ NEST.ERR = 1
+end
+
+-- calcolo rotazioni e flip ed aggiungo pezzi al nesting
+if bOk then
+ bOk = AddParts(RawParts, vPartsDoneManually)
+end
+
+if not bOk then
+ EgtOutLog("Interruzione nesting")
+ NEST.ERR = 1
+end
+
+if bOk then
+ -- aggiungo offset tra pezzi
+ EgtAutoNestSetInterpartGap( NEST.OFFSET)
+
+ -- Impostazione corner di inizio del nesting (NST_CORNER.BL, TL, BR, TR)
+ EgtAutoNestSetStartCorner( NEST.CORNER)
+
+ -- Report dei dati di nesting per debug
+ EgtAutoNestSetReportFile( EgtGetTempDir() .. '\\LastNest.json')
+
+ -- imposto tempo di nesting e lo avvio
+ EgtAutoNestCompute( true, NEST.TIME)
+end
+
+-- Variabili di calcolo
+local nNestedParts, nParts, nSheets, nNestings, dTotFillRatio
+local bNestingOk = bOk
+-- Attesa fine calcolo
+local nTime = 0
+while bNestingOk do
+ bNestingOk, nStat = EgtAutoNestGetComputationStatus()
+ if nStat == 2 or nStat == 3 then
+ nNestedParts, nParts, nSheets, nNestings, dTotFillRatio = EgtAutoNestGetResults()
+ --EgtOutText( string.format( 'Parts : %d/%d Filling : %.2f%%', nNestedParts, nParts, 100 * dTotFillRatio))
+ end
+ if nStat == 3 then break end
+ nTime = nTime + 1
+ if EgtProcessEvents( nTime / NEST.TIME * 100, 995) == 1 then
+ bNestingOk = EgtAutoNestCancelComputation()
+ bOk = false
+ EgtOutLog("Interruzione nesting")
+ NEST.ERR = 1
+ break
+ end
+end
+
+
+local dXCorr = 0
+local dYCorr = 0
+if NEST.CORNER == NST_CORNER.TL then
+ dYCorr = - 0.1
+elseif NEST.CORNER == NST_CORNER.TR then
+ dYCorr = - 0.1
+ dXCorr = - 0.1
+elseif NEST.CORNER == NST_CORNER.BR then
+ dXCorr = - 0.1
+end
+
+
+-- se nesting andato bene
+if bNestingOk then
+
+ -- disposizione sheet e parts
+ local SheetId = GDB_ID.NULL
+ local vtAdd = V_NULL()
+ local MachGroupList = {}
+ local nPartCount = 0
+ local Sheet = {PartList = {}}
+ local bFirstSheet = true
+ for i = 0, 999 do
+ local nType, nId, nFlag, dX, dY, dAngRot = EgtAutoNestGetOneResult( i)
+ if not nType then break end
+ -- se sheet
+ if nType > 0 then
+ MachGroupList = {}
+ for MGIndex = 1, nType do
+ -- creo gruppo di lavorazione
+ local MachGroupName = NewMachGroupName()
+ local nMachGroup = EgtAddMachGroup(MachGroupName, sCurrMachName)
+ table.insert( MachGroupList, { MGId = nMachGroup})
+ for nIndex = 1, #RawParts do
+ for nInd2 = 1, #(RawParts[nIndex].PartId) do
+ if RawParts[nIndex].PartId[nInd2] == nId then
+ EgtSetInfo(nMachGroup, "PANELLEN", RawParts[nIndex].Len)
+ EgtSetInfo(nMachGroup, "PANELWIDTH", RawParts[nIndex].Width)
+ EgtSetInfo(nMachGroup, "MATERIAL", NEST.MATERIAL)
+ EgtSetInfo(nMachGroup, "AUTONEST", 1)
+ -- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
+ EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
+ EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
+ end
+ end
+ end
+
+ -- aggiungo pezzi nestati a mano
+ nPartCount = 0
+ for nInd = 1, #vDoneManually do
+ if vDoneManually[nInd].SheetId == nId then
+ vDoneManually[nInd].Done = 1
+ for nInd2 = 1, #(vDoneManually[nInd].Parts) do
+ nPartCount = nPartCount + 1
+ local nPartDuploId = EgtDuploNew( vDoneManually[nInd].Parts[nInd2].Id)
+
+ -- aggiungo le curve corrispondenti alle aree di lavorazione del pezzo
+ local sToolOutlines = EgtGetInfo( vDoneManually[nInd].Parts[nInd2].Id, "ToolOutlines", 's')
+ if sToolOutlines then
+ -- recupero o creo il gruppo per gli outlines
+ local nToolOutlinesGrp = EgtGetFirstNameInGroup( nPartDuploId, "ToolOutlines")
+ if not nToolOutlinesGrp then
+ nToolOutlinesGrp = EgtGroup( nPartDuploId)
+ EgtSetName( nToolOutlinesGrp, "ToolOutlines")
+ EgtSetStatus( nToolOutlinesGrp, GDB_ST.ON)
+ end
+
+ for str in string.gmatch(sToolOutlines, "([^"..",".."]+)") do
+ EgtCopyGlob( tonumber(str), nToolOutlinesGrp)
+ end
+ end
+
+ -- applico flip, rotazione e traslazione pezzo e box da nesting
+ EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posX, 3) .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posY, 3) .. "," .. 0 .."," .. 0)
+ EgtSetInfo( nPartDuploId, "POSX", vDoneManually[nInd].Parts[nInd2].posX)
+ EgtSetInfo( nPartDuploId, "POSY", vDoneManually[nInd].Parts[nInd2].posY)
+ end
+ end
+ end
+
+
+ end
+
+ -- altrimenti pezzo
+ else
+ nPartCount = nPartCount + 1
+ for MGIndex = 1, #MachGroupList do
+ local nMachGroup = MachGroupList[MGIndex].MGId
+ --EgtSetCurrMachGroup(nMachGroup)
+ -- se c'e' un grezzo valido
+ if nMachGroup and nMachGroup ~= GDB_ID.NULL then
+ -- creo pezzo copia
+ local nPartDuploId = EgtDuploNew( nId)
+ -- applico flip e rotazioni fatte durante verifica posizionamento pezzo
+ -- local b3Part = EgtGetBBoxGlob( nPartDuploId, GDB_BB.STANDARD)
+ local nPartInd
+ -- for nInd = 1, #PartStates do
+ -- if PartStates[nInd].PartId == nId then
+ -- -- if PartStates[nInd].Flip then
+ -- -- EgtRotate( nPartDuploId, b3Part:getCenter(), X_AX(), 180, GDB_RT.GLOB)
+ -- -- end
+ -- -- if PartStates[nInd].Rotate and PartStates[nInd].Rotate > 0 then
+ -- -- EgtRotate( nPartDuploId, b3Part:getCenter(), Z_AX(), PartStates[nInd].Rotate, GDB_RT.GLOB)
+ -- -- end
+ -- nPartInd = nInd
+ -- end
+ -- end
+
+
+
+ -- aggiungo le curve corrispondenti alle aree di lavorazione del pezzo
+ local sToolOutlines = EgtGetInfo( nId, "ToolOutlines", 's')
+ if sToolOutlines then
+ -- recupero o creo il gruppo per gli outlines
+ local nToolOutlinesGrp = EgtGetFirstNameInGroup( nPartDuploId, "ToolOutlines")
+ if not nToolOutlinesGrp then
+ nToolOutlinesGrp = EgtGroup( nPartDuploId)
+ EgtSetName( nToolOutlinesGrp, "ToolOutlines")
+ EgtSetStatus( nToolOutlinesGrp, GDB_ST.ON)
+ end
+
+ for str in string.gmatch(sToolOutlines, "([^"..",".."]+)") do
+ EgtCopyGlob( tonumber(str), nToolOutlinesGrp)
+ end
+ end
+
+ -- applico flip, rotazione e traslazione pezzo e box da nesting
+ if nFlag == 1 then
+ EgtRotate( nPartDuploId, ORIG(), X_AX(), 180, GDB_RT.GLOB)
+ end
+ EgtRotate( nPartDuploId, ORIG(), Z_AX(), dAngRot, GDB_RT.GLOB)
+ EgtMove( nPartDuploId, Vector3d( dX, dY, 0), GDB_RT.GLOB)
+
+ local nBoxLayerId = EgtGetFirstNameInGroup( nPartDuploId, "Box")
+ local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
+ local PartBBox = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
+ local ptPos = Point3d( PartBBox:getMin():getX(), PartBBox:getMin():getY(), 0)
+ EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( ptPos:getX() + dXCorr, 3) .. "," .. EgtNumToString( ptPos:getY() + dYCorr, 3) .. "," .. 0 .."," .. 0)
+ EgtSetInfo( nPartDuploId, "POSX", ptPos:getX() + dXCorr)
+ EgtSetInfo( nPartDuploId, "POSY", ptPos:getY() + dYCorr)
+
+ local nPartRot = EgtGetInfo( nId, "ROTATED", 'i') or 0
+ local nTotRot = dAngRot + nPartRot
+ nTotRot = EgtIf( nTotRot < 360, nTotRot, nTotRot - 360)
+ EgtSetInfo( nPartDuploId, "ROT", nTotRot)
+
+ local nPartFlip = EgtGetInfo( nId, "INVERTED", 'i')
+ nPartFlip = EgtIf( nPartFlip == 180, 1, 0)
+ local nTotFlip = EgtIf( nPartFlip ~ nFlag, 180, 0)
+ EgtSetInfo( nPartDuploId, "FLIP", nTotFlip)
+
+ end
+ end
+ end
+ end
+
+ -- creo gruppi di lavorazione per fogli con pezzi nestati solo a mano
+ for nInd = 1, #vDoneManually do
+ if vDoneManually[nInd].Done == 0 then
+ -- creo gruppo di lavorazione
+ local MachGroupName = NewMachGroupName()
+ local nMachGroup = EgtAddMachGroup(MachGroupName, sCurrMachName)
+ table.insert( MachGroupList, { MGId = nMachGroup})
+ for nIndex = 1, #RawParts do
+ for nInd2 = 1, #(RawParts[nIndex].PartId) do
+ if RawParts[nIndex].PartId[nInd2] == vDoneManually[nInd].SheetId then
+ EgtSetInfo(nMachGroup, "PANELLEN", RawParts[nIndex].Len)
+ EgtSetInfo(nMachGroup, "PANELWIDTH", RawParts[nIndex].Width)
+ EgtSetInfo(nMachGroup, "MATERIAL", NEST.MATERIAL)
+ EgtSetInfo(nMachGroup, "AUTONEST", 1)
+ -- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
+ EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
+ EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
+ end
+ end
+ end
+
+ -- aggiungo pezzi nestati a mano
+ nPartCount = 0
+ for nInd2 = 1, #(vDoneManually[nInd].Parts) do
+ nPartCount = nPartCount + 1
+ local nPartDuploId = EgtDuploNew( vDoneManually[nInd].Parts[nInd2].Id)
+
+ -- aggiungo le curve corrispondenti alle aree di lavorazione del pezzo
+ local sToolOutlines = EgtGetInfo( vDoneManually[nInd].Parts[nInd2].Id, "ToolOutlines", 's')
+ if sToolOutlines then
+ -- recupero o creo il gruppo per gli outlines
+ local nToolOutlinesGrp = EgtGetFirstNameInGroup( nPartDuploId, "ToolOutlines")
+ if not nToolOutlinesGrp then
+ nToolOutlinesGrp = EgtGroup( nPartDuploId)
+ EgtSetName( nToolOutlinesGrp, "ToolOutlines")
+ EgtSetStatus( nToolOutlinesGrp, GDB_ST.ON)
+ end
+
+ for str in string.gmatch(sToolOutlines, "([^"..",".."]+)") do
+ EgtCopyGlob( tonumber(str), nToolOutlinesGrp)
+ end
+ end
+
+ -- applico flip, rotazione e traslazione pezzo e box da nesting
+ EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posX, 3) .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posY, 3) .. "," .. 0 .."," .. 0)
+ EgtSetInfo( nPartDuploId, "POSX", vDoneManually[nInd].Parts[nInd2].posX)
+ EgtSetInfo( nPartDuploId, "POSY", vDoneManually[nInd].Parts[nInd2].posY)
+ end
+ end
+ end
+
+
+ -- creo grezzi per ogni gruppo di lavorazione
+ local MachGroupToTCnt = EgtGetMachGroupCount()
+ local MachGroupIndex = 0
+ _G.WALL = {}
+ WALL.FILE = NEST.FILE
+ WALL.MACHINE = NEST.MACHINE
+ WALL.FLAG = 6 -- CREATE_PANEL
+ WALL.NESTING_REF = 'BL'
+ nMachGroup = EgtGetFirstMachGroup()
+ while nMachGroup do
+ EgtSetCurrMachGroup( nMachGroup)
+ if EgtGetInfo( nMachGroup, "AUTONEST",'i') == 1 then
+ MachGroupIndex = MachGroupIndex + 1
+ EgtRemoveInfo( nMachGroup, "AUTONEST")
+ EgtSetInfo( nMachGroup, "UPDATEUI", 1)
+ dofile( EgtGetSourceDir() .. "BatchProcessNew.lua")
+ -- aggiorno interfaccia
+ EgtProcessEvents( 200 + ( MachGroupIndex / MachGroupToTCnt * 100), 0)
+ end
+
+ -- ciclo sui duplo per sistemare Q
+ local nRawPartId = EgtGetFirstRawPart()
+ -- recupero box grezzo ridotto della tolleranza
+ local b3Raw = EgtGetRawPartBBox( nRawPartId)
+ b3Raw:expand( - WD.INSIDE_RAW_TOL)
+ EgtOutLog( 'RawBox='..tostring( b3Raw))
+
+ local nPartDuploId = EgtGetFirstPartInRawPart( nRawPartId)
+ while nPartDuploId do
+ local vPartProc = WE.CollectFeatures( nPartDuploId)
+ for ProcIndex = 1, #vPartProc do
+ local Proc = vPartProc[ProcIndex]
+
+ if LapJoint.Identify( Proc) then
+ -- cerco la faccia rivolta verso l'alto e la faccia rivolta verso il basso
+ local nFaceInd = -1
+ local nFaceDownInd = -1
+ for nIdx = 0, Proc.Fct - 1 do
+ local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
+ if vtN:getZ() > 0.95 then
+ nFaceInd = nIdx
+ elseif vtN:getZ() < - 0.95 then
+ nFaceDownInd = nIdx
+ end
+ end
+ -- se è lap joint dall'alto
+ if nFaceInd ~= -1 and nFaceDownInd == -1 then
+ local ptCen = EgtSurfTmFacetCenter( Proc.Id, nFaceInd, GDB_ID.ROOT)
+ -- se all'interno rimuovo info Q
+ if EnclosesPointXY( b3Raw, ptCen) then
+ -- resetto parametro Q
+ if Proc.Prc == 30 then
+ EgtRemoveInfo( Proc.Id, "Q08")
+ EgtRemoveInfo( Proc.Id, "Q08A")
+ else
+ EgtRemoveInfo( Proc.Id, "Q03")
+ EgtRemoveInfo( Proc.Id, "Q03A")
+ end
+ end
+ end
+
+ elseif DoubleCut.Identify( Proc) then
+ -- verifico se due facce e rivolto verso l'alto
+ if Proc.Fct == 2 then
+ local vtN = {}
+ vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
+ vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
+
+ if ( vtN[1]:getZ() >= 0.95 or vtN[2]:getZ() >= 0.95) then
+ local nFaceInd = EgtIf( vtN[1]:getZ() >= 0.95, 0, 1)
+ local ptCen = EgtSurfTmFacetCenter( Proc.Id, nFaceInd, GDB_ID.ROOT)
+ -- se all'interno rimuovo info Q
+ if EnclosesPointXY( b3Raw, ptCen) then
+ -- resetto parametro Q
+ if Proc.Prc == 12 then
+ EgtRemoveInfo( Proc.Id, "Q02")
+ EgtRemoveInfo( Proc.Id, "Q02A")
+ end
+ end
+ end
+ end
+ end
+ end
+ nPartDuploId = EgtGetNextPartInRawPart(nPartDuploId)
+ end
+ nMachGroup = EgtGetNextMachGroup(nMachGroup)
+ end
+
+else
+ EgtOutLog("Errore: nesting fallito")
+ NEST.ERR = 2
+end
+
+EgtResetCurrMachGroup()
+
+ -- cancello rettangolo del materiale per nesting
+for RawPartId = 1, #RawParts do
+ EgtErase(RawParts[RawPartId].PartId)
+end
+
+local nOutlineGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "ToolOutlines")
+if nOutlineGrp and nOutlineGrp ~= GDB_ID.NULL then EgtErase( nOutlineGrp) end
+local nSheetDefectsGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "SheetDefects")
+if nSheetDefectsGrp and nSheetDefectsGrp ~= GDB_ID.NULL then EgtErase( nSheetDefectsGrp) end
+
+-- EgtSaveFile( "C:\\EgtData\\EgtBEAMWALL\\Temp\\file.nge")
+
+EgtOutLog( ' +++ NestProcess completed')
diff --git a/ProgettoRestylingWall/Wall/Overturn.lua b/ProgettoRestylingWall/Wall/Overturn.lua
new file mode 100644
index 0000000..7edac61
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/Overturn.lua
@@ -0,0 +1,32 @@
+-- Rotate.lua by Egaltech s.r.l. 2020/04/06
+-- Gestione ribaltamento di una Parete
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+
+-- recupero il pezzo del primo oggetto selezionato
+local nId = EgtGetFirstSelectedObj()
+local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL)
+if not nPartId or not EgtIsPart( nPartId) then
+ EgtOutBox( 'Nessuna parete selezionata', 'Overturn Parete', 'ERROR')
+ return
+end
+
+-- recupero il box del pezzo
+local Ls = EgtGetFirstNameInGroup( nPartId, 'Box')
+local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+if not b3Solid then
+ local sName = EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId))
+ EgtOutBox( 'Box non definito per la parete ' .. sName, 'Overturn Parete', 'ERROR')
+ return
+end
+
+-- eseguo rotazione di 180 gradi attorno asse X
+local ptRot = b3Solid:getMin() + Vector3d( 0, b3Solid:getDimY() / 2, b3Solid:getDimZ() / 2)
+EgtRotate( nPartId, ptRot, X_AX(), 180, GDB_RT.GLOB)
+EgtDraw()
+
+-- end
\ No newline at end of file
diff --git a/ProgettoRestylingWall/Wall/Process.lua b/ProgettoRestylingWall/Wall/Process.lua
new file mode 100644
index 0000000..c4ad254
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/Process.lua
@@ -0,0 +1,309 @@
+-- Process.lua by Egaltech s.r.l. 2021/07/27
+-- Gestione calcolo disposizione e lavorazioni per Pareti
+-- Si opera sulla macchina corrente
+-- 2020/12/09 Come per BatchProcess.lua si gestiscono anche rotazioni di inversione con valori negativi.
+-- 2021/10/27 Come per BatchProcess.lua nel controllo spessore si deve considerare anche PosY.
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+-- Imposto direttorio libreria specializzata per Travi
+local sBaseDir = EgtGetSourceDir()
+EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua')
+
+-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Pareti
+local sMachDir = EgtGetCurrMachineDir()
+if not sMachDir then
+ EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Pareti', 'ERROR')
+ return
+end
+if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then
+ EgtOutBox( 'La macchina corrente non è configurata per lavorare pareti', 'Lavora Pareti', 'ERROR')
+ return
+end
+
+-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
+EgtRemoveBaseMachineDirFromPackagePath()
+EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua')
+
+-- Segnalazione avvio
+EgtOutLog( '*** Wall Process Start ***', 1)
+
+-- Carico le librerie
+_G.package.loaded.WallExec = nil
+local WE = require( 'WallExec')
+local WL = require( 'WallLib')
+
+-- Carico i dati globali
+local WD = require( 'WallData')
+
+-- Variabili di modulo
+local vWall = {}
+local dRawH
+
+-------------------------------------------------------------------------------------------------------------
+-- *** Recupero le pareti selezionate ***
+-------------------------------------------------------------------------------------------------------------
+local function MyProcessInputData()
+
+ -- Recupero le travi selezionate
+ local nId = EgtGetFirstSelectedObj()
+ while nId do
+ local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL)
+ if nPartId then
+ local bFound = false
+ for i = 1, #vWall do
+ if vWall[i].Id == nPartId then
+ bFound = true
+ break
+ end
+ end
+ if not bFound then
+ table.insert( vWall, { Id = nPartId, Name = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
+ end
+ end
+ nId = EgtGetNextSelectedObj()
+ end
+ if #vWall == 0 then
+ EgtOutBox( 'Non sono state selezionate pareti', 'Lavora Pareti', 'ERROR')
+ return false
+ else
+ local sOut = ''
+ for i = 1, #vWall do
+ sOut = sOut .. vWall[i].Name .. ', '
+ end
+ sOut = sOut:sub( 1, -3)
+ EgtOutLog( 'Pareti selezionate : ' .. sOut, 1)
+ end
+
+ -- Ne recupero le dimensioni
+ for i = 1, #vWall do
+ local Ls = EgtGetFirstNameInGroup( vWall[i].Id, 'Box')
+ local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+ if not b3Solid then
+ EgtOutBox( 'Box non definito per la parete ' .. vWall[i].Name, 'Lavora Pareti', 'ERROR')
+ return false
+ else
+ vWall[i].Box = b3Solid
+ end
+ end
+
+ -- Ne recupero la posizione
+ local CurrX = 50
+ for i = 1, #vWall do
+ local PosX = EgtGetInfo( vWall[i].Id, 'POSX', 'd') or CurrX
+ vWall[i].PosX = PosX
+ CurrX = CurrX + vWall[i].Box:getDimX() + 50
+ if WD.USE_POSY then
+ local PosY = EgtGetInfo( vWall[i].Id, 'POSY', 'd') or 0
+ vWall[i].PosY = max( PosY, 0)
+ else
+ vWall[i].PosY = 0
+ end
+ local PosZ = EgtGetInfo( vWall[i].Id, 'POSZ', 'd') or 50
+ vWall[i].PosZ = PosZ
+ end
+
+ -- Recupero informazione se progetto o produzione
+ local bProj = ( EgtGetInfo( EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL, 'PROJECT', 'i') == 1)
+
+ -- Eseguo eventuali rotazioni e inversioni testa-coda
+ for i = 1, #vWall do
+ local b3Solid = vWall[i].Box
+ -- rotazione
+ local dRotAng = EgtGetInfo( vWall[i].Id, 'ROTATED', 'd')
+ if dRotAng then
+ if abs( dRotAng) > GEO.EPS_ANG_SMALL and not EgtExistsInfo( vWall[i].Id, 'ROTATED_DONE') then
+ local ptRotCen = b3Solid:getCenter()
+ EgtRotate( vWall[i].Id, ptRotCen, X_AX(), dRotAng, GDB_RT.GLOB)
+ b3Solid:rotate( ptRotCen, X_AX(), dRotAng)
+ end
+ EgtSetInfo( vWall[i].Id, 'ROTATED_DONE', dRotAng)
+ end
+ -- inversione
+ local dInvAng = EgtGetInfo( vWall[i].Id, 'INVERTED', 'd')
+ if dInvAng then
+ if abs( dInvAng - 180) > GEO.EPS_ANG_SMALL and abs( dInvAng + 180) > GEO.EPS_ANG_SMALL and not EgtExistsInfo( vWall[i].Id, 'INVERTED_DONE') then
+ local ptInvCen = b3Solid:getCenter()
+ EgtRotate( vWall[i].Id, ptInvCen, Z_AX(), dInvAng - 180, GDB_RT.GLOB)
+ b3Solid:rotate( ptInvCen, Z_AX(), dInvAng - 180)
+ end
+ EgtSetInfo( vWall[i].Id, 'INVERTED_DONE', dInvAng)
+ end
+ -- correzioni per rotazioni non centrate di produzioni TS3 (quasi sempre multipli di 90 deg)
+ local sType = EgtGetInfo( vWall[i].Id, 'TYPE', 's')
+ if not bProj and dRotAng and dInvAng and sType ~= 'LAYER' then
+ if abs( dInvAng - 0) < GEO.EPS_ANG_SMALL then
+ if abs( dRotAng - 180) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ elseif abs( dRotAng - 270) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ end
+ elseif abs( dInvAng - 90) < GEO.EPS_ANG_SMALL or abs( dInvAng + 270) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ if abs( dRotAng - 180) < GEO.EPS_ANG_SMALL or abs( dRotAng + 180) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ elseif abs( dRotAng - 270) < GEO.EPS_ANG_SMALL or abs( dRotAng + 90) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ end
+ elseif abs( dInvAng - 180) < GEO.EPS_ANG_SMALL or abs( dInvAng + 180) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ if abs( dRotAng - 0) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ elseif abs( dRotAng - 270) < GEO.EPS_ANG_SMALL or abs( dRotAng + 90) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ elseif abs( dRotAng - 90) < GEO.EPS_ANG_SMALL or abs( dRotAng + 270) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosZ = vWall[i].PosZ - vWall[i].Box:getDimY()
+ end
+ elseif abs( dInvAng - 270) < GEO.EPS_ANG_SMALL or abs( dInvAng + 90) < GEO.EPS_ANG_SMALL then
+ if abs( dRotAng - 0) < GEO.EPS_ANG_SMALL then
+ vWall[i].PosX = vWall[i].PosX - vWall[i].Box:getDimX()
+ end
+ end
+ end
+ end
+
+ -- Ne verifico le dimensioni
+ dRawH = vWall[1].Box:getDimZ() + vWall[1].PosY
+ local vWallErr = {}
+ for i = 2, #vWall do
+ local dDimH = vWall[i].Box:getDimZ() + vWall[i].PosY
+ if abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL then
+ table.insert( vWallErr, i)
+ end
+ end
+ if #vWallErr > 0 then
+ local sOut = 'Rimosse pareti con spessore diverso dalla prima :\n'
+ for i = #vWallErr, 1, -1 do
+ sOut = sOut .. vWall[vWallErr[i]].Name .. '\n'
+ EgtDeselectPartObjs( vWall[vWallErr[i]].Id)
+ table.remove( vWall, vWallErr[i])
+ end
+ EgtOutLog( sOut, 1)
+ EgtOutBox( sOut, 'Lavora Pareti', 'INFO')
+ EgtDraw()
+ return false
+ end
+ EgtDeselectAll()
+
+ return true
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- *** Inserimento delle pareti nel grezzo ***
+-------------------------------------------------------------------------------------------------------------
+local function MyProcessWalls()
+
+ -- Ingombro totale delle pareti
+ local b3Tot = BBox3d( ORIG())
+ for i = 1, #vWall do
+ local ptMin = Point3d( - vWall[i].PosX - vWall[i].Box:getDimX(), vWall[i].PosZ, 0)
+ local ptMax = Point3d( - vWall[i].PosX, vWall[i].PosZ + vWall[i].Box:getDimY(), 0)
+ b3Tot:Add( ptMin)
+ b3Tot:Add( ptMax)
+ end
+ local dBoxL = b3Tot:getDimX()
+ local dBoxW = b3Tot:getDimY()
+ EgtOutLog( 'Ltot : ' .. EgtNumToString( dBoxL, 1) .. ' Wtot : '.. EgtNumToString( dBoxW, 1), 1)
+
+ -- Eventuali dimensioni predefinite del pannello
+ local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
+ local dPanelLen = EgtGetInfo( BtlInfoId, 'PANELLEN', 'd') or WD.STD_RAW_LENGTH
+ local dPanelWidth = EgtGetInfo( BtlInfoId, 'PANELWIDTH', 'd') or WD.STD_RAW_WIDTH
+
+ -- Richiedo lunghezza del grezzo e sovramateriale di testa
+ local vsVal = EgtDialogBox( 'Lavora Pareti' .. ' (Ltot='.. EgtNumToString( dBoxL + 0.05, 1) .. ', Wtot=' .. EgtNumToString( dBoxW + 0.05, 1) .. ')',
+ {'Lunghezza grezzo', EgtNumToString( dPanelLen, 1)},
+ {'Larghezza grezzo', EgtNumToString( dPanelWidth, 1)})
+ if not vsVal then
+ EgtDraw()
+ return
+ end
+ local dRawL = EgtEvalNumExpr( vsVal[1])
+ if not dRawL then
+ local sOut = 'Lunghezza grezzo errata : ' .. vsVal[1]
+ EgtOutLog( sOut)
+ EgtOutBox( sOut, 'Lavora Pareti', 'WARNING')
+ EgtDraw()
+ return false
+ end
+ dRawL = min( dRawL, WD.MAX_LENGTH)
+ local dRawW = EgtEvalNumExpr( vsVal[2])
+ if not dRawW then
+ local sOut = 'Larghezza grezzo errata : ' .. vsVal[2]
+ EgtOutLog( sOut)
+ EgtOutBox( sOut, 'Lavora Pareti', 'WARNING')
+ EgtDraw()
+ return false
+ end
+ dRawW = min( dRawW, WD.MAX_WIDTH )
+
+ -- Verifico dimensioni massime grezzo
+ if dRawL > WD.MAX_LENGTH + 10 * GEO.EPS_SMALL or dRawW > WD.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > WD.MAX_HEIGHT + 10 * GEO.EPS_SMALL then
+ local sOut = 'Grezzo (' .. EgtNumToString( dRawL, 2) .. ' x ' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
+ 'oltre il limite della macchina ('..EgtNumToString( WD.MAX_LENGTH, 2)..' x '..EgtNumToString( WD.MAX_WIDTH, 2)..' x '..EgtNumToString( WD.MAX_HEIGHT, 2)..') '
+ EgtOutLog( sOut)
+ EgtOutBox( sOut, 'Lavora Pareti', 'WARNING')
+ EgtDraw()
+ return false
+ end
+
+ -- Verifico dimensioni minime del grezzo
+ if dRawL < WD.MIN_LENGTH - 10 * GEO.EPS_SMALL or dRawW < WD.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < WD.MIN_HEIGHT - 10 * GEO.EPS_SMALL then
+ local sOut = 'Grezzo (' .. EgtNumToString( dRawL, 2) .. ' x ' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
+ 'sotto il limite della macchina ('..EgtNumToString( WD.MIN_LENGTH, 2)..' x '..EgtNumToString( WD.MIN_WIDTH, 2)..' x '..EgtNumToString( WD.MIN_HEIGHT, 2)..')'
+ EgtOutLog( sOut)
+ EgtOutBox( sOut, 'Lavora Pareti', 'WARNING')
+ EgtDraw()
+ return false
+ end
+
+ -- Sistemo le pareti nel grezzo
+ return WE.ProcessWalls( dRawL, dRawW, dRawH, vWall)
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- *** Inserimento delle lavorazioni nelle travi ***
+-------------------------------------------------------------------------------------------------------------
+local function MyProcessFeatures()
+
+ local bOk, Stats = WE.ProcessFeatures()
+ local nErrCnt = 0
+ local nWarnCnt = 0
+ local sOutput = ''
+ for i = 1, #Stats do
+ if Stats[i].Err > 0 then
+ nErrCnt = nErrCnt + 1
+ sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, Stats[i].Msg)
+ elseif Stats[i].Err < 0 then
+ nWarnCnt = nWarnCnt + 1
+ sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, Stats[i].Msg)
+ end
+ end
+ if #sOutput > 0 then EgtOutLog( sOutput) end
+ if nErrCnt > 0 then
+ EgtOutBox( sOutput, 'Lavora Pareti', 'ERRORS')
+ EgtDraw()
+ return false
+ elseif nWarnCnt > 0 then
+ EgtOutBox( sOutput, 'Lavora Pareti', 'WARNINGS')
+ EgtDraw()
+ return true
+ end
+
+ return true
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- *** Esecuzione ***
+-------------------------------------------------------------------------------------------------------------
+if not MyProcessInputData() then return end
+
+if not MyProcessWalls() then return end
+
+-- Abilito Vmill
+EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
+
+if not MyProcessFeatures() then return end
diff --git a/ProgettoRestylingWall/Wall/Rotate.lua b/ProgettoRestylingWall/Wall/Rotate.lua
new file mode 100644
index 0000000..e12c7af
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/Rotate.lua
@@ -0,0 +1,31 @@
+-- Swap.lua by Egaltech s.r.l. 2020/04/06
+-- Gestione rotazione nel piano di una Parete
+
+-- Intestazioni
+require( 'EgtBase')
+_ENV = EgtProtectGlobal()
+EgtEnableDebug( false)
+
+
+-- recupero il pezzo del primo oggetto selezionato
+local nId = EgtGetFirstSelectedObj()
+local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL)
+if not nPartId or not EgtIsPart( nPartId) then
+ EgtOutBox( 'Nessuna parete selezionata', 'Rotate Parete', 'ERROR')
+ return
+end
+
+-- recupero il box del pezzo
+local Ls = EgtGetFirstNameInGroup( nPartId, 'Box')
+local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
+if not b3Solid then
+ local sName = EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId))
+ EgtOutBox( 'Box non definito per la parete ' .. sName, 'Rotate Parete', 'ERROR')
+ return
+end
+
+-- eseguo rotazione di 90 gradi attorno asse Z
+EgtRotate( nPartId, b3Solid:getCenter(), Z_AX(), 90, GDB_RT.GLOB)
+EgtDraw()
+
+-- end
\ No newline at end of file
diff --git a/ProgettoRestylingWall/Wall/Wall.ini b/ProgettoRestylingWall/Wall/Wall.ini
new file mode 100644
index 0000000..6b018dd
--- /dev/null
+++ b/ProgettoRestylingWall/Wall/Wall.ini
@@ -0,0 +1,8 @@
+[Wall]
+BtlEnable=1
+BaseDir=C:\EgtData\Wall
+BtlExec=BatchProcess.lua
+Button1=Process.lua,Images\Process.png,Lavora Pareti
+Button2=Rotate.lua,Images\Rotate.png,Ruota Parete
+Button3=Overturn.lua,Images\Overturn.png,Ribalta Parete
+Button4=WallMachinings,Images\WallMachinings.png,Lista lavorazioni
diff --git a/ProgettoRestylingWall/btl_v105.pdf b/ProgettoRestylingWall/btl_v105.pdf
new file mode 100644
index 0000000..bb56514
Binary files /dev/null and b/ProgettoRestylingWall/btl_v105.pdf differ
diff --git a/ProgettoRestylingWall/btl_v106.pdf b/ProgettoRestylingWall/btl_v106.pdf
new file mode 100644
index 0000000..cd6c379
--- /dev/null
+++ b/ProgettoRestylingWall/btl_v106.pdf
@@ -0,0 +1,11816 @@
+%PDF-1.4
+%
+1 0 obj
+<<
+/ModDate (D:20220504113015+02'00')
+/Producer (PDF-XChange 4.0.209.0 [Lite] \(Windows \(Build 9200\)\))
+/CreationDate (D:20190716093112+02'00')
+/PXCViewerInfo (PDF-XChange Viewer;2.5.214.2;Feb 17 2014;20:31:41;D:20220504113015+02'00')
+>>
+endobj
+2 0 obj
+<<
+/Type /Catalog
+/Pages 3 0 R
+/Metadata 4 0 R
+/Outlines 5 0 R
+/PageMode /UseNone
+/PageLayout /SinglePage
+/ViewerPreferences <<
+/DisplayDocTitle true
+>>
+>>
+endobj
+3 0 obj
+<<
+/Kids [6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R
+22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R
+38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R
+54 0 R 55 0 R 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R
+70 0 R 71 0 R 72 0 R 73 0 R 74 0 R 75 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R
+86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R
+102 0 R 103 0 R 104 0 R 105 0 R 106 0 R 107 0 R 108 0 R 109 0 R 110 0 R 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R
+118 0 R 119 0 R 120 0 R 121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R 127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R 133 0 R
+134 0 R 135 0 R 136 0 R 137 0 R 138 0 R 139 0 R 140 0 R 141 0 R]
+/Type /Pages
+/Count 136
+>>
+endobj
+4 0 obj
+<<
+/Type /Metadata
+/Length 2827
+/Subtype /XML
+>>
+stream
+
+
+
+
+ 2019-07-16T09:31:12+02:00
+ 2022-05-04T11:30:15+02:00
+
+
+ PDF-XChange 4.0.209.0 [Lite] (Windows (Build 9200))
+
+
+ application/pdf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endstream
+endobj
+5 0 obj
+<<
+/Last 142 0 R
+/Count 26
+/First 143 0 R
+>>
+endobj
+6 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [144 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+7 0 obj
+<<
+/Type /Page
+/Annots [146 0 R 147 0 R]
+/Parent 3 0 R
+/Contents [148 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+8 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [149 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+9 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [150 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+10 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [151 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+11 0 obj
+<<
+/Type /Page
+/Annots [152 0 R 153 0 R 154 0 R 155 0 R]
+/Parent 3 0 R
+/Contents [156 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+12 0 obj
+<<
+/Type /Page
+/Annots [157 0 R 158 0 R 159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R]
+/Parent 3 0 R
+/Contents [165 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+13 0 obj
+<<
+/Type /Page
+/Annots [166 0 R 167 0 R 168 0 R]
+/Parent 3 0 R
+/Contents [169 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+14 0 obj
+<<
+/Type /Page
+/Annots [170 0 R]
+/Parent 3 0 R
+/Contents [171 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+15 0 obj
+<<
+/Type /Page
+/Annots [172 0 R 173 0 R 174 0 R 175 0 R 176 0 R 177 0 R 178 0 R 179 0 R 180 0 R 181 0 R]
+/Parent 3 0 R
+/Contents [182 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+16 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [183 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+17 0 obj
+<<
+/Type /Page
+/Annots [184 0 R 185 0 R 186 0 R 187 0 R 188 0 R 189 0 R]
+/Parent 3 0 R
+/Contents [190 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+18 0 obj
+<<
+/Type /Page
+/Annots [191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 203 0 R 204 0 R 205 0 R 206 0 R]
+/Parent 3 0 R
+/Contents [207 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+19 0 obj
+<<
+/Type /Page
+/Annots [208 0 R 209 0 R 210 0 R 211 0 R]
+/Parent 3 0 R
+/Contents [212 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+20 0 obj
+<<
+/Type /Page
+/Annots [213 0 R 214 0 R]
+/Parent 3 0 R
+/Contents [215 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+21 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [216 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+22 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [217 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+23 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [218 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+24 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [219 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+25 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [220 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+26 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [221 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+27 0 obj
+<<
+/Type /Page
+/Annots [222 0 R 223 0 R]
+/Parent 3 0 R
+/Contents [224 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+28 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [225 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+29 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [226 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+30 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [227 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+31 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [228 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+32 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [229 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+33 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [230 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+34 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [231 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+35 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [232 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+36 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [233 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+37 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [234 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+38 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [235 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+39 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [236 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+40 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [237 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+41 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [238 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+42 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [239 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+43 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [240 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+44 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [241 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+45 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [242 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+46 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [243 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+47 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [244 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+48 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [245 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+49 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [246 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+50 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [247 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+51 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [248 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+52 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [249 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+53 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [250 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+54 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [251 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+55 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [252 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+56 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [253 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+57 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [254 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+58 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [255 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+59 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [256 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+60 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [257 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+61 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [258 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+62 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [259 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+63 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [260 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+64 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [261 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+65 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [262 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+66 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [263 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+67 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [264 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+68 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [265 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+69 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [266 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+70 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [267 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+71 0 obj
+<<
+/Type /Page
+/Annots [268 0 R 269 0 R 270 0 R 271 0 R]
+/Parent 3 0 R
+/Contents [272 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+72 0 obj
+<<
+/Type /Page
+/Annots [273 0 R 274 0 R 275 0 R]
+/Parent 3 0 R
+/Contents [276 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+73 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [277 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+74 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [278 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+75 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [279 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+76 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [280 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+77 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [281 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+78 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [282 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+79 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [283 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+80 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [284 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+81 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [285 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+82 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [286 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+83 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [287 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+84 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [288 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+85 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [289 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+86 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [290 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+87 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [291 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+88 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [292 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+89 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [293 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+90 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [294 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+91 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [295 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+92 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [296 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+/F2 297 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+93 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [298 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+94 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [299 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+95 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [300 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+96 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [301 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+97 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [302 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+98 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [303 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+99 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [304 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+100 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [305 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+101 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [306 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+102 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [307 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+103 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [308 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+104 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [309 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+105 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [310 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+106 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [311 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+107 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [312 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+108 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [313 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+109 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [314 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+110 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [315 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+/F3 316 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+111 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [317 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+112 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [318 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+113 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [319 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+114 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [320 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+115 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [321 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+116 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [322 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+/F2 297 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+117 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [323 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+118 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [324 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+119 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [325 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+120 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [326 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+121 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [327 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+122 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [328 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+123 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [329 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+124 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [330 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+125 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [331 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+126 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [332 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+127 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [333 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+128 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [334 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+129 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [335 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+130 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [336 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+131 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [337 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+132 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [338 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+/F2 297 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+133 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [339 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+134 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [340 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+135 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [341 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+136 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [342 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+137 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [343 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+138 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [344 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+139 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [345 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+140 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [346 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+141 0 obj
+<<
+/Type /Page
+/Parent 3 0 R
+/Contents [347 0 R]
+/MediaBox [0 0 595.2 841.919]
+/Resources <<
+/Font <<
+/F1 145 0 R
+>>
+/ProcSet [/PDF /Text]
+>>
+>>
+endobj
+142 0 obj
+<<
+/Dest [24 0 R /XYZ 0 791.643269 null]
+/Last 348 0 R
+/Prev 349 0 R
+/Count 14
+/First 350 0 R
+/Title (6. Description of processing)
+/Parent 5 0 R
+>>
+endobj
+143 0 obj
+<<
+/Dest [8 0 R /XYZ 0 795.550937 null]
+/Next 351 0 R
+/Title (1. Hystory)
+/Parent 5 0 R
+>>
+endobj
+144 0 obj
+<<
+/Filter [/FlateDecode]
+/Length 5938
+>>
+stream
+x]K$ׯ+أ c/k7b;0c%-/_DYU]]-Yㄠb>F/zGSÿ>bݟ;.ٖrtKc*v!ngjSÿV3|j}m9yqin;L/dfja]nO8SRKy89Vfb[Z\v7Oy.õm{ Ƨ3b=vεXL/:?Vp踫è%ϝ:k6ɛNdtM][v3uع$*j.7F@Z^5R6S{Hk({#q9T^zDS]48@fRXY*46d&'(XPmq2ŵjbnXZ,K]3Y-bKvM"_"Dފ~O6Wf,^sr(5] i$Ldfq{/Te>`˼p=(yghrOW.ihAV(alq! '"YO,:x"pmHm(OVmHafdA
++<C&5f#ebZbd&g0T3f&a*+CLc)PS*,(P9(,jd$].mјR1=cg]otAM|tКJZb
M"2qfh"=EڴK3
g1U˅fBS[iu!ܠҪqvpVcSdE3eVl$!&)%u^̈́