Files
Carlo Baronchelli 741791a0e4 Copia locale Iniziale
2022-05-19 16:04:07 +02:00

988 lines
38 KiB
Lua

-- EmtGenerator.lua by EgalTech s.r.l. 2021/12/28
-- 2018/02/22 DS Funzioni bit32 sostituite con operatori sui bit.
-- 2018/08/16 DS Corretta ricorsione di SimulMoveAxis.
-- 2018/10/09 DS Controllo nDec anche in EmtLenToString.
-- 2019/03/19 DS Modificate SimulMoveAxis e SimulMoveAxes.
-- 2019/05/19 DS Aggiunta funzione SetToolForVmill.
-- 2019/08/06 DS Aggiunte funzioni AddToCollisionCheck, AddToolToCollisionCheck e DumpCollisionCheck.
-- 2020/02/04 DS Modifiche a SetToolForVmill per gestire frese con gambo piccolo.
-- 2020/02/05 DS Aggiunto parametro sCollGrp a AddToCollisionCheck e riportato nei dati successivi come Grp.
-- 2020/03/23 DS Aggiunta funzione per impostare il numero di decimali nell'emissione coordinate assi.
-- 2020/10/06 DS In AddToolToCollisionCheck ora si usano diametro e lunghezza totali, prima quelli di lavoro.
-- 2020/10/31 DS Corretta AddToCollisionCheck per riferimenti da calcolarsi in globale.
-- 2020/12/07 DS In SetToolForVmill aggiunta gestione WaterJet.
-- 2020/12/22 DS In AddToCollisionCheck per cilindri ora raggio precede altezza.
-- 2021/01/03 DS Aggiunta funzione AddToolToCollisionObj. In MoveAxis e MoveAxes aggiunta gestione delle collisioni.
-- 2021/01/19 DS In AddToolToCollisionCheck aggiunta gestione per mortasatrici/seghe a catena.
-- 2021/02/10 DS In SimulMoveAx* migliorata gestione segnalazione collisioni.
-- 2021/04/14 DS A AddToolToCollisionObj e AddToolToCollisionCheck aggiunto parametro opzionale bUseDiam.
-- 2021/05/24 DS Corretta AddToolToCollisionCheck perchè recuperava sempre l'utensile dell'uscita 1 della testa e uscita indicate.
-- Parametro bUseDiam eliminato perchè superato dalle modifiche.
-- 2021/06/25 DS In AddToolToCollisionCheck corretta gestione lame ora con lunghezza e spessore.
-- 2021/07/12 DS Migliorie a movimento asse/i per simulazione.
-- 2021/12/28 DS Anche a Centro e Punto Medio di Arco si sottrae EMT.ADDORI se definito.
-- Tavola per definizione modulo (serve ma non usata)
local EmtGenerator = {}
EgtOutLog( 'EmtGenerator started', 1)
-- Include
require( 'EgtBase')
---------------------------------------------------------------------
-- *** Output ***
---------------------------------------------------------------------
function EmtOutput( sOut, nId)
if EMT.NUM then
if not nId or nId == 1 then
EMT.LINENBR = EMT.LINENBR + EMT.LINEINC
if EMT.LINEMAX and EMT.LINENBR > EMT.LINEMAX then EMT.LINENBR = EMT.LINEINC end
EmtWrite( EMT.Nt .. EMT.LINENBR .. ' ' .. ( sOut or ''))
else
if not EMT.LINENBRS then EMT.LINENBRS = {} end
if not EMT.LINENBRS[nId] then EMT.LINENBRS[nId] = 0 end
EMT.LINENBRS[nId] = EMT.LINENBRS[nId] + EMT.LINEINC
if EMT.LINEMAX and EMT.LINENBRS[nId] > EMT.LINEMAX then EMT.LINENBRS[nId] = EMT.LINEINC end
OutFile( nId, EMT.Nt .. EMT.LINENBRS[nId] .. ' ' .. ( sOut or ''))
end
else
if not nId or nId == 1 then
EmtWrite( sOut or '')
else
OutFile( nId, sOut or '')
end
end
end
-----------------------------------------------------------------
-- *** Other Files ***
-----------------------------------------------------------------
local s_OutFh = {}
-----------------------------------------------------------------
function OpenOutFile( nId, sFile)
s_OutFh[nId] = io.open( sFile, 'w')
return s_OutFh[nId]
end
-----------------------------------------------------------------
function OutFile( nId, sOut)
if s_OutFh[nId] then
s_OutFh[nId]:write( sOut .. '\n')
end
end
-----------------------------------------------------------------
function CloseOutFile( nId)
if s_OutFh[nId] then
s_OutFh[nId]:close()
s_OutFh[nId] = nil
end
end
-----------------------------------------------------------------
-- *** Utilities ***
---------------------------------------------------------------------
function EmtUpdatePrev()
EMT.L1p = EMT.L1
EMT.L2p = EMT.L2
EMT.L3p = EMT.L3
EMT.R1p = EMT.R1
EMT.R2p = EMT.R2
EMT.R3p = EMT.R3
EMT.R4p = EMT.R4
EMT.L1op = EMT.L1o
EMT.L2op = EMT.L2o
EMT.L3op = EMT.L3o
if EMT.MOVE ~= 0 then
if EMT.F then
EMT.Fp = EMT.F
end
else
EMT.Fp = nil
end
end
function EmtResetPrevLinear()
EMT.L1p = nil
EMT.L2p = nil
EMT.L3p = nil
EMT.L1op = nil
EMT.L2op = nil
EMT.L3op = nil
end
function EmtResetPrev()
EMT.L1p = nil
EMT.L2p = nil
EMT.L3p = nil
EMT.R1p = nil
EMT.R2p = nil
EMT.R3p = nil
EMT.R4p = nil
EMT.L1op = nil
EMT.L2op = nil
EMT.L3op = nil
EMT.Fp = nil
end
function EmtSetAdditionalOrig( dAddX, dAddY, dAddZ)
EMT.ADDORI = Point3d( dAddX, dAddY, dAddZ)
end
function EmtAdjustLinearAxes()
-- salvo i valori rispetto a Zero macchina
EMT.L1o = EMT.L1
EMT.L2o = EMT.L2
EMT.L3o = EMT.L3
-- se emetto rispetto all'origine 1 della tavola
if EMT.USETO1 then
-- sottraggo agli assi lineari l'origine 1 della tavola
if EMT.L1 then
EMT.L1 = EMT.L1 - EMT.TABORI1[1]
if EMT.ADDORI then
EMT.L1 = EMT.L1 - EMT.ADDORI[1]
end
end
if EMT.L2 then
EMT.L2 = EMT.L2 - EMT.TABORI1[2]
if EMT.ADDORI then
EMT.L2 = EMT.L2 - EMT.ADDORI[2]
end
end
if EMT.L3 then
EMT.L3 = EMT.L3 - EMT.TABORI1[3]
if EMT.ADDORI then
EMT.L3 = EMT.L3 - EMT.ADDORI[3]
end
end
end
-- se emetto rispetto a piano locale
if EMT.IPLGL then
local ptP = Point3d( EMT.L1, EMT.L2, EMT.L3)
ptP:toLoc( EMT.IPLGLFR)
EMT.L1 = ptP:getX()
EMT.L2 = ptP:getY()
EMT.L3 = ptP:getZ()
end
end
function EmtAdjustRotaryAxes()
-- salvo i valori rispetto a Zero macchina
EMT.R1o = EMT.R1
EMT.R2o = EMT.R2
EMT.R3o = EMT.R3
EMT.R4o = EMT.R4
end
function EmtAdjustCenterAxes()
-- salvo i valori rispetto a Zero macchina
EMT.C1o = EMT.C1
EMT.C2o = EMT.C2
EMT.C3o = EMT.C3
-- se emetto rispetto all'origine 1 della tavola
if EMT.USETO1 then
-- sottraggo agli assi lineari l'origine 1 della tavola
if EMT.C1 then
EMT.C1 = EMT.C1 - EMT.TABORI1[1]
if EMT.ADDORI then
EMT.C1 = EMT.C1 - EMT.ADDORI[1]
end
end
if EMT.C2 then
EMT.C2 = EMT.C2 - EMT.TABORI1[2]
if EMT.ADDORI then
EMT.C2 = EMT.C2 - EMT.ADDORI[2]
end
end
if EMT.C3 then
EMT.C3 = EMT.C3 - EMT.TABORI1[3]
if EMT.ADDORI then
EMT.C3 = EMT.C3 - EMT.ADDORI[3]
end
end
end
-- se emetto rispetto a piano locale
if EMT.IPLGL then
local ptP = Point3d( EMT.C1, EMT.C2, EMT.C3)
ptP:toLoc( EMT.IPLGLFR)
EMT.C1 = ptP:getX()
EMT.C2 = ptP:getY()
EMT.C3 = ptP:getZ()
end
end
function EmtAdjustMidPointAxes()
-- salvo i valori rispetto a Zero macchina
EMT.M1o = EMT.M1
EMT.M2o = EMT.M2
EMT.M3o = EMT.M3
-- se emetto rispetto all'origine 1 della tavola
if EMT.USETO1 then
-- sottraggo agli assi lineari l'origine 1 della tavola
if EMT.M1 then
EMT.M1 = EMT.M1 - EMT.TABORI1[1]
if EMT.ADDORI then
EMT.M1 = EMT.M1 - EMT.ADDORI[1]
end
end
if EMT.M2 then
EMT.M2 = EMT.M2 - EMT.TABORI1[2]
if EMT.ADDORI then
EMT.M2 = EMT.M2 - EMT.ADDORI[2]
end
end
if EMT.M3 then
EMT.M3 = EMT.M3 - EMT.TABORI1[3]
if EMT.ADDORI then
EMT.M3 = EMT.M3 - EMT.ADDORI[3]
end
end
end
-- se emetto rispetto a piano locale
if EMT.IPLGL then
local ptP = Point3d( EMT.M1, EMT.M2, EMT.M3)
ptP:toLoc( EMT.IPLGLFR)
EMT.M1 = ptP:getX()
EMT.M2 = ptP:getY()
EMT.M3 = ptP:getZ()
end
end
local function EmtToEmit( V, Vp)
if not V then
return false
end
if not EMT.MODAL or not Vp then
return true
end
return ( abs( V - Vp) > 0.001)
end
function EmtGetAxis( Ax, bRotLikeLin)
local Axp = Ax .. 'p'
local Axt = Ax .. 't'
if EMT[Axt] and EmtToEmit( EMT[Ax], EMT[Axp]) then
local nDec = EMT.DECNUM or 3
if not EMT.INCHES or (( Ax == 'R1' or Ax == 'R2' or Ax == 'R3' or Ax == 'R4') and not bRotLikeLin) then
return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Ax], nDec), true
else
return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Ax] / GEO.ONE_INCH, nDec + 1), true
end
end
return '', false
end
function EmtGetRapidAxis( Ax, bRotLikeLin)
local MaskVal = {L1=1,L2=2,L3=4,R1=8,R2=16,R3=32,R4=64} -- per lua 5.2 {L1=0,L2=1,L3=2,R1=3,R2=4,R3=5,R4=6}
if ( EMT.MASK & MaskVal[Ax]) ~= 0 then -- per lua 5.2 bit32.extract(EMT.MASK,MaskVal[Ax]) ~= 0
return EmtGetAxis( Ax, bRotLikeLin)
end
-- mascherato, sistemo attuale come precedente
local Axp = Ax .. 'p'
local Axt = Ax .. 't'
EMT[Ax] = EMT[Axp]
return '', false
end
function EmtGetHomeAxis( Ax, bRotLikeLin)
local MaskVal = {L1=1,L2=2,L3=4,R1=8,R2=16,R3=32,R4=64} -- per lua 5.2 {L1=0,L2=1,L3=2,R1=3,R2=4,R3=5,R4=6}
if ( EMT.MASK & MaskVal[Ax]) ~= 0 then -- per lua 5.2 bit32.extract(EMT.MASK,MaskVal[Ax]) ~= 0
local Axo = Ax .. 'o'
local Axt = Ax .. 't'
if EMT[Axt] then
local nDec = EMT.DECNUM or 3
if not EMT.INCHES or (( Ax == 'R1' or Ax == 'R2' or Ax == 'R3' or Ax == 'R4') and not bRotLikeLin) then
return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Axo], nDec), true
else
return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Axo] / GEO.ONE_INCH, nDec + 1), true
end
end
end
return '', false
end
function EmtGetHomeAxisByName( Ax, dOffset, bRotLikeLin)
local sToken = EgtGetAxisToken( Ax)
local bLinear = EgtGetAxisType( Ax)
local dVal = EgtGetAxisHomePos( Ax)
if dOffset then
dVal = dVal + dOffset
end
if sToken and bLinear ~= nil and dVal then
local nDec = EMT.DECNUM or 3
if not EMT.INCHES or ( not bLinear and not bRotLikeLin) then
return ' ' .. sToken .. EgtNumToString( dVal, nDec), true
else
return ' ' .. sToken .. EgtNumToString( dVal / GEO.ONE_INCH, nDec + 1), true
end
else
return '', false
end
end
function EmtGetFeed()
if EmtToEmit( EMT.F, EMT.Fp) then
if not EMT.INCHES then
return ' ' .. EMT.Ft .. EgtNumToString( EMT.F, 0)
else
return ' ' .. EMT.Ft .. EgtNumToString( EMT.F / GEO.ONE_INCH, 1)
end
end
return ''
end
function EmtGetArcType( nMove, bInv)
if nMove == 2 then
if bInv then
return 3
else
return 2
end
elseif nMove == 3 then
if bInv then
return 2
else
return 3
end
else
return nil
end
end
-------------------------------------------------------------------------------
function EmtGetAngO2( vtZ, vtX, dAngV, dAngO)
-- vettore X di riferimento
local vtRif = Vector3d( X_AX())
-- lo ruoto prima attorno a Y poi attorno a Z
vtRif:rotate( Y_AX(), dAngV)
vtRif:rotate( Z_AX(), dAngO)
-- prodotto scalare tra vettore riferimento ruotato e vettore vtX
local dCos = vtRif * vtX
-- prodotto scalare tra vettore prodotto vettoriale dei due e vettore vtZ
local dSin = ( vtRif ^ vtX) * vtZ
-- restituisco l'angolo di rotazione richiesto
return atan2( dSin, dCos)
end
-------------------------------------------------------------------------------
function EmtGetAngO3( vtZ, vtX, dAngV, dAngO)
-- vettore X di riferimento
local vtRif = Vector3d( X_AX())
-- vettore asse di rotazione
local vtAx = Vector3d( - sin( dAngO), cos( dAngO), 0)
-- ruoto X di rif attorno a questo asse
vtRif:rotate( vtAx, dAngV)
-- prodotto scalare tra vettore riferimento ruotato e vettore vtX
local dCos = vtRif * vtX
-- prodotto scalare tra vettore prodotto vettoriale dei due e vettore vtZ
local dSin = ( vtRif ^ vtX) * vtZ
-- restituisco l'angolo di rotazione richiesto
return atan2( dSin, dCos)
end
-------------------------------------------------------------------------------
function EmtLenToString( Val, nDec)
nDec = ( nDec or 3)
if not EMT.INCHES then
return EgtNumToString( Val, nDec)
else
return EgtNumToString( Val/GEO.ONE_INCH, nDec + 1)
end
end
-------------------------------------------------------------------------------
function EmtNum3ToString( Tav, nDec)
nDec = ( nDec or 3)
return EgtNumToString( Tav[1], nDec) .. ","..
EgtNumToString( Tav[2], nDec) .. ","..
EgtNumToString( Tav[3], nDec)
end
-------------------------------------------------------------------------------
function EmtLen3ToString( Tav, nDec)
nDec = ( nDec or 3)
return EmtLenToString( Tav[1], nDec) .. ","..
EmtLenToString( Tav[2], nDec) .. ","..
EmtLenToString( Tav[3], nDec)
end
---------------------------------------------------------------------
function EmtSecToHMS( dSec)
local nH = floor( dSec / 3600)
local nM = floor(( dSec - nH * 3600) / 60)
local nS = floor( dSec - nH * 3600 - nM * 60)
local sH = EgtIf( nH < 10, '0', '') .. tostring( nH)
local sM = EgtIf( nM < 10, '0', '') .. tostring( nM)
local sS = EgtIf( nS < 10, '0', '') .. tostring( nS)
return sH .. ':' .. sM .. ':' .. sS
end
---------------------------------------------------------------------
function EmtLenToMF( dLen)
local dOut
if EMT.INCHES then
dOut = dLen / 304.8
else
dOut = dLen / 1000
end
return EgtIf( dOut < 10, ' ', '') .. EgtNumToString( dOut, -1)
end
---------------------------------------------------------------------
-- *** Estimation functions ***
---------------------------------------------------------------------
local s_TleTitle
local s_TleMach = {}
local s_TleTool = {}
---------------------------------------------------------------------
function EmtTleStart( sTitle)
-- inizializzazioni
s_TleTitle = sTitle
s_TleMach = {}
s_TleTool = {}
end
---------------------------------------------------------------------
function EmtTleAddMachining( sName, sTime, sLen, sTool)
table.insert( s_TleMach, { Name = sName, Time = sTime, Len = sLen, Tool = sTool})
end
---------------------------------------------------------------------
function EmtTleAddTotal( sTotTime, sTotLen)
s_TleMach.Total = { Time = sTotTime, Len = sTotLen}
end
---------------------------------------------------------------------
function EmtTleAddTool( sName, sLen)
table.insert( s_TleTool, { Name = sName, Len = sLen})
end
---------------------------------------------------------------------
function EmtTleEnd( sFormat)
-- se richiesto formato HTML
if sFormat:lower() == 'html' then
-- intestazione
EmtOutput( '<!DOCTYPE html>')
EmtOutput( '<html>')
EmtOutput( '<head>')
EmtOutput( ' <meta http-equiv="X-UA-Compatible" content="IE=10; charset=utf-8"/>')
EmtOutput( ' <title>' .. ( s_TleTitle or '') .. '</title>')
EmtOutput( ' <style type = "text/css">\r\n' ..
' caption {\r\n' ..
' margin: 10px;\r\n' ..
' font: 200% arial, sans-serif;\r\n' ..
' }\r\n' ..
' table, th, td {\r\n' ..
' border: 1px solid black;\r\n' ..
' border-collapse: collapse;\r\n' ..
' }\r\n' ..
' table {\r\n' ..
' margin: 30px;\r\n' ..
' background-color: #f2f2f2;\r\n' ..
' }\r\n' ..
' th, td {\r\n' ..
' padding: 0.4rem;\r\n' ..
' text-align: center;\r\n' ..
' }\r\n' ..
' tr.total {\r\n' ..
' background-color: #e6e6e6;\r\n' ..
' }\r\n' ..
' </style>')
EmtOutput( '</head>')
EmtOutput( '<body>')
-- tabella lavorazioni
if s_TleMach and #s_TleMach > 0 then
EmtOutput( ' <table>\r\n' ..
' <caption>Machinings</caption>\r\n' ..
' <tr>\r\n' ..
' <th></th>\r\n' ..
' <th>Time [h:m:s]</th>\r\n' ..
' <th>Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]') .. '</th>\r\n' ..
' <th>Tool</th>\r\n' ..
' </tr>')
for i = 1, #s_TleMach do
EmtOutput( ' <tr>\r\n' ..
' <td>' .. ( s_TleMach[i].Name or '') .. '</td>\r\n' ..
' <td>' .. ( s_TleMach[i].Time or '') .. '</td>\r\n' ..
' <td>' .. ( s_TleMach[i].Len or '') .. '</td>\r\n' ..
' <td>' .. ( s_TleMach[i].Tool or '') .. '</td>\r\n' ..
' </tr>')
end
EmtOutput( ' <tr class="total">\r\n' ..
' <td>TOTAL</td>\r\n' ..
' <td>' .. ( s_TleMach.Total.Time or '') .. '</td>\r\n' ..
' <td>' .. ( s_TleMach.Total.Len or '') .. '</td>\r\n' ..
' <td>' .. '</td>\r\n' ..
' </tr>')
EmtOutput( ' </table>')
end
-- tabella utensili
if s_TleTool and #s_TleTool > 0 then
EmtOutput( ' <table>\r\n' ..
' <caption>Tools</caption>\r\n' ..
' <tr>\r\n' ..
' <th></th>\r\n' ..
' <th>Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]') .. '</th>\r\n' ..
' </tr>')
for i = 1, #s_TleTool do
EmtOutput( ' <tr>\r\n' ..
' <td>' .. ( s_TleTool[i].Name or '') .. '</td>\r\n' ..
' <td>' .. ( s_TleTool[i].Len or '') .. '</td>\r\n' ..
' </tr>')
end
EmtOutput( ' </table>')
end
-- conclusione
EmtOutput( '</body>')
EmtOutput( '</html>')
-- altrimenti formato testo
else
-- intestazione
EmtOutput( ' ' .. ( s_TleTitle or '') .. '\r\n \r\n')
-- tabella lavorazioni
if s_TleMach and #s_TleMach > 0 then
EmtOutput( ' Machinings')
EmtOutput( ' ==========')
EmtOutput( ' Time [h:m:s] Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]') .. ' Tool')
for i = 1, #s_TleMach do
local sName = ( s_TleMach[i].Name or '')
sName = sName .. string.rep( ' ', 18 - #sName)
EmtOutput( sName .. ( s_TleMach[i].Time or '') .. ' ' .. ( s_TleMach[i].Len or '') .. ' ' .. ( s_TleMach[i].Tool or ''))
end
end
EmtOutput( '-------------------------------------------------------')
EmtOutput( 'TOTAL ' .. ( s_TleMach.Total.Time or '') .. ' ' .. ( s_TleMach.Total.Len or ''))
-- tabella utensili
if s_TleTool and #s_TleTool > 0 then
EmtOutput( '\r\n\r\n Tools')
EmtOutput( ' =====')
EmtOutput( ' Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]'))
for i = 1, #s_TleTool do
local sName = ( s_TleTool[i].Name or '')
sName = sName .. string.rep( ' ', 19 - #sName)
EmtOutput( sName .. ( s_TleTool[i].Len or ''))
end
end
end
end
---------------------------------------------------------------------
-- *** Simulation functions ***
---------------------------------------------------------------------
local function MyPrepareAxis( sName, dPos, dStep, nS)
if not sName then return nil, nS end
local dPrev = EgtGetAxisPos( sName)
if not dPrev then return nil, nS end
if abs( dStep) > GEO.EPS_SMALL then
local nSa = abs( ceil( ( dPos - dPrev) / dStep))
nS = max( nS, nSa)
end
return dPrev, nS
end
---------------------------------------------------------------------
local function MySetAxisPos( sName, dPos)
local bOk, dNewPos = EgtSetAxisPos( sName, dPos)
return ( bOk and abs( dNewPos - dPos) < 10 * GEO.EPS_SMALL)
end
---------------------------------------------------------------------
function SimulMoveAxis( sName, dPos, dStep)
-- salvo step attuale
EMT.SIMSTEP = EMT.SIMSTEP or 20
local dSimStep = EMT.SIMSTEP
-- preparazione asse
local dPrev, nS = MyPrepareAxis( sName, dPos, dStep, 1)
-- l'asse deve essere ben definito
if not dPrev then return false end
-- movimento
if nS > 0 then
for i = 1, nS do
local dCoeff = i / nS
local bOk = MySetAxisPos( sName, ( 1 - dCoeff) * dPrev + dCoeff * dPos)
EgtDraw()
local bCheckOk, nCdInd, nObjInd = EmtExecCollisionCheck()
if not bCheckOk then
local nPrevErr = EMT.ERR
local bCollOk, nErr = EmtOnCollision( nCdInd, nObjInd)
if not bCollOk and nErr == 11 then
if EgtGetEnableUI() then
EgtOutBox( 'Collisione!', 'AVVERTIMENTO', 'WARNING')
EMT.SIMUISTAT = MCH_UISIM.PAUSE
while EMT.SIMUISTAT == MCH_UISIM.PAUSE do
-- Param1 = -11 notifica al simulatore pausa per collisione
EgtProcessEvents( -11, 4)
end
end
else
EMT.ERR = nPrevErr
end
end
if not bOk then
return false
end
if EgtGetEnableUI() then
EgtProcessEvents( 0, 4)
while EMT.SIMUISTAT == MCH_UISIM.PAUSE do
EgtProcessEvents( 0, 4)
end
if EMT.SIMUISTAT == MCH_UISIM.STOP then
error( 'STOP')
end
-- se cambia lo step di simulazione richiesto in modo significativo ...
if abs( EMT.SIMSTEP - dSimStep) > 5 then
local dC = EMT.SIMSTEP / dSimStep
return SimulMoveAxis( sName, dPos, dC * dStep)
end
end
end
end
-- assegno valore finale esatto
return MySetAxisPos( sName, dPos)
end
---------------------------------------------------------------------
function SimulMoveAxes( sName, dPos, dStep, sName2, dPos2, dStep2, sName3, dPos3, dStep3, sName4, dPos4, dStep4, sName5, dPos5, dStep5)
-- salvo step attuale
EMT.SIMSTEP = EMT.SIMSTEP or 20
local dSimStep = EMT.SIMSTEP
-- preparazione dei diversi assi
local dPrev, dPrev2, dPrev3, dPrev4, dPrev5
local nS = 1
dPrev, nS = MyPrepareAxis( sName, dPos, dStep, nS)
dPrev2, nS = MyPrepareAxis( sName2, dPos2, dStep2, nS)
dPrev3, nS = MyPrepareAxis( sName3, dPos3, dStep3, nS)
dPrev4, nS = MyPrepareAxis( sName4, dPos4, dStep4, nS)
dPrev5, nS = MyPrepareAxis( sName5, dPos5, dStep5, nS)
-- il primo asse deve essere ben definito
if not dPrev then return false end
-- movimento
if nS > 0 then
for i = 1, nS do
local dCoeff = i / nS
local bOk = MySetAxisPos( sName, ( 1 - dCoeff) * dPrev + dCoeff * dPos)
local bOk2 = not dPrev2 or MySetAxisPos( sName2, ( 1 - dCoeff) * dPrev2 + dCoeff * dPos2)
local bOk3 = not dPrev3 or MySetAxisPos( sName3, ( 1 - dCoeff) * dPrev3 + dCoeff * dPos3)
local bOk4 = not dPrev4 or MySetAxisPos( sName4, ( 1 - dCoeff) * dPrev4 + dCoeff * dPos4)
local bOk5 = not dPrev5 or MySetAxisPos( sName5, ( 1 - dCoeff) * dPrev5 + dCoeff * dPos5)
EgtDraw()
local bCheckOk, nCdInd, nObjInd = EmtExecCollisionCheck()
if not bCheckOk then
local nPrevErr = EMT.ERR
local bCollOk, nErr = EmtOnCollision( nCdInd, nObjInd)
if not bCollOk and nErr == 11 then
EMT.ERR = 11
if EgtGetEnableUI() then
EgtOutBox( 'Collisione!', 'AVVERTIMENTO', 'WARNING')
EMT.SIMUISTAT = MCH_UISIM.PAUSE
while EMT.SIMUISTAT == MCH_UISIM.PAUSE do
-- Param1 = -11 notifica al simulatore pausa per collisione
EgtProcessEvents( -11, 4)
end
end
else
EMT.ERR = nPrevErr
end
end
if not ( bOk and bOk2 and bOk3 and bOk4 and bOk5) then
return false, bOk, bOk2, bOk3, bOk4, bOk5
end
if EgtGetEnableUI() then
EgtProcessEvents( 0, 4)
while EMT.SIMUISTAT == MCH_UISIM.PAUSE do
EgtProcessEvents( 0, 4)
end
if EMT.SIMUISTAT == MCH_UISIM.STOP then
error( 'STOP')
end
-- se cambia lo step di simulazione richiesto in modo significativo ...
if abs( EMT.SIMSTEP - dSimStep) > 5 then
local dC = EMT.SIMSTEP / dSimStep
return SimulMoveAxes( sName, dPos, dC * dStep,
sName2, dPos2, dC * ( dStep2 or 0), sName3, dPos3, dC * ( dStep3 or 0),
sName4, dPos4, dC * ( dStep4 or 0), sName5, dPos5, dC * ( dStep5 or 0))
end
end
end
end
-- assegno valore finale esatto
local bOk = MySetAxisPos( sName, dPos)
local bOk2 = not dPrev2 or MySetAxisPos( sName2, dPos2)
local bOk3 = not dPrev3 or MySetAxisPos( sName3, dPos3)
local bOk4 = not dPrev4 or MySetAxisPos( sName4, dPos4)
local bOk5 = not dPrev5 or MySetAxisPos( sName5, dPos5)
return ( bOk and bOk2 and bOk3 and bOk4 and bOk5), bOk, bOk2, bOk3, bOk4, bOk5
end
---------------------------------------------------------------------
function SetToolForVmill( sTool, sHead, nExit, VMill)
-- se Vmill non definito, esco
if not VMill then return true end
-- se utensile, testa o uscita non definiti, reset ed esco
if not sTool or sTool == '' or not sHead or sHead == '' or not nExit then
EgtVolZmapResetTool( VMill)
return false
end
-- verifico che l'utensile sia corrente
local sOldTool = EgtTdbGetCurrToolParam( MCH_TP.NAME)
if sTool ~= sOldTool then
if not EgtTdbSetCurrTool( sTool) then return false end
end
-- dichiaro utensile per Vmill
local nType = EgtTdbGetCurrToolParam( MCH_TP.TYPE)
local dLen = EgtTdbGetCurrToolParam( MCH_TP.LEN)
local dDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK)
local dCornR = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD)
local dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG)
local dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
-- ricerca dell'outline e del diametro gambo
local nExitId = EgtGetFirstNameInGroup( EgtGetHeadId( sHead) or GDB_ID.NULL, 'T' .. tostring( nExit))
local nToolId = EgtGetFirstNameInGroup( nExitId or GDB_ID.NULL, sTool)
local nOutlineId = EgtGetFirstNameInGroup( nToolId or GDB_ID.NULL, 'Outline')
local dMaxStemDiam = EgtGetInfo( nToolId or GDB_ID.NULL, 'D_STEM', 'd') or dDiam
-- imposto profilo utensile per Vmill
if nOutlineId then
EgtVolZmapSetGenTool( VMill, sTool, nOutlineId)
elseif nType == MCH_TY.MORTISE_STD then
EgtVolZmapSetMortiserTool( VMill, sTool, dLen, dDiam, dThick, dCornR)
elseif nType == MCH_TY.SAW_STD or nType == MCH_TY.SAW_FLAT then
EgtVolZmapSetSawTool( VMill, sTool, dLen, dDiam, dThick, 0, dCornR)
elseif nType == MCH_TY.WATERJET then
EgtVolZmapSetStdTool( VMill, sTool, dLen + 50, dDiam, dCornR, dMaxMat)
elseif abs( dSideAng) < GEO.EPS_ANG_SMALL or abs( dThick) < GEO.EPS_ANG_SMALL then
if dDiam <= dMaxStemDiam then
EgtVolZmapSetStdTool( VMill, sTool, dLen, dDiam, dCornR, dMaxMat)
else
EgtVolZmapSetSawTool( VMill, sTool, dLen, dDiam, dMaxMat, 0, dCornR)
end
else
local bExtra = ( dThick > 0)
local dTipLen = abs( dThick)
local dTotLen = EgtIf( bExtra, dLen + dTipLen, dLen)
local dDelta
if dSideAng > 0 then
if dCornR < GEO.EPS_SMALL then
dDelta = 2 * dTipLen * tan( dSideAng)
else
dDelta = 2 * ( dCornR * cos( dSideAng) + ( dTipLen - dCornR + dCornR * sin( dSideAng)) * tan( dSideAng))
end
else
dDelta = 2 * tan( dSideAng) * dTipLen
end
local dStemDiam = EgtIf( bExtra, dDiam, dDiam + dDelta)
local dTipDiam = EgtIf( bExtra, dDiam - dDelta, dDiam)
EgtVolZmapSetAdvTool( VMill, sTool, dTotLen, dStemDiam, dTipLen, dTipDiam, dCornR, dMaxMat)
end
-- se l'utensile non era corrente, ripristino il precedente
if sTool ~= sOldTool then
EgtTdbSetCurrTool( sOldTool)
end
return true
end
---------------------------------------------------------------------
local function AddGeomToCollisionCheck( CollGrpId, sClass, vColl)
if not CollGrpId then return false end
local sCollGrp = EgtGetName( CollGrpId) or ''
-- ricerca dei box
local BoxId = EgtGetFirstNameInGroup( CollGrpId, 'BOX')
while BoxId do
local FrameId = BoxId + ( EgtGetInfo( BoxId, 'Frame', 'i') or 0)
if FrameId ~= BoxId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then
local b3Box = EgtGetBBoxRef( BoxId, GDB_BB.STANDARD, EgtFR( FrameId, GDB_ID.ROOT))
local vtDiag = b3Box:getMax() - b3Box:getMin()
local vtM = b3Box:getMin() - ORIG()
table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.BOX, Mv=vtM, P1=vtDiag:getX(), P2=vtDiag:getY(), P3=vtDiag:getZ()})
BoxId = EgtGetNextName( BoxId, 'BOX')
end
end
-- ricerca dei cilindri
local CylId = EgtGetFirstNameInGroup( CollGrpId, 'CYL')
while CylId do
local FrameId = CylId + ( EgtGetInfo( CylId, 'Frame', 'i') or 0)
if FrameId ~= CylId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then
local b3Box = EgtGetBBoxRef( CylId, GDB_BB.STANDARD, EgtFR( FrameId, GDB_ID.ROOT))
local dR = ( b3Box:getDimX() + b3Box:getDimY()) / 4
local dH = b3Box:getDimZ()
local vtM = Vector3d( 0, 0, b3Box:getMin():getZ())
table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtM, P1=dR, P2=dH, P3=0})
CylId = EgtGetNextName( CylId, 'CYL')
end
end
-- ricerca delle sfere
local SphId = EgtGetFirstNameInGroup( CollGrpId, 'SPH')
while SphId do
local FrameId = SphId + ( EgtGetInfo( SphId, 'Frame', 'i') or 0)
if FrameId ~= SphId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then
local b3Box = EgtGetBBoxRef( SphId, GDB_BB.STANDARD, EgtFR( FrameId, GDB_ID.ROOT))
local dR = ( b3Box:getDimX() + b3Box:getDimY() + b3Box:getDimZ()) / 6
local vtM = b3Box:getCenter() - ORIG()
table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.SPHE, Mv=vtM, P1=dR, P2=0, P3=0})
SphId = EgtGetNextName( SphId, 'SPH')
end
end
-- ricerca dei tronchi di cono
local ConId = EgtGetFirstNameInGroup( CollGrpId, 'CON')
while ConId do
local FrameId = ConId + ( EgtGetInfo( ConId, 'Frame', 'i') or 0)
if FrameId ~= ConId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then
local frRef = EgtFR( FrameId, GDB_ID.ROOT)
local vtZ = frRef:getVersZ()
local dRb, dRt, dOb, dOt
-- ricerca delle facce bottom e top
local nFacCnt = EgtSurfTmFacetCount( ConId)
for i = 0, nFacCnt - 1 do
local vtN = EgtSurfTmFacetNormVersor( ConId, i, GDB_ID.ROOT)
if AreSameVectorApprox( vtN, vtZ) then
local b3Box = EgtSurfTmGetFacetBBoxRef( ConId, i, GDB_BB.STANDARD, frRef)
dRt = ( b3Box:getDimX() + b3Box:getDimY()) / 4
dOt = b3Box:getCenter():getZ()
elseif AreOppositeVectorApprox( vtN, vtZ) then
local b3Box = EgtSurfTmGetFacetBBoxRef( ConId, i, GDB_BB.STANDARD, frRef)
dRb = ( b3Box:getDimX() + b3Box:getDimY()) / 4
dOb = b3Box:getCenter():getZ()
end
end
if dRb and dRt and dOb and dOt then
local vtM = Vector3d( 0, 0, dOb)
local dH = dOt - dOb
table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.CONE, Mv=vtM, P1=dRb, P2=dRt, P3=dH})
end
ConId = EgtGetNextName( ConId, 'CON')
end
end
return true
end
---------------------------------------------------------------------
function AddToCollisionCheck( sName, sCollGrp, vColl)
if not vColl then return false end
-- ricerca del gruppo base
local GroupId = EgtGetHeadId( sName)
if not GroupId then GroupId = EgtGetAxisId( sName) end
if not GroupId then GroupId = EgtGetTableId( sName) end
if not GroupId then GroupId = EgtGetBaseId( sName) end
if not GroupId then return false end
-- ricerca del gruppo di collisione
local CAxCollId = EgtGetFirstNameInGroup( GroupId, sCollGrp)
if not CAxCollId then return false end
-- recupero della geometria di collisione
return AddGeomToCollisionCheck( CAxCollId, sName, vColl)
end
---------------------------------------------------------------------
function AddToolToCollisionCheck( sHeadName, nExit, vColl)
if not vColl then return false end
local sTool = EgtGetLoadedTool( sHeadName, nExit)
if not EgtTdbSetCurrTool( sTool or '') then return false end
local nType = EgtTdbGetCurrToolParam( MCH_TP.TYPE)
local dTotRad = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) / 2
local dTotLen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN)
local HeadId = EgtGetHeadId( sHeadName)
local FrameId = EgtGetFirstNameInGroup( HeadId, '_T'..tostring( nExit))
if nType == MCH_TY.SAW_STD or nType == MCH_TY.SAW_FLAT then
local vtM = Vector3d( 0, 0, -dTotLen)
local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtM, P1=dTotRad, P2=dThick, P3=0})
elseif nType == MCH_TY.DRILL_STD or nType == MCH_TY.DRILL_LONG then
local dLen = EgtTdbGetCurrToolParam( MCH_TP.LEN)
local vtMc = Vector3d( 0, 0, -dLen)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtMc, P1=dTotRad, P2=dLen, P3=0})
if dTotLen > dLen + 0.1 then
local vtMt = Vector3d( 0, 0, -dTotLen)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CONE, Mv=vtMt, P1=0, P2=dTotRad, P3=dTotLen-dLen})
end
elseif nType ~= MCH_TY.MORTISE_STD then
local dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG)
local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK)
if abs( dSideAng) < GEO.EPS_ANG_SMALL or abs( dThick) < GEO.EPS_ANG_SMALL then
local vtM = Vector3d( 0, 0, -dTotLen)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtM, P1=dTotRad, P2=dTotLen, P3=0})
else
local dLen = EgtTdbGetCurrToolParam( MCH_TP.LEN)
local dDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
local bExtra = ( dThick > 0)
local dTipLen = abs( dThick)
local dTotLen = EgtIf( bExtra, dLen + dTipLen, dLen)
local dDelta = 2 * dTipLen * tan( dSideAng)
local dStemRad = EgtIf( bExtra, dDiam, dDiam + dDelta) / 2
local dTipRad = EgtIf( bExtra, dDiam - dDelta, dDiam) / 2
local vtMs = Vector3d( 0, 0, -( dTotLen - dTipLen))
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtMs, P1=dStemRad, P2=dTotLen-dTipLen, P3=0})
local vtMt = Vector3d( 0, 0, -dTotLen)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CONE, Mv=vtMt, P1=dTipRad, P2=dStemRad, P3=dTipLen})
end
else
EgtErase( EgtGetFirstNameInGroup( HeadId, '_TT'..tostring( nExit)) or GDB_ID.NULL)
local frRef = EgtFR( FrameId)
local SpecFrId = EgtCopy( FrameId, FrameId, GDB_IN.AFTER)
EgtSetName( SpecFrId, '_TT'..tostring( nExit))
EgtRotate( SpecFrId, frRef:getOrigin(), frRef:getVersY(), 90)
local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK)
local vtMb = Vector3d( 0, -dTotRad, 0)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=SpecFrId, Ty=MCH_SIM_COB.BOX, Mv=vtMb, P1=dTotLen-dTotRad, P2=2*dTotRad, P3=dThick})
local vtMc = Vector3d( dTotLen-dTotRad, 0, 0)
table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=SpecFrId, Ty=MCH_SIM_COB.CYL, Mv=vtMc, P1=dTotRad, P2=dThick, P3=0})
end
return true
end
---------------------------------------------------------------------
function DumpCollisionCheck( vColl, sTitle, nDbgLev)
if not vColl then return false end
if EgtGetDebugLevel() < ( nDbgLev or 1) then return true end
if sTitle then EgtOutLog( sTitle, nDbgLev or 1) end
for i, Coll in ipairs( vColl) do
local sOut = ' Class='..Coll.Cl..' Group='..Coll.Grp..' FrId='..tostring( Coll.Fr)..' Type='..tostring( Coll.Ty)..' Mv='..tostring( Coll.Mv)
if Coll.Ty == MCH_SIM_COB.BOX then
sOut = sOut .. ' L='..EgtNumToString( Coll.P1, 3)..' W='..EgtNumToString( Coll.P2, 3)..' H='..EgtNumToString( Coll.P3, 3)
elseif Coll.Ty == MCH_SIM_COB.CYL then
sOut = sOut .. ' R='..EgtNumToString( Coll.P1, 3)..' H='..EgtNumToString( Coll.P2, 3)
elseif Coll.Ty == MCH_SIM_COB.SPHE then
sOut = sOut .. ' R='..EgtNumToString( Coll.P1, 3)
elseif Coll.Ty == MCH_SIM_COB.CONE then
sOut = sOut .. ' Rb='..EgtNumToString( Coll.P1, 3)..' Rt='..EgtNumToString( Coll.P2, 3)..' H='..EgtNumToString( Coll.P3, 3)
end
EgtOutLog( sOut, nDbgLev or 1)
end
return true
end
---------------------------------------------------------------------
function AddToolToCollisionObj( sTool, sHeadName, nExit, nInd)
local vToolColl = {}
AddToolToCollisionCheck( sHeadName, nExit, vToolColl)
if #vToolColl == 0 then return false end
DumpCollisionCheck( vToolColl, 'Tool Collision Objects :', 4)
-- aggiungo la geometria trovata
for i = 1, #vToolColl do
EmtAddCollisionObjEx( nInd, vToolColl[i].Fr, vToolColl[i].Ty, vToolColl[i].Mv, vToolColl[i].P1, vToolColl[i].P2, vToolColl[i].P3)
end
return true, vToolColl[1]
end
---------------------------------------------------------------------
function AddToolHolderToCollisionObj( sTool, sHeadName, nExit, nInd)
-- recupero il gruppo dell'utensile
local HeadId = EgtGetHeadId( sHeadName)
local ExitId = EgtGetFirstNameInGroup( HeadId, 'T'..tostring( nExit))
local ToolId = EgtGetFirstInGroup( ExitId)
-- cerco la geometria di collisione in questo gruppo
local vThColl = {}
if not AddGeomToCollisionCheck( ToolId, 'TH_'..sHeadName, vThColl) then return false end
DumpCollisionCheck( vThColl, 'ToolHolder Collision Objects :', 4)
-- aggiungo la geometria trovata
for i = 1, #vThColl do
EmtAddCollisionObjEx( nInd, vThColl[i].Fr, vThColl[i].Ty, vThColl[i].Mv, vThColl[i].P1, vThColl[i].P2, vThColl[i].P3)
end
return true, #vThColl
end
---------------------------------------------------------------------
return EmtGenerator