Files
DataWall/LuaLibs/WProcessLapJoint.lua
T
2023-11-16 09:39:33 +01:00

3033 lines
142 KiB
Lua

-- WProcessLapJoint.lua by Egaltech s.r.l. 2023/10/02
-- 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.
-- 2022/09/30 In MakeSideGrooveByMill sistemato il calcolo del massimo sottosquadro dell'utensile per determinare la fattibilità della tasca.
-- 2022/10/05 In MakeSideGrooveByMill implementata l'inversione dello step se la tasca guarda verso il basso
-- 2022/11/15 DS Con lama massima inclinazione 60deg.
-- 2022/12/01 Per 2 facce con angolo > 90° implementata lavorazione principale verticale. Se da sopra, aggiunta ripresa del lato inclinato.
-- 2022/12/14 Nel caso di 2 facce piccola correzione al modo di ordinare le facce.
-- 2023/03/09 Gestito caso riconoscimento errato Stype 3.
-- 2023/03/09 In MakeMoreFaces aggiunta la possibilità di lavorare le fessure con la lama.
-- 2023/03/17 In MakeByMill gestito correttamente il caso di Workside destro.
-- 2023/04/15 Corretta scelta tipo lavorazione 'SideGroove' aggiungendo massimo spessore.
-- 2023/04/17 Sistemata gestione parametri Q, eliminando quello non usato di forzatura lama e abilitandoli anche per DoubleCut.
-- Lavorazione CleanCorner sempre forzata con lato di lavoro in centro.
-- 2023/05/25 Funzioni EgtAddMachining sostituite da WM.AddMachining in modo da trascrivere le priorità da btl alle lavorazioni.
-- 2023/06/30 Aggiunta lettura delle note esistenti dalle lavorazioni per evitare di sovrascriverle.
-- 2023/07/10 In MakeSideGrooveByMill si impedisce ora di lavorare una groove se la testa deve scendere sotto al limite superiore del grezzo.
-- 2023/07/25 Aggiunte passate laterali per SideGroove, se specificato SIDESTEP nelle note utensile.
-- 2023/08/01 Migliorato controllo testa sotto al grezzo in SieGroove.
-- 2023/08/07 Controllo testa sotto al grezzo in SideGroove escluso se richiesto il move after.
-- 2023/09/19 Controllo lavorabilità con una sola faccia ora ha limiti come FreeContour.
-- 2023/09/21 Modifica controllo lavorabilità con tre facce tipo tunnel ma non ortogonali tra loro.
-- 2023/09/21 In MakeByMill modificato SCC per correggere caso con lama su testa fresa.
-- 2023/10/02 Aggiunta segnalazione lavorazione tipo Side non trovata.
-- 2023/11/14 Aggiunta tasche in doppio.
-- Miglioramenti sostanziali nella gestione delle tasche.
-- 2023/11/16 Fresature a salire estese a groove cieche.
-- 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_SIDE_MILL = '' -- d
local Q_CORNER_CUT = '' -- i
-- variabile settaggio doppia lavorazione su angolo > 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_SIDE_MILL = ''
Q_CORNER_CUT = ''
if Proc.Prc == 11 then
Q_SIDE_MILL = 'Q02' -- i
Q_CORNER_CUT = 'Q05' -- i
elseif Proc.Prc == 12 then
Q_SIDE_MILL = 'Q02' -- i
Q_CORNER_CUT = '' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then
Q_SIDE_MILL = 'Q08' -- i
Q_CORNER_CUT = 'Q05' -- i
else
Q_SIDE_MILL = 'Q03' -- i
Q_CORNER_CUT = 'Q05' -- i
end
-- le altre features gestite non hanno parametri Q
end
---------------------------------------------------------------------
local function EvaluateQParam( Proc)
-- 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
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 o di fianco
return vtN:getZ() >= -0.5
-- 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.028 or vtN[2]:getZ() >= -0.028)
-- 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
-- conto le adiacenze delle facce
local vAdj = {}
local nFacesWithMoreThanOneAdj = 0
for i = 1, Proc.Fct do
-- recupero le adiacenze del loop esterno
local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.Id, 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
if nCount > 1 then
nFacesWithMoreThanOneAdj = nFacesWithMoreThanOneAdj + 1
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 and nFacesWithMoreThanOneAdj < 2 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 o assimilabile
elseif nFacInd == -1 or nFacInd == -2 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 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[7], tFacAdj[8], tFacAdj[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
local 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], GDB_ID.ROOT)
local _, vtN3 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[2], GDB_ID.ROOT)
-- trovo il punto sulla superfice di riferimento
local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1], GDB_ID.ROOT)
local _, ptLocP3, ptLocP4, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[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[4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[4]) < GEO.EPS_SMALL) then
nIdEndPoint = 4
nIdIniPoint = 5
elseif ( dist( ptLocP1, tFacAdj[5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[5]) < GEO.EPS_SMALL) then
nIdEndPoint = 5
nIdIniPoint = 4
end
end
-- versore direzione
local vtExtr = tFacAdj[nIdIniPoint] - tFacAdj[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[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[nIdIniPoint], tFacAdj[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[nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
local dLenTrimExt = dist( tFacAdj[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[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[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[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[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[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
local dLenTrimExt = dist( tFacAdj[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[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[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[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- ultima linea di distacco (5mm in direzione utensile)
local pEnd = tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr)
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
else
-- linea di distacco (2mm in direzione utensile)
local pEnd = tFacAdj[nIdEndPoint] + ( 2 * vtExtr)
nAuxId = EgtLine( nAddGrpId, tFacAdj[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[nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB)
end
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc))
local nMchId = WM.AddMachining( nNewProc, 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_ZP
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)
-- forzo lato correzione a centrato
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER)
-- leggo eventuali note esistenti della lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
-- aggiungo alle note massima elevazione
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( 0.0, 1))
-- scrivo le note della lavorazione
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
-- RIMUOVERE
if false and 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
-- FINE PARTE DA RIMUOVERE
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 (nFace1, nFace2, tFacAdj)
local nFace1 = vFace[i].Fac
-- ricavo i tre punti per eventuale superficie locale
local ptLoc1, ptLoc2, ptLoc3
-- aggiungo geometria
local j = EgtIf( i < #vFace, i + 1, EgtIf( bClosed, 1, nil))
if not j then return true end
local nFace2 = vFace[j].Fac
-- punto in comune tra le due facce (punto precedente della faccia [j])
ptLoc1 = vFace[j].PPrev
-- punto precedente (punto precedente della faccia [i])
if vFace[i].PPrev then
ptLoc3 = vFace[i].PPrev
else
ptLoc3 = Point3d( vFace[i].Cen:getX(), vFace[i].Cen:getY(), ptLoc1:getZ())
end
-- punto successivo ( precedente della faccia successiva)
local k = EgtIf( j < #vFace, j + 1, 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].Cen:getX(), vFace[j].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
local tFacAdj = {}
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)
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
end
-- passo alla successiva
i = i + 1
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 = WM.AddMachining( Proc, 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) .. ')'
local dDepth = dMaxDepth - dElev
EgtOutLog( sWarn)
EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH '..EgtNumToString( dDepth, 1))
end
-- leggo eventuali note esistenti della lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
-- imposto elevazione
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 2))
-- scrivo le note della lavorazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- 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
---------------------------------------------------------------------
-- restituisce true se la lavorazione potrebbe danneggiare le parti limitrofe
local function IsMachiningDamagingOtherParts( Proc, dMillDiameter, nRawId)
local bIsMachiningDamagingOtherParts = false
-- box da estendere in tutte le direzioni, compreso angolo cieco
local b3ProcExtended = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD)
-- punto minimo e massimo assoluti del box
local ptMin = b3ProcExtended:getMin()
local ptMax = b3ProcExtended:getMax()
-- estensione aggiunta ai box
local dBoxExtensionLength = dMillDiameter / 2 + 5
-- check box verso X-
if Proc.AffectedFaces.Left then
local vtMove = Vector3d( -dBoxExtensionLength, 0, 0)
ptMin:move( vtMove)
end
-- check box verso X+
if Proc.AffectedFaces.Right then
local vtMove = Vector3d( dBoxExtensionLength, 0, 0)
ptMax:move( vtMove)
end
-- check box verso Y-
if Proc.AffectedFaces.Front then
local vtMove = Vector3d( 0, -dBoxExtensionLength, 0)
ptMin:move( vtMove)
end
-- check box verso Y+
if Proc.AffectedFaces.Back then
local vtMove = Vector3d( 0, dBoxExtensionLength, 0)
ptMax:move( vtMove)
end
-- estendo il box in direzione X e Y e verifico se interseca altre parti
b3ProcExtended:Add( ptMin)
b3ProcExtended:Add( ptMax)
local nPartId = EgtGetFirstPartInRawPart( nRawId)
while nPartId do
local nBoxSolidId = EgtGetFirstNameInGroup( nPartId, 'Box')
local b3Solid = EgtGetBBoxGlob( nBoxSolidId or GDB_ID.NULL, GDB_BB.STANDARD)
b3Solid:expand( - 10 * GEO.EPS_SMALL)
if ( nPartId ~= Proc.PartId) and OverlapsXY( b3ProcExtended, b3Solid) then
bIsMachiningDamagingOtherParts = true
end
nPartId = EgtGetNextPartInRawPart( nPartId)
end
return bIsMachiningDamagingOtherParts
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 Proc.Double and Proc.Double == 2 then
local sMillingBackup = sMilling
sMilling = WM.FindMilling( 'Side', nil, nil, nil, nil, nil, nil, nil, 'H1')
if not WM.IsMachiningOkForDouble( sMilling) then
Proc.Double = 0
sMilling = sMillingBackup
end
end
if not sMilling then
local sErr = 'Error : Side 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 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 = WM.AddMachining( Proc, 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)
-- setto inversione in base al workside
local bIsWorkSideRight = ( EgtGetMachiningParam( MCH_MP.WORKSIDE) == MCH_MILL_WS.RIGHT)
local bInvert = false
if bIsWorkSideRight then
bInvert = true
end
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
-- 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_XM)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- imposto modo di lavorare la faccia
local nFaceUse = WL.GetNearestOrthoOpposite( vtRef, vtN)
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- leggo eventuali note esistenti della lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
-- se lavorazione in doppio aggiungo le rispettive note
if Proc.Double and Proc.Double == 2 then
sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx)
sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ)
end
-- scrivo le note della lavorazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- 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, bExcludeFinishing, bDoubleCustomMach)
local sWarn
-- dati della faccia principale (la più verticale)
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT)
local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId)
-- dati della faccia più orizzontale
local nOtherFacet
local dMinZ = 1
for i = 1, Proc.Fct do
local dCurrentZ = Proc.Face[i].VtN:getZ()
if dCurrentZ < dMinZ then
nOtherFacet = Proc.Face[i].Id
dMinZ = dCurrentZ
end
end
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFacet, GDB_ID.ROOT)
local dElevOtherFacet = WL.GetFaceElevation( Proc.Id, nOtherFacet, nRawId)
-- se lap joint 2 facce dal basso e angolo negativo
local bExcludeSideMill = Proc.Fct == 2 and vtN:getZ() < -0.01 and vtN2:getZ() < -0.01
-- dimensioni della faccia principale
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
-- se avevo stabilito che la customMach non era adatta al double, setto per non specchiare
if not bDoubleCustomMach then Proc.Double = 0 end
-- altrimenti la cerco
else
sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV))
-- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata
if Proc.Double and Proc.Double == 2 then
local sMillOnSideBackup = sMilling
sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, nil, 'H1')
if not WM.IsMachiningOkForDouble( sMilling) then
Proc.Double = 0
sMilling = sMillOnSideBackup
end
end
end
if not sMilling then
local sErr = 'Error : SideGroove not found in library'
EgtOutLog( sErr)
return false, sErr
end
local dGrooveMinZ = max( b3Raw:getMin():getZ(), Proc.Box:getMin():getZ())
local dRawMaxZ = b3Raw:getMax():getZ()
-- recupero i dati dell'utensile
local dMillDiam = 20
local dMillLen = 10
local dMillTotLen = 30
local dMaxMat = 0
local dMillDiamTh = 999
local dMillDiamThStem = 0
local dMillLenTh = 0
local dSideStep = 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
-- di default uso il diametro "alto" del portautensile come diametro del gambo
dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh
dMillDiamThStem = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or dMillDiamThStem
dMillLenTh = EgtTdbGetCurrToolThLength() or dMillLenTh
dSideStep = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDESTEP', 'd') or dSideStep
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
-- se riesco a lavorare il sottosquadro senza arrivare alla parte larga del portautensile uso la sidedepth o il diametro stretto del portautensile come diametro del gambo
if ( dMillTotLen - dMillLenTh) > ( abs( dRawMaxZ - dGrooveMinZ) + 1) then
if dMaxDepthOnSide and dMaxDepthOnSide > 0 then
dMillDiamTh = dMillDiam - dMaxDepthOnSide * 2
elseif dMillDiamThStem > 0 then
dMillDiamTh = dMillDiamThStem
end
end
end
end
-- se profondità ribasso è maggiore della capacità di sottosquadro dell'utensile
if ( dElev > 0.5 * ( dMillDiam - dMillDiamTh) - 10 * GEO.EPS_SMALL) then
if ( not bEnablePreMill and ( bMachFromDn or Proc.Fct > 2)) then
local sErr = 'Error : Side Elevation (' .. dElev .. ') bigger than max tool side depth (' .. ( 0.5 * ( dMillDiam - dMillDiamTh)) ..')'
EgtOutLog( sErr)
return false, sErr
elseif Proc.Double then
Proc.Double = 0
end
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
-- dimensioni della testa
local dHeadMaxWidth = 250
local dHeadMinWidth = 160
local dHeadMinWidthHeight = 30
-- se la testa scende sotto al limite superiore del grezzo e non c'è sufficiente capacità di sottosquadro
-- controllo disattivato se move after
if WD.SIDEMILL_BEFORE and not ( bEnablePreMill or bAsEnablePreMill) and
( ( dMillTotLen < ( abs( dRawMaxZ - dGrooveMinZ) + 10 * GEO.EPS_SMALL) and ( dElev > 0.5 * ( dMillDiam - dHeadMinWidth) - 10 * GEO.EPS_SMALL)) or
( dMillTotLen + dHeadMinWidthHeight < ( abs( dRawMaxZ - dGrooveMinZ) + 10 * GEO.EPS_SMALL) and ( dElev > 0.5 * ( dMillDiam - dHeadMaxWidth) - 10 * GEO.EPS_SMALL))) then
local sErr = 'Error : Tool too short, head will collide with rawpart'
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)
local nMchFId = WM.AddMachining( Proc, 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())
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 = WM.AddMachining( Proc, 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
-- se la groove è rivolta verso il basso (-85°) lavoro a salire con step negativo
local bUpwardMilling = false
if vtN2:getZ() < -0.996 then
bUpwardMilling = true
end
-- step extra in caso di doppio con mix rabbet dal basso e dall'alto, per eliminare la lamina che potrebbe rimanere
if Proc.Double and Proc.Double == 2 and ( Proc.Topology == 'Rabbet' or Proc.Topology == 'Groove') and
not ( Proc.AffectedFaces.Bottom and Proc.Mirror.AffectedFaces.Bottom) and not ( Proc.AffectedFaces.Top and Proc.AffectedFaces.Bottom) then
-- determino a quale delle due feature applicare la lavorazione
local bProcVsMirrorToCopy = true
local nFacetToMachine = nFacet
if Proc.AffectedFaces.Bottom then
bProcVsMirrorToCopy = false
for i = 1, Proc.Mirror.Fct do
local vtNMirror = Proc.Mirror.Face[i].VtN
if AreOppositeVectorApprox( vtN, vtNMirror) then
nFacetToMachine = Proc.Mirror.Face[i].Id
break
end
end
end
local nAddGrpId = WL.GetAddGroup( EgtIf( bProcVsMirrorToCopy, Proc.PartId, Proc.Mirror.PartId))
local nNewProc = EgtCopyGlob( EgtIf( bProcVsMirrorToCopy, Proc.Id, Proc.Mirror.Id), nAddGrpId) or GDB_ID.NULL
local NewProc = { Id = nNewProc, PartId = EgtIf( bProcVsMirrorToCopy, Proc.PartId, Proc.Mirror.PartId)}
-- lavorazione
local sName = 'PreSideMill_' .. EgtGetName( NewProc.Id) or tostring( NewProc.Id)
local nMchFId = WM.AddMachining( NewProc, sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchFId, 'Part', NewProc.PartId)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ NewProc.Id, nFacetToMachine}})
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_NEAR
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- imposto modo di lavorare la faccia
local nFaceUse = WL.GetNearestParalOpposite( Z_AX())
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto elevazione e step
local dDepth = 5
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
EgtSetMachiningParam( MCH_MP.STEP, dElev)
-- setto il lato di lavoro standard
EgtSetMachiningParam( MCH_MP.INVERT, true)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- 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
-- se richiesto, setto la nota per spostare la lavorazione alla fine
if not WD.SIDEMILL_BEFORE then
EgtSetInfo( nMchFId, 'MOVE_AFTER', 1)
end
-- eseguo
if not EgtApplyMachining( true, false) then
-- provo a invertire posizione braccio porta testa
nSCC = MCH_SCC.ADIR_FAR
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
-- se faccio lo step extra e ho rimosso la lamina, in doppio lavorerò dal basso verso l'alto
bUpwardMilling = true
end
-- lavorazione
local dStepOri
if not bExcludeSideMill then
local nSideStep = 1
if dSideStep > 0 and not ( bEnablePreMill or bAsEnablePreMill) and nModifyLeadInOut < 1 then
nSideStep = ceil( dElev / dSideStep)
dSideStep = max( dElev / nSideStep, 0)
end
for i = 1, nSideStep do
-- inserisco la lavorazione di ribasso o gola
local sName = EgtIf( bEnablePreMill ~= nil, 'SideMill_', 'Mill_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = WM.AddMachining( Proc, 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_NEAR
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- imposto modo di lavorare la faccia
local nFaceUse = WL.GetNearestParalOpposite( Z_AX())
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto elevazione e step
local dStep = EgtGetMachiningParam( MCH_MP.STEP)
dStepOri = dStep
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
if bUpwardMilling then
dStep = -dStep
end
EgtSetMachiningParam( MCH_MP.STEP, dStep)
-- leggo eventuali note esistenti della lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
-- aggiungo alle note massima elevazione
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev, 3))
-- se lavorazione in doppio aggiungo le rispettive note
if Proc.Double and Proc.Double == 2 then
sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx)
sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ)
end
-- scrivo le note della lavorazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- setto il lato di lavoro standard
EgtSetMachiningParam( MCH_MP.INVERT, true)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- setto offset radiale per gestire le eventuali passate in orizzontale
local dRadialOffset = dSideStep * ( nSideStep - i)
EgtSetMachiningParam( MCH_MP.OFFSR, dRadialOffset)
-- 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 ho passate orizzontali riduco l'eventuale allungamento settato dall'utente
local dLiPerp = EgtGetMachiningParam( MCH_MP.LIPERP)
local dLoPerp = EgtGetMachiningParam( MCH_MP.LOPERP)
if dLiPerp > 0 then
dLiPerp = dLiPerp - dRadialOffset
end
if dLoPerp > 0 then
dLoPerp = dLoPerp - dRadialOffset
end
EgtSetMachiningParam( MCH_MP.LIPERP, dLiPerp)
EgtSetMachiningParam( MCH_MP.LOPERP, dLoPerp)
-- 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
-- provo a invertire posizione braccio porta testa
nSCC = MCH_SCC.ADIR_FAR
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
end
else
sWarn = 'Warning in LapJoint : upside down groove with obtuse angle not completed'
EgtOutLog( sWarn)
end
-- verifico se devo lavorare anche la seconda faccia basandomi sul valore dell'angolo interno
if dAng and dAng > -90 + 10 * GEO.EPS_SMALL and not bExcludeFinishing then
-- inserisco la lavorazione di contornatura
local sName = 'Mill_Oth_Fac_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = WM.AddMachining( Proc, 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 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)
local dMaxElev = dMaxMat
local dStepOtherFace = 0
local dDepthOtherFace = dMaxMat
if Proc.Fct == 2 and abs( vtN2:getZ()) > 0.99 and abs( vtN2:getZ()) < 1.01 then
dStepOtherFace = dStepOri or EgtGetMachiningParam( MCH_MP.STEP)
if dStepOtherFace < GEO.EPS_SMALL then dStepOtherFace = 0.75 * dMaxMat end
local nStepOtherFace = ceil( ( dElevOtherFacet - dMaxMat) / dStepOtherFace)
dStepOtherFace = max( ( dElevOtherFacet - dMaxMat) / max( nStepOtherFace, 1), 0)
dMaxElev = max( ( nStepOtherFace + 1) * dStepOtherFace - GEO.EPS_SMALL, 0)
dDepthOtherFace = dElevOtherFacet
end
if bUpwardMilling then
dStepOtherFace = -dStepOtherFace
end
EgtSetMachiningParam( MCH_MP.STEP, dStepOtherFace)
-- leggo eventuali note esistenti della lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
-- aggiungo alle note massima elevazione
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev, 3))
-- scrivo le note della lavorazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
if bMachFromDn then
EgtSetMachiningParam( MCH_MP.INVERT, true)
EgtSetMachiningParam( MCH_MP.DEPTH, dDepthOtherFace)
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 bEnablePreMill or bAsEnablePreMill or 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
elseif bExcludeSideMill then
local sErr = 'Feature not machinable by orientation'
EgtOutLog( sErr)
return false, sErr
end
return true, sWarn
end
---------------------------------------------------------------------
-- trova la migliore lavorazione tasca in base a diametro utensile, elevazione, doppio e eventuale interferenza di parti vicine
-- se necessario forza la tasca a chiusa
local function VerifyPocket( Proc, nFacet, dElev, nRawId)
local bForceClosedPocket = false
local b3Raw = EgtGetRawPartBBox( nRawId)
-- verifico se la feature è sul bordo (non ci sono altri pezzi davanti alla tasca). Se è sul bordo, l'utensile potrà attaccare da fuori.
local bIsFeatureOnEdge = ( Proc.Topology == 'Groove' and Proc.Fct == 4 and Proc.DistanceToNearestParts.Front > b3Raw:getDimY())
-- trovo il massimo diametro utensile ammissibile per la tasca
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
local dStartDiameter = min( dH, dV)
local dMaxDiameter = dStartDiameter
-- se una sola faccia posso usare un utensile più grande della faccia
if Proc.Fct == 1 then
dMaxDiameter = 2 * dMaxDiameter
end
-- se forma ad L posso usare un utensile più grande della faccia
local bIsL = ( Proc.Fct == 2 or WL.TestElleShape3( Proc.Id, Proc.Fct) or WL.TestElleShape4( Proc.Id, Proc.Fct) == 2)
if bIsL then
dMaxDiameter = 2 * dMaxDiameter
end
-- se forma ad U riduco il diametro se necessario
local bIsU = ( Proc.Fct == 3 and not WL.TestElleShape3( Proc.Id, Proc.Fct))
if bIsU then
-- prendo la linea di base
local dMiddleFacetLength = 0
if abs( dElev - dH) < 1 and abs( dElev - dV) > 1 then
dMiddleFacetLength = dV
elseif abs( dElev - dV) < 1 and abs( dElev - dH) > 1 then
dMiddleFacetLength = dH
end
if dMiddleFacetLength > dMaxDiameter then
dMaxDiameter = min( 2 * dMaxDiameter, dMiddleFacetLength)
end
end
-- in presenza di angoli interni, limito secondo impostazione globale il diametro massimo utensile
if Proc.Fct == 3 and bIsL then
dMaxDiameter = min( dMaxDiameter, WD.MAXDIAM_POCK_CORNER or 1000)
elseif Proc.Fct >= 4 then
dMaxDiameter = min( dMaxDiameter, WD.MAXDIAM_POCK_CORNER or 1000)
end
-- verifico la distanza minima dalle parti vicine e nel caso il FindPocketing limiterà il diametro massimo dell'utensile
local dDistanceToNearestPart = GEO.INFINITO
if Proc.AffectedFaces.Front then
dDistanceToNearestPart = Proc.DistanceToNearestParts.Front
end
if Proc.AffectedFaces.Back then
dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Back)
end
if Proc.AffectedFaces.Left then
dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Left)
end
if Proc.AffectedFaces.Right then
dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Right)
end
-- se la distanza è inferiore ad un valore minimo forzo la tasca chiusa per evitare che la ricerca utensile fallisca
local dMinToolDiameter = 25
if dDistanceToNearestPart < dMinToolDiameter / 2 - 10 * GEO.EPS_SMALL then
bForceClosedPocket = true
dDistanceToNearestPart = dMaxDiameter
end
local bExcludeNoTipFeed = ( Proc.Topology == 'Pocket')
-- recupero la lavorazione
local bUseDElevToFindPocketing = true
local sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, dElev, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart)
-- se tasca troppo profonda cerco senza elevazione e limiterò la profondità
if not sPocketing then
bUseDElevToFindPocketing = false
sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, nil, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart)
end
local dMillDiam = 20
local dMaxDepth = 0
local dThDiam = 100
local sTuuid
-- se lavorazione trovata verifico eventuale doppio, raccolgo i dati utensile e verifico collisioni dell'utensile con altre parti
if sPocketing then
-- se doppio cerco una lavorazione adatta
if Proc.Double and Proc.Double == 2 then
local sPocketingBackup = sPocketing
sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, EgtIf( bUseDElevToFindPocketing, dElev, nil), nil, 'H1', true, dDistanceToNearestPart)
if not WM.IsMachiningOkForDouble( sPocketing) then
Proc.Double = 0
sPocketing = sPocketingBackup
end
end
-- recupero diametro utensile
if EgtMdbSetCurrMachining( sPocketing) then
sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
end
end
-- verifico se la lavorazione (o il suo eventuale mirror) potrebbe danneggiare le parti limitrofe e devo quindi forzare una tasca chiusa
local bIsMachiningDamagingOtherParts = IsMachiningDamagingOtherParts( Proc, dMillDiam, nRawId)
if bIsMachiningDamagingOtherParts then
bForceClosedPocket = true
end
-- disattivo il doppio se devo forzare una tasca chiusa ma l'altra no
if Proc.Double and Proc.Double > 0 then
local bIsMirrorMachiningDamagingOtherParts = IsMachiningDamagingOtherParts( Proc.Mirror, dMillDiam, nRawId)
if bIsMachiningDamagingOtherParts ~= bIsMirrorMachiningDamagingOtherParts then
Proc.Double = 0
end
end
-- altrimenti diametro utensile troppo piccolo: devo forzare tasca chiusa
else
bForceClosedPocket = true
end
-- se tasca chiusa cerco lavorazione con diametro massimo pari a dimensione tasca e riverifico per eventuale doppio
if bForceClosedPocket then
dMaxDiameter = dStartDiameter
bUseDElevToFindPocketing = true
sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, dElev, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart)
if not sPocketing then
bUseDElevToFindPocketing = false
sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, nil, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart)
end
-- se doppio cerco una lavorazione adatta
if Proc.Double and Proc.Double == 2 then
local sPocketingBackup = sPocketing
sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, EgtIf( bUseDElevToFindPocketing, dElev, nil), nil, 'H1', true, dDistanceToNearestPart)
if not WM.IsMachiningOkForDouble( sPocketing) then
Proc.Double = 0
sPocketing = sPocketingBackup
end
end
end
-- recupero dati utensile
if sPocketing and EgtMdbSetCurrMachining( sPocketing) then
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
return sPocketing, bForceClosedPocket, bIsFeatureOnEdge, sTuuid, dMillDiam, dMaxDepth, dThDiam
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)
-- gruppo ausiliario
local nAddGrpId = WL.GetAddGroup( Proc.PartId)
local nNewProc = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet)
-- cerco lavorazione adatta e recupero i dati utensile
local sPocketing, bForceClosedPocket, bIsFeatureOnEdge, sTuuid, dMillDiam, dMaxDepth, dThDiam = VerifyPocket( Proc, nFacet, dElev, nRawId)
if not sPocketing then
local sErr = 'Error : pocketing not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = WM.AddMachining( Proc, 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)
-- leggo eventuali note della lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
-- imposto elevazione
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( min( dElev, dMaxDepth), 1))
-- se lavorazione in doppio aggiungo le rispettive note
if Proc.Double and Proc.Double == 2 then
sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx)
sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ)
-- escludo ottimizzazioni e forzo attacco interno perchè la tasca specchiata potrebbe essere nel mezzo del pannello
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxOptSize', 0.1)
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALOUT)
end
-- setto eventuale nota per forzare tasca chiusa
if bForceClosedPocket then sUserNotes = EgtSetValInNotes( sUserNotes, 'Open', 0) end
-- setto eventuale nota per forzare attacco esterno, fino ad un certo spessore del grezzo
local dMaxRawThicknessToStartOut = 75
if bIsFeatureOnEdge and ( not Proc.Double or Proc.Double == 0) then sUserNotes = EgtSetValInNotes( sUserNotes, 'OpenMinSafe', dMaxRawThicknessToStartOut) end
-- scrivo le note della lavorazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not EgtApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- verifica parametro Q per pulitura spigoli
local bIsU = ( Proc.Fct == 3 and not WL.TestElleShape3( Proc.Id, Proc.Fct))
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, sTuuid
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_EXTRA 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 = WM.AddMachining( Proc, 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)
local ptPM = ( ptP1 + ptP2) / 2
if ( vtN[1] ^ ( ptPM - 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 = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev)
-- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata
local bDoubleMillOnSide = false
if Proc.Double and Proc.Double == 2 then
local sMillOnSideBackup = sMillOnSide
sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev, 'H1')
if WM.IsMachiningOkForDouble( sMillOnSide) then
bDoubleMillOnSide = true
else
sMillOnSide = sMillOnSideBackup
end
end
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, nil, nil, nil, bDoubleMillOnSide)
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 vtNTemp = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
local dSideDist
local ptMid = ( ptP1 + ptP2) / 2
-- faccia orizzontale
local nFacet = EgtIf( vtNTemp:getZ() >= WD.NZ_MINA, nFacInd, nFacInd2)
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacet, GDB_ID.ROOT)
-- 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 oppure se la specchiata guarda in basso e quindi l'attacco deve essere a filo
if ( bEnableMillOnSide and dMaxDepthOnSide > 0) or ( Proc.Double == 2 and Proc.MirrorDeltaZ and abs( Proc.MirrorDeltaZ) > GEO.EPS_SMALL) then
bLikeAsMakeFirstGroove = false
return MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove, nil, nil, bDoubleMillOnSide)
else
local bOk, sErr = MakeByMill( Proc, nFacet, 1 - nFacet, nRawId, b3Raw, dSideDist)
-- se angolo ottuso riprendo il lato quasi verticale
if bOk and dAng and dAng > -90 + 10 * GEO.EPS_SMALL then
local bOk2, sErr2 = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, false, nil, true)
end
return bOk, sErr
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, nil, nil, bDoubleMillOnSide)
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 vtN:getZ() > 0.866 or vtNV:getZ() > 0.866 or 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
local bOk, sErr, sTuuid = MakeByPocketing( Proc, nFacet, nRawId, b3Raw)
-- se angolo ottuso riprendo il lato quasi verticale
if bOk and dAng and dAng > -90 + 10 * GEO.EPS_SMALL then
local _, dHVert, dVVert = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacetVert, GDB_ID.ROOT)
local dDepth = min( dHVert, dVVert)
local _, dHHor, dVHor = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT)
local dDiam = 2 * min( dHHor, dVHor)
local sMillObtuseAngle = WM.FindMilling( 'FreeContour', dDepth, sTuuid, nil, dDiam, nil, nil, nil)
if not sMillObtuseAngle then
sMillObtuseAngle = WM.FindMilling( 'FreeContour', dDepth, nil, nil, dDiam, nil, nil, nil)
end
if not sMillObtuseAngle then
local sErrMillNotFound = 'Error : Processing to finish obtuse angle not found in library'
EgtOutLog( sErrMillNotFound)
return true, sErrMillNotFound
end
local bOk2, sErr2 = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, sMillObtuseAngle, dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, false, nil, true)
end
return bOk, sErr
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 = WM.AddMachining( Proc, 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)
local dMaxSlotThicknessForBlade = 25
local bIsSmallSlot = ( Proc.Fct == 3 and ( min( dH, dV) < dMaxSlotThicknessForBlade + 10 * GEO.EPS_SMALL) and vtN:getZ() > -0.01)
-- se di fianco
if not bPckt and Proc.Fct >= 3 and ( ( vtN:getZ() < WD.NZ_MINA) or bIsSmallSlot) 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)
-- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata
local bDoubleMillOnSide = false
if Proc.Double and Proc.Double == 2 then
local sMillOnSideBackup = sMillOnSide
sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, min( dH, dV), nil, dSideElev, 'H1')
if WM.IsMachiningOkForDouble( sMillOnSide) then
bDoubleMillOnSide = true
else
sMillOnSide = sMillOnSideBackup
end
end
local _, nUseMillOnSide = EvaluateQParam( Proc)
-- se ho abilitata lavorazione di fresa di fianco
if Proc.Fct >= 3 and sMillOnSide and nUseMillOnSide >= 1 and not bIsSmallSlot 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, nil, bDoubleMillOnSide)
end
else
-- fresatura (se definita); se disponibile, cerco di usare un utensile che non lavori al limite della capacità di sottosquadro
local dSideElevMultiplier = 1.2
local sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElevMultiplier * dSideElev)
-- se non ho trovato un utensile un po' più grande del sottosquadro richiesto, passo alla ricerca standard
if not sMilling then
sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElev)
dSideElevMultiplier = 1
end
-- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata
bDoubleMillOnSide = false
if Proc.Double and Proc.Double == 2 then
local sMillOnSideBackup = sMillOnSide
sMillOnSide = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElevMultiplier * dSideElev, 'H1')
if WM.IsMachiningOkForDouble( sMillOnSide) then
bDoubleMillOnSide = true
else
sMillOnSide = sMillOnSideBackup
end
end
-- recupero i dati dell'utensile
local dMaxMat = 1000
local dMaxDepthOnSide = 0
local bIsBlade = false
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 0
bIsBlade = EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE ~= 0
if bIsBlade 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 then
return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, sMilling, nil, nil, nil, nil, nil, nil, nil, bDoubleMillOnSide)
-- 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