Files
DataBeam/LuaLibs/ProcessLapJoint.lua
T

8564 lines
411 KiB
Lua

-- ProcessLapJoint.lua by Egaltech s.r.l. 2024/03/15
-- Gestione calcolo mezzo-legno per Travi
-- 2019/10/08 Agg. gestione OpenPocket.
-- 2021/01/24 Con sega a catena ora sempre impostato asse A.
-- 2021/02/03 Corretto riconoscimento feature di coda.
-- 2021/02/04 Razionalizzata gestione forzatura lama. Corretta gestione diametro minimo utensile per svuotatura.
-- 2021/03/04 Due facce con testa da sotto.
-- 2021/03/20 Piccole correzioni.
-- 2021/03/22 Modificata gestione caso due facce lunghe come la trave con trave corta.
-- 2021/04/13 Modificata gestione fessura U con sega a catena (corta ora ok, lunga ancora da correggere).
-- 2021/04/14 Correzioni ribasso a U con fresa da sotto.
-- 2021/04/15 Aggiunta gestione massima lunghezza fresa da sotto su svuotature.
-- 2021/04/21 Anche feature lunga con due facce con opzione lama ora si taglia con lama.
-- 2021/04/23 Corretto caso con antischeggia non inseriti perchè inutili.
-- 2021/04/27 Antischeggia solo se feature trasversali.
-- 2021/05/12 Semplificata gestione diametro minimo utensile per svuotatura.
-- 2021/06/04 Su U passante con faccia perpendicolare aggiunta si forza Pocket.
-- 2021/06/11 Su U passante e profonda se non bastano due svuotature su faccia ortogonale si fa anche la faccia di fondo per quanto possibile.
-- 2021/06/21 Nel caso precedente si fa la terza svuotatura anche se è possibile fare una sola delle prime due (altra da sotto).
-- 2021/06/21 Gestione ripresa spigoli o contorno con fresa più piccola ( diametro < 3/4 utensile svuotatura) attivata da parametro Q.
-- 2021/07/02 Migliorie e correzioni su svuotature e pulitura spigoli.
-- 2021/07/15 Aggiunti antischeggia con fresa.
-- 2021/09/08 Aggiunta gestione parametro Q04 per i tagli di lama lungo facce lunghe (con o senza facce di chiusura)
-- 2021/09/21 Aggiunta lavorazione/opzione "lamello" con le feature 16, 30, 32, 39,
-- che si attiva abilitando il check al tipo milling: SideMillAsBlade (SideMillAsBlade_2)
-- 2021/09/23 Gestione migliorata lavorazioni BH (blockhaus) su macchina fast BH,
-- migliorata applicazione lavorazioni BH su feature lunghe lavorte a passi
-- 2021/10/06 Ad antischeggia con lama in presenza di testa da sotto aggiunta preferenza a testa da sopra.
-- 2021/10/19 Corretta gestione inversione per Tunnel. OpenPocket anche se spezzato ma 1 o 2 facce. Introdotta lunghezza minima per lamello.
-- 2021/10/21 Migliorato controllo affondamento utensile in U lavorato da 3 parti (anche da sotto).
-- 2021/10/27 Migliorato calcolo asse tunnel o similare.
-- 2021/11/02 In svuotatura con lati aperti diametro fresa non superiore al doppio del lato piccolo.
-- 2021/11/15 Quando si usa sega a catena uso Q10 come massima elevazione.
-- 2021/11/22 Corretta segnalazione warning su foro di L20 e L25.
-- 2022/01/19 Cambiata % lunghezza pezzo per spezzatura. Tolta correzione spessore fresa a disco con superficie da lavorare verso Z-.
-- 2022/01/26 Migliorato controllo uso testa da sotto nel caso due facce con lama.
-- 2022/02/07 Corretto caso con due facce che non è un LongDoubleCut ma che veniva identificato come tale.
-- 2022/02/14 Introdotto uso svuotature ZigZag ottimizzate.
-- 2022/03/18 Corretta lavorazione BH.
-- 2022/03/21 Quando si usa lama uso Q10 come massima elevazione.
-- 2022/03/29 Aggiunta gestione antischeggia con Q06 anche su 3/4-033-X.
-- 2022/04/28 Lavorazione BH forzata sempre OneWay.
-- 2022/05/04 Corretta classificazione due facce sotto. Modificati criteri assegnazione due facce alla coda.
-- 2022/05/24 Miglioramenti vari per BH, compreso controlli per lavorazione da sotto.
-- 2022/06/13 Modifiche per feature lunga con due facce non equivalenti a taglio long. doppio o singolo con faccia terminale.
-- 2022/06/15 Correzione calcolo normale alla faccia per sega catena di fianco.
-- 2022/06/16 Implemento lavorazioni con fresatura di lato per L30 (al momento solo passanti) se parametro Q03=2. Modificate funzioni Make, MakeMoreFaces, Classify.
-- 2022/06/21 Implemento di lavorazioni non passanti con fresatura di lato per L30 se parametro Q03=2. Modificate funzioni MakeMoreFaces, Classify.
-- 2022/06/29 Migliorate lavorazioni con fresatura di lato per L30 se parametro Q03=2. Ora con 4 facce / 3 facce a L può entrare una fresa grande fino al doppio dell'altezza della tasca / doppio della dimensione minima.
-- 2022/07/05 Modifiche per sega a catena di testa e relativa MaxElev.
-- 2022/07/12 In MakeByChainOrSaw aggiunto check per feature L20 usata in modo improprio e, nel caso, si passa a una lavorazione tasca.
-- 2022/08/11 Aggiunta lavorazione tunnel splittata con sega a catena per tutte le macchine ad esclusione della Fast.
-- 2022/09/01 Spostate le funzioni GetTunnelDimension, CalcCollisionSafety, SetOpenSide in BeamLib.
-- 2022/09/15 Implementata gestione feature Planing L090, gestita come LapJoint
-- Implementata, in caso di fresatura di lato con altezza tasca molto bassa, la contornatura con unica passata
-- Migliorata gestione AntiSplint (Mill e Saw)
-- 2022/09/27 Aggiunta gestione SCC per svuotature con TURN (solo dopo applicazione lavorazione).
-- 2022/10/20 In MakeByChainOrSaw modificato check per trovare la faccia adiacente sul lato più lungo.
-- 2022/12/12 Default 1000 per BD.MIN_LEN_LAMELLO. In MachineByMill migliorata ricerca utensile e gestione inversione in funzione del lato di lavoro.
-- 2022/12/16 Implementato parametro Q_SIDE_ROUGH_TOOL anche per L20
-- 2022/12/21 Sistemata gestione SideMillAsSaw.
-- 2023/01/19 In MakeMoreFaces -> MakeBySideMill aggiunto controllo che lo step finale non superi lo spessore utensile.
-- 2023/01/24 In MakeByPocket gestito caso il caso in cui veniva applicata una fresatura con percorso vuoto. Ora viene rimossa e la tasca viene fatta con lama.
-- 2023/02/06 Alla MakeDrillOnCorner aggiunto controllo distanza di sicurezza minima.
-- 2023/02/16 Piccola correzione alla scelta utensile di svuotatura.
-- 2023/02/21 Piccola correzione alla MakeByPocket.
-- 2023/03/31 Correzione al calcolo della distanza di collisione nel caso in cui il gambo sia più piccolo dell'utensile.
-- 2023/06/06 Limiti su svuotature tasche a L 4 facce come per L 3 facce. In svuotatura aggiunto recupero UserNotes da libreria per MaxOptSize.
-- 2023/16/12 Corretto il recupero dati utensile che, in alcune funzioni, puntava all'utensile errato.
-- 2023/06/29 Se forzata lavorazione laterale permetto l'uso del truciolatore solo se non è una tasca chiusa.
-- 2023/07/19 Correzioni e modifiche ad antischeggia con lama (#1351).
-- 2023/08/01 Aggiunta gestione rinvio angolare solo per tasche 5 lati, da sotto e perfettamente verticali.
-- 2023/08/02 Piccola correzione al calcolo della distanza di sicurezza in base al gambo dell'utensile.
-- 2023/08/02 Corretto incremento della profondità pari al raggio utensile per tunnel con sega a catena.
-- 2023/08/10 Modificata scelta SCC per tasche in Y+/- in coda o quasi (anche per relativi antischeggia con lama).
-- 2023/09/12 In MakeByPockets gestito correttamente il ritorno nil di GetUShapeWidth.
-- 2023/09/26 In MakeLongMoreFaces migliorata gestione spezzatura di Tunnel.
-- 2023/09/26 Modificata chiamata a GetFaceWithMostAdj.
-- 2023/09/27 In MakeMoreFaces e Classify refactoring della gestione scanalatura chiusa.
-- 2023/09/27 In MakeLongMoreFaces aggiunto Topology.Classify alla Proc creata.
-- 2023/10/03 In MakePocket aggiunto messaggio in caso si rovini il pezzo successivo.
-- 2023/10/25 In LapJoint 2 facce longitudinali faccio di lama solo se taglio completamente. Altrimenti fresa.
-- 2023/10/27 In Lapjoint 2 facce con angolo > 90 deg, se forzata fresa, si svuota la faccia principale e si lavora poi la faccia inclinata.
-- 2023/11/03 Aggiunta MakeStaircaseStep per lavorazione con fresa + lama di gradini scala. Smusso opzionale.
-- 2023/11/06 In MakeStaircaseStep gestito ritorno.
-- 2023/11/06 Migliorie per lavorazione con AngularTransmission con FAST.
-- 2023/11/30 Calcolo elevazione velocizzato e centralizzato tramite la funzione GetFaceElevation.
-- 2023/12/01 In MakeMoreFaces, nelle OpenPocket, ammesso utensile con diametro fino a 3 volte la dimensione della tasca (era 2).
-- 2023/12/06 In VerifySideMillAsSaw, se SIDEDEPTH non definita, viene calcolata.
-- 2024/01/18 Implementata GetBlockedAxis che gestisce gli assi bloccati per tutti i tipi di utensile.
-- 2024/01/22 Implementata gestione seghe a catena multiple.
-- 2024/01/31 In tagli con sega a catena ora si considera l'ingombro della testa per il calcolo della massima profondità.
-- Aggiunta funzione GetToolEntryAngle per determinare l'angolo di ingresso dell'utensile nella faccia.
-- 2024/02/08 Ora i rabbet lungo X che guardano in basso sono sempre fatti con fresatura di lato per evitare di ruotare.
-- 2024/02/13 In MakeMoreFaces escluse le Groove 2 facce dalla gestione Special3faces.
-- 2024/02/22 Migliorato calcolo area non pinzabile in testa HCING e coda TCING
-- Rimosso un caso di controllo per HCING/TCING
-- 2024/02/29 In MakeMoreFaces passato b3Solid alla funzione ManageAntiSplintByMill
-- 2024/02/29 In lapjoint 2 facce (TestTwoFacesDownHead) migliorata la scelta della lama da sotto.
-- 2024/03/01 Migliorata VerifyPocket.
-- 2024/03/04 Implementato attacco esterno se tasca 4 facce sulla coda ma nessun pezzo successivo.
-- 2024/03/15 Correzione a calcolo ingombro per feature basse e lunghe dalla testa.
-- 2024/04/02 In ForceSideMill escluso caso 4 facce senza possibilità di ingresso lungo Y.
-- 2024/04/11 Aggiunta strategia SawPlusChain per lavorazione tasche con lama + sega a catena opzionale. Attivata con Q11.
-- 2024/04/15 In SideMillAsSaw gestito anche rabbet
-- 2024/04/17 In MakeMoreLongFaces corretto calcolo divisione in parti per evitare problemi di ceil con interi perfetti (ceil(3) = 3 o 4??)
-- 2024/04/22 In IsTailFeature se LapJoint a 2 facce che taglia intera sezione, deve essere fatto dopo taglio di coda
-- 2024/06/18 In MakeByMillAsSaw si cerca di orientare il motore verso il lato più vicino (rispetto a dove è la feature)
-- 2024/06/28 In VerifySideMillAsSaw modificato criterio ricerca utensile in base a normale della faccia
-- 2024/07/04 In IsTailFeature controllo per spostare lapjoint dopo taglio di separazione per lavorazioni tipo BH
-- 2024/09/03 In MakeLongMoreFaces si aggiunge faccia di fondo anche per topologia Groove passante a 3 facce
-- Tabella per definizione modulo
local ProcessLapJoint = {}
-- Include
require( 'EgtBase')
local BL = require( 'BeamLib')
local Fbs = require( 'FacesBySaw')
local Fbp = require( 'FaceByPocket')
local Cut = require( 'ProcessCut')
local DoubleCut = require( 'ProcessDoubleCut')
local LongCut = require( 'ProcessLongCut')
local Long2Cut = require( 'ProcessLongDoubleCut')
local Topology = require( 'FeatureTopology')
EgtOutLog( ' ProcessLapJoint started', 1)
-- Dati
local BD = require( 'BeamData')
local ML = require( 'MachiningLib')
local WHISK_OFFS = 0.1
local WHISK_SAFE = 5
local MIN_LEN_CUT = 30
-- variabili assegnazione parametri Q
local Q_FORCE_BLADE = '' -- i
local Q_DEPTH_CHAMFER = '' -- d
local Q_ONLY_CHAMFER = '' -- i
local Q_USE_MILL = '' -- i
local Q_USE_ROUGH_TOOL = '' -- i
local Q_BORE_ON_CORNER = '' -- 1
local Q_CONTOUR_SMALL_TOOL = '' -- i
local Q_ONLY_CONTOUR = '' -- i
local Q_SIDE_ROUGH_TOOL = '' -- i
local Q_ANTISPLINT_TYPE = '' -- i
local Q_BLADE_ON_ALONG_FACE = '' -- i
local Q_MAX_ELEVATION = '' -- d
local Q_SAW_PLUS_CHAIN = '' -- i
local Q_FORCE_CHAINSAW = '' -- i
local Q_CHAINSAW_FROM_SIDE = '' -- i
local Q_CONVENTIONAL_MILLING = '' -- i
local Q_CLEAN_CORNER = '' -- 1
local Q_FLOATING_AGGREGATE = '' -- i
-- variabile smussi
local bMadeChamfer
-- Settaggi interni
local bTrySidePocketAtFirst = true
---------------------------------------------------------------------
-- Riconoscimento della feature
function ProcessLapJoint.Identify( Proc)
if Proc.bForceMill then
return true
else
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 == 25) 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 == 33) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) or
(( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 90) or
( Proc.Grp == 4 and Proc.Prc == 37) or
( Proc.Grp == 4 and Proc.Prc == 39) or
( Proc.Grp == 4 and Proc.Prc == 120))
end
end
---------------------------------------------------------------------
local function AssignQIdent( Proc)
-- reset assegnazione parametri Q
Q_FORCE_BLADE = ''
Q_DEPTH_CHAMFER = ''
Q_ONLY_CHAMFER = ''
Q_USE_MILL = ''
Q_USE_ROUGH_TOOL = ''
Q_BORE_ON_CORNER = ''
Q_CONTOUR_SMALL_TOOL = ''
Q_ONLY_CONTOUR = ''
Q_SIDE_ROUGH_TOOL = ''
Q_ANTISPLINT_TYPE = ''
Q_MAX_ELEVATION = 'Q10'
Q_STAIRCASE = ''
Q_SAW_PLUS_CHAIN = 'Q11'
Q_FORCE_CHAINSAW = 'Q12'
-- TODO da riportare a Q13 quando è sistemata la gestione del movimento in macchina nell'attacco laterale
Q_CHAINSAW_FROM_SIDE = 'Q999'
Q_CONVENTIONAL_MILLING = ''
Q_CLEAN_CORNER = ''
Q_FLOATING_AGGREGATE = ''
if ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16 then
Q_FORCE_BLADE = 'Q01' -- i
Q_DEPTH_CHAMFER = 'Q04' -- d
Q_ONLY_CHAMFER = 'Q05' -- i
Q_CONVENTIONAL_MILLING = 'Q14' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17 then
Q_DEPTH_CHAMFER = 'Q01' -- d
Q_ONLY_CHAMFER = 'Q02' -- i
Q_USE_MILL = 'Q03' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20 then
Q_DEPTH_CHAMFER = 'Q01' -- d
Q_USE_MILL = 'Q02' -- i
Q_USE_ROUGH_TOOL = 'Q03' -- i
Q_SIDE_ROUGH_TOOL = 'Q04' -- i
Q_BORE_ON_CORNER = 'Q06' -- i
Q_STAIRCASE = 'Q09' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25 then
Q_BORE_ON_CORNER = 'Q01' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then
Q_CONTOUR_SMALL_TOOL = 'Q01' -- i
Q_ONLY_CONTOUR = 'Q02' -- i
Q_SIDE_ROUGH_TOOL = 'Q03' -- i
Q_BLADE_ON_ALONG_FACE = 'Q04' -- i
Q_ANTISPLINT_TYPE = 'Q06' -- i
Q_DEPTH_CHAMFER = 'Q07' -- d
Q_CONVENTIONAL_MILLING = 'Q14' -- i
Q_CLEAN_CORNER = 'Q15' -- i
Q_FLOATING_AGGREGATE = 'Q16' -- i
elseif ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 30 then
Q_BLADE_ON_ALONG_FACE = 'Q04' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32 then
Q_SIDE_ROUGH_TOOL = 'Q01' -- i
Q_CONTOUR_SMALL_TOOL = 'Q02' -- i
Q_ANTISPLINT_TYPE = 'Q06' -- i
Q_CONVENTIONAL_MILLING = 'Q14' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 33 then
Q_ANTISPLINT_TYPE = 'Q06' -- i
Q_CONVENTIONAL_MILLING = 'Q14' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34 then
Q_CONTOUR_SMALL_TOOL = 'Q01' -- i
Q_USE_MILL = 'Q02' -- i
Q_ANTISPLINT_TYPE = 'Q06' -- i
elseif ( Proc.Grp == 4) and Proc.Prc == 37 then
Q_ANTISPLINT_TYPE = 'Q06' -- i
Q_CONVENTIONAL_MILLING = 'Q14' -- i
elseif ( Proc.Grp == 4) and Proc.Prc == 39 then
Q_CONTOUR_SMALL_TOOL = 'Q01' -- i
Q_USE_MILL = 'Q02' -- i
Q_ANTISPLINT_TYPE = 'Q06' -- i
Q_CONVENTIONAL_MILLING = 'Q14' -- i
elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 90 then
Q_ANTISPLINT_TYPE = 'Q03' -- i
Q_SIDE_ROUGH_TOOL = 'Q04' -- i
Q_CONVENTIONAL_MILLING = 'Q14' -- i
end
-- le altre features gestite non hanno parametri Q
end
---------------------------------------------------------------------
local function EvaluateQParam( Proc)
-- verifico che lo smusso sia richiesto
local nChamfer = 0
local dDepth = EgtGetInfo( Proc.Id, Q_DEPTH_CHAMFER, 'd') or 0
if dDepth > 0 then
nChamfer = 1
end
-- verifico se posso fare solo lo smusso
if EgtGetInfo( Proc.Id, Q_ONLY_CHAMFER, 'i') == 1 then
if dDepth > 0 then
nChamfer = nChamfer + 1
-- altrimenti se non ho l'affondamento esco
else
local sErr = 'Error : no chamfer depth'
EgtOutLog( sErr)
return -1, dDepth, sErr
end
end
-- verifico se devo usare lama invece della sega-catena
-- 2020-03-20 forzata abilitazione uso lama se parametro Q non è presente
-- xxxx-xx-xx tolta la preferenza alla lama in favore della sega-catena per un caso particolare
-- 2021-02-15 re-introdotta la preferenza alla lama se non c'è il parametro Q. Rimane da
-- implementare un ulteriore parametro per poter scegliere di prediligere la sega-catena o no al fine di continuare
-- a cambiare il codice per gestire il caso particolare
local bForceUseBlade = false
if #Q_FORCE_BLADE == 0 or EgtGetInfo( Proc.Id, Q_FORCE_BLADE, 'i') == 1 then
bForceUseBlade = true
end
return nChamfer, dDepth, sErr, bForceUseBlade
end
---------------------------------------------------------------------
local function TestElleShape3( Proc, bNotProc)
-- se non passato il Proc vero e proprio
local nNumFacet
local nProcId
if bNotProc then
nProcId = Proc
nNumFacet = EgtSurfTmFacetCount( nProcId)
else
nProcId = Proc.Id
nNumFacet = Proc.Fct
end
-- valida solo nel caso di tre facce
if nNumFacet ~= 3 then return false end
-- determino se L con una faccia terminale o U con tre facce
local bIsL = true
for i = 1, 3 do
local vFacAdj = EgtSurfTmFacetAdjacencies( nProcId, i - 1)[1]
-- le conto
local nCount = 0
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
nCount = nCount + 1
end
end
if nCount == 1 then
bIsL = false
break
end
end
return bIsL
end
---------------------------------------------------------------------
local function TestElleShape4( Proc)
-- valida solo nel caso di quattro facce
if Proc.Fct ~= 4 then return false end
-- determino se L con due facce terminali o O
local nFac3Adj = 0
local dMinArea3 = GEO.INFINITO * GEO.INFINITO
local dMaxArea2 = 0
for i = 1, 4 do
local vFacAdj = EgtSurfTmFacetAdjacencies( 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
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, i - 1, GDB_ID.ROOT)
local dArea = dH * dV
if nCount == 2 then
dMaxArea2 = max( dMaxArea2, dArea)
elseif nCount == 3 then
dMinArea3 = min( dMinArea3, dArea)
nFac3Adj = nFac3Adj + 1
end
end
if nFac3Adj ~= 2 then return false end
-- verifico se L profonda oppure lunga
if dMinArea3 < 2 * dMaxArea2 then
return 1
else
return 2
end
end
---------------------------------------------------------------------
local function VerifyChainSaw( Proc, dMinDim, dMaxDim, dDepth)
local bUseChainSaw = false
local sMchFind = 'Sawing'
-- prendo la prima sega a catena lunga a sufficienza
local sSawing = ML.FindSawing( sMchFind, dDepth, true)
-- se non trovo alcuna sega a catena lunga a sufficienza, accetto di non arrivare sul fondo della tasca
if not sSawing then
sSawing = ML.FindSawing( sMchFind, nil, nil, 'Longest')
end
local dMaxMat = 0
local dSawCornerRad = 0
local dSawThick = 0
local dMaxDepth = 200
local dSawWidth = 0
-- se non trova una lavorazione di sawing esco
if not sSawing then
return bUseChainSaw
else
-- recupero i dati dell'utensile
local dToolLength = 0
local dSawWidth = 75
if EgtMdbSetCurrMachining( sSawing) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength
dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat
dSawWidth = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawWidth
dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
dSawCornerRad = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) or dSawCornerRad
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
end
if dSawThick < dMinDim + 10 * GEO.EPS_SMALL and dSawWidth < dMaxDim + 10 * GEO.EPS_SMALL then
bUseChainSaw = true
end
end
end
return bUseChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick, dMaxDepth, dSawWidth
end
---------------------------------------------------------------------
local function VerifyPocket( Proc, dDiam, dDepth, dMaxTotLen, sMchFindMaster, bPocketUp, bPocketDown)
-- tipo di svuotatura
local sMchFind = EgtIf( sMchFindMaster and #sMchFindMaster > 0, sMchFindMaster, 'Pocket')
-- ricerca della svuotatura
local sPocketing
if dDepth then
sPocketing = ML.FindPocketing( sMchFind, dDiam, dDepth, dMaxTotLen, bPocketUp, bPocketDown) or
ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen, bPocketUp, bPocketDown, nil, nil, 'Longest') or
ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen)
else
sPocketing = ML.FindPocketing( sMchFind, dDiam, 0, dMaxTotLen)
end
if not sPocketing then
return false
end
-- recupero i dati dell'utensile
local bUsePocketing = false
local dMaxDepth = 0
local dToolDiam = 0
if EgtMdbSetCurrMachining( sPocketing) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
end
bUsePocketing = true
end
return bUsePocketing, sPocketing, dMaxDepth, dToolDiam
end
---------------------------------------------------------------------
local function VerifyBHSideMill( Proc, bIsU, bIsL, bSinglePart, bPrevBhSideMill, b3Raw)
-- se non feature BlockHausHalfLap e non abilitato parametro Q per lavorarlo di fianco e non macchina BH esco
local nUseSideTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0
if Proc.Prc ~= 37 and not BD.BH_MACHINE and ( nUseSideTool == 0 or ( nUseSideTool == 4 and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right))) then
return false
end
-- recupero l'ingombro della trave
local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL)
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
return false
end
-- verifico se la funzione è lanciata da IsTailFeature o Classify
if bSinglePart == nil then
-- se lunghezza non richiede spezzatura setto la variabile bSinglePart
if not( ( Proc.Box:getDimX() > BD.LONGCUT_MAXLEN) or
( Proc.Box:getDimX() > 0.8 * b3Solid:getDimX() and Proc.Box:getDimX() > BD.LONGCUT_ENDLEN)) then
bSinglePart = true
end
end
-- determino se U o L(anche con 1 o 2 facce di terminazione)
bIsU = ( bIsU or ( Proc.Fct == 3 and not TestElleShape3( Proc)))
bIsL = ( bIsL or ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2))
-- le facce devono contenere X e quelle di chiusura devono essere perpendicolari a X
local bStopY, bStopZ
if not Proc.TopologyLongName then
Topology.Classify( Proc, b3Raw)
end
for i = 1, Proc.Fct do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT)
-- permessa U passante non parallela agli assi principali
if abs( vtN:getX()) > 0.001 and abs( vtN:getX()) < 0.999962 and Proc.TopologyLongName ~= "Groove-Through-RightAngles-NotParallel-3" then
return false
end
if abs( vtN:getY()) > 0.866 then bStopY = true end
if abs( vtN:getZ()) > 0.866 then bStopZ = true end
end
if bStopY and bStopZ then
return false
end
-- se non U o L o singola faccia di multipla, non accettata
if not ( ( bIsU or bIsL or ( Proc.Fct == 1 and not bSinglePart)) and Proc.Box:getDimX() <= BD.LONGCUT_MAXLEN) then
return false
end
-- se risultato precedente di passo multiplo negativo, riporto il risultato del passo precedente
if bPrevBhSideMill ~= nil and not bPrevBhSideMill then
return false
end
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'BHSideMill')
if not sMilling then
return false
end
-- recupero i dati dell'utensile
local dToolLength = 0
local dToolDiam = 0
local dToolMaxDepth = 0
local dToolThick = 0
local dToolFreeLen = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength
dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam
local dToolThDiam = EgtTdbGetCurrToolThDiam() or 150
if ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE) ~= 0 then
dToolMaxDepth = EgtTdbGetCurrToolMaxDepth() or dToolMaxDepth
dToolThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dToolThick
dToolFreeLen = dToolLength
else
dToolMaxDepth = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or 0.5 * ( dToolDiam - dToolThDiam)
dToolThick = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT)
dToolFreeLen = EgtTdbGetCurrToolMaxDepth() or dToolFreeLen
end
end
end
-- verifico se abbastanza larga (oppure L) rispetto all'utensile
if Proc.Box:getDimX() < dToolThick - 15 * GEO.EPS_SMALL and not bIsL then
return false
end
-- limiti trasversali
local dDepth = min( Proc.Box:getDimY(), Proc.Box:getDimZ())
if dDepth > dToolMaxDepth then
return false
end
-- limiti longitudinali
local dMinXF = Proc.Box:getMin():getX()
local dMaxXF = Proc.Box:getMax():getX()
local dMinT = b3Solid:getMin():getX()
local dMaxT = b3Solid:getMax():getX()
-- determino se è più vicino alla testa o alla coda (con offset per evitare problemi a metà)
local bHeadDir = ( dMaxT - dMinXF) < ( dMaxXF - dMinT) + 50
local bHead = bHeadDir
-- verifico se raggiungibile con la testa senza collisioni
local bUseBHSideMill = EgtIf( bHead, ( dMaxT - dMinXF), ( dMaxXF - dMinT)) < dToolFreeLen
-- se diametro utensile maggiore della testa
if BD.HEAD_DIM_FOR_BH and dToolDiam - 2 * dDepth > BD.HEAD_DIM_FOR_BH then
bHead = true
bUseBHSideMill = true
end
return bUseBHSideMill, bHead, bHeadDir, sMilling, dToolThick, dToolDiam
end
---------------------------------------------------------------------
local function VerifySideMillAsSaw( Proc, nAddGrpId, vtN, dDiam, dFacElev)
-- Verifico sia feature L016, L030, L032, L039
if not ( Proc.Prc == 16 or Proc.Prc == 30 or Proc.Prc == 32 or Proc.Prc == 39) then
return false
end
-- Verifico sia gola lungo X con 3 facce più eventuali terminali
local nTestId = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
local bNewIsU
local nFaces = EgtSurfTmFacetCount( nTestId)
while nFaces >= 3 do
local bDeleteFace
local nInt = 0
while not bDeleteFace and nInt < nFaces do
nInt = nInt + 1
local b3Facet = EgtSurfTmGetFacetBBoxGlob( nTestId, nInt-1, GDB_BB.STANDARD)
local vtN = EgtSurfTmFacetNormVersor( nTestId, nInt-1, GDB_ID.ROOT)
-- se dimensione faccia sulla X
if b3Facet:getDimX() < 1 or abs( vtN:getX()) > 0.1 then
EgtSurfTmRemoveFacet( nTestId, nInt-1)
bDeleteFace = true
end
end
nFaces = EgtSurfTmFacetCount( nTestId)
-- se non ho cancellato una faccia faccio il test per forma ad U
if not bDeleteFace then
-- ottengo il numero di facce rimanenti
bNewIsU = ( nFaces == 3 and not TestElleShape3( nTestId, true))
-- verifico che gola allineata su X
if bNewIsU then
local vtN1 = EgtSurfTmFacetNormVersor( nTestId, 0, GDB_ID.ROOT)
bNewIsU = ( abs( vtN1:getX()) < 0.01)
end
-- esco dal ciclo
break
end
end
-- cancello la copia del percorso
EgtErase( nTestId)
-- eseguo test
if not bNewIsU and not ( Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2') then
return false
end
-- Verifico sia abbastanza lunga
if not (( Proc.TotBox and Proc.TotBox:getDimX() > ( BD.MIN_LEN_LAMELLO or 1000)) or
( not Proc.TotBox and Proc.Box:getDimX() > ( BD.MIN_LEN_LAMELLO or 1000))) then
return false
end
-- Recupero la lavorazione
local bDownHead
local sMillingOnSide
-- se ho testa da sotto e lap-joint diretto verso il basso, cerco prima testa sotto
if BD.DOWN_HEAD and vtN:getZ() < BD.NZ_MINA then
bDownHead = true
sMillingOnSide = ML.FindMilling( 'SideMillAsBlade_H2', nil, nil, nil, nil, not bDownHead, bDownHead)
end
-- se non ha trovato su testa sotto, cerco su testa sopra
if not sMillingOnSide then
bDownHead = false
sMillingOnSide = ML.FindMilling( 'SideMillAsBlade', nil, nil, nil, nil, not bDownHead, bDownHead)
end
if not sMillingOnSide then
return false
end
-- Recupero i dati dell'utensile
local dToolDiamOnSide = 0
local dThickMillOnSide = 0
local dMaxDepthOnSide = 0
local dTDiamStem = 50
if EgtMdbSetCurrMachining( sMillingOnSide) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dToolDiamOnSide = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiamOnSide
dThickMillOnSide = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dThickMillOnSide
dTDiamStem = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or dTDiamStem
dMaxDepthOnSide = min( EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or 999, 0.5 * ( dToolDiamOnSide - dTDiamStem)) or dMaxDepthOnSide
end
end
local bSpecialMillOnSide = ( dDiam > dThickMillOnSide - 10 * GEO.EPS_SMALL and dFacElev < dMaxDepthOnSide + 10 * GEO.EPS_SMALL)
-- Restituisco i dati
return bSpecialMillOnSide, sMillingOnSide, dThickMillOnSide, dToolDiamOnSide, dMaxDepthOnSide
end
---------------------------------------------------------------------
local function GetFaceAdj( Proc, nFacInd, dH, dV)
-- Recupero le facce adiacenti alla principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
if not vAdj or #vAdj == 0 then
local sErr = 'Error : main face without adjacencies'
return -1, sErr
end
EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 4)
-- Riordino le dimensioni per avere dH > dV
if dH < dV then
dH, dV = dV, dH
end
-- Cerco una faccia adiacente alla principale sul lato lungo
local nFacAdj
for i = 1, #vAdj do
if vAdj[i] >= 0 then
local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
local dLen = dist( ptP1, ptP2)
if dLen > 0.5 * dH then
nFacAdj = vAdj[i]
EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 4)
break
end
end
end
if not nFacAdj then
local sErr = 'Error : main face without long adjacent face'
return -1, sErr
end
return nFacAdj
end
---------------------------------------------------------------------
local function UpdateEncumbrance( Proc, nRawId, b3Raw, b3Solid)
-- verifico siano una o due facce
if Proc.Fct > 2 then return end
-- eventuale segnalazione ingombro di testa o coda
local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * b3Raw:getDimZ())
local dMinZ = max( BD.MIN_HEIGHT, 0.35 * b3Raw:getDimZ())
-- calcolo punto massimo in Z fino a dove considerare il pinzaggio. Minimo tra pinzaggio massimo e altezza pezzo
local dMaxHZ = b3Raw:getMin():getZ() + min( BD.VICE_MAXH or BD.MAX_HEIGHT, b3Raw:getDimZ())
-- punto massimo in Z considerando anche la Z della feature
local dMaxHZFeat = min( dMaxHZ, Proc.Box:getMax():getZ())
-- dimensione Z del pinzaggio (differenza massima Z pinzabile e box feature)
local dDeltaZClamp = ( ( dMaxHZ - b3Raw:getMin():getZ()) - max( 0, dMaxHZFeat - Proc.Box:getMin():getZ()))
-- se pinzaggio minimo è come il massimo (oppure come l'altezza massima del pezzo) significa che è verticale
local bIsVertClamps = BD.VICE_MINH > BD.MAX_HEIGHT - 100 * GEO.EPS_SMALL
-- condizioni per limitare pinzaggio testa/coda
local bUpdateIng = true
-- se dimensione del box della feature maggiore di metà pinzaggio minimo o metà spessore pezzo
bUpdateIng = bUpdateIng and Proc.Box:getDimZ() > dMinHIng
-- se la feature si trova più in basso del minimo pinzabile in Z o il 35% dello spessore pezzo
bUpdateIng = bUpdateIng and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + dMinZ
-- se feature è al di sotto del pinzaggio massimo
bUpdateIng = bUpdateIng and Proc.Box:getMin():getZ() < dMaxHZ
-- se ho le morse verticali, o se la feature è in centro o verso alto, controllo se non prendo abbastanza.
if bIsVertClamps or ( Proc.Box:getMin():getZ() - b3Raw:getMin():getZ()) > BD.MIN_HEIGHT then
bUpdateIng = bUpdateIng and dDeltaZClamp < BD.VICE_MINH
end
if bUpdateIng then
if Proc.Head then
local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX()
-- se pinze a 45° e pinza abbastanza materiale, compenso comunque, ma solo inclinazione morse
if not bIsVertClamps and dDeltaZClamp > BD.VICE_MINH and BD.VICE_MAXH then
dOffs = min( dOffs, BD.VICE_MAXH - BD.VICE_MINH)
end
BL.UpdateHCING( nRawId, dOffs)
elseif Proc.Tail then
local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX()
-- se pinze a 45° e pinza abbastanza materiale, compenso comunque, ma solo inclinazione morse
if not bIsVertClamps and dDeltaZClamp > BD.VICE_MINH and BD.VICE_MAXH then
dOffs = min( dOffs, BD.VICE_MAXH - BD.VICE_MINH)
end
BL.UpdateTCING( nRawId, dOffs)
elseif Proc.Box:getCenter():getX() > b3Solid:getCenter():getX() then
local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX()
local dDist = b3Solid:getMax():getX() - Proc.Box:getMax():getX()
-- se pinze a 45° e pinza abbastanza materiale, compenso comunque, ma solo inclinazione morse
if not bIsVertClamps and dDeltaZClamp > BD.VICE_MINH and BD.VICE_MAXH then
dOffs = min( dOffs, BD.VICE_MAXH - BD.VICE_MINH)
end
BL.UpdateHCING( nRawId, dOffs, dDist)
end
end
end
---------------------------------------------------------------------
-- Verifica se feature di testa
function ProcessLapJoint.IsHeadFeature( Proc, b3Raw, dCurrOvmH)
-- se una sola faccia
if Proc.Fct == 1 then
local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
if vtN0:getX() > 0.1 then
return true
end
end
-- verifico se è in testa
if Proc.Box:getMax():getX() < b3Raw:getMax():getX() - dCurrOvmH - BD.MAX_DIST_HTFEA then
return false
end
-- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave
if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 *b3Raw:getDimX()) then
return false
end
-- recupero identificativo del pezzo
local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL)
-- se una o due facce e interessa veramente la testa, allora di testa
if Proc.Fct <= 2 then
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if Proc.Box:getMax():getX() > b3Solid:getMax():getX() - 1. then
return true
elseif Proc.Box:getMax():getX() < b3Solid:getMax():getX() - 5. then
return false
end
end
-- deve avere la normale principale diretta verso la testa
Topology.Classify( Proc, b3Raw)
local nFacInd, dElev = BL.GetFaceWithMostAdj( Proc, nPartId)
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
if vtN and vtN:getX() < 0.499 then
return false
elseif Proc.Fct >= 5 then
return true
end
-- deve occupare la maggior parte dell'area
if Proc.Box:getDimY() > 0.75 * b3Raw:getDimY() or Proc.Box:getDimZ() > 0.75 * b3Raw:getDimZ() then
return true
end
-- non è di testa
return false
end
---------------------------------------------------------------------
-- Verifica se feature di coda
function ProcessLapJoint.IsTailFeature( Proc, b3Raw)
-- se una sola faccia
if Proc.Fct == 1 then
local vtN0 = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
if vtN0:getX() < -0.1 then
return true
end
end
-- se interessa l'intera sezione
if BL.IsFeatureCuttingEntireSection( Proc.Box, b3Raw:getDimY(), b3Raw:getDimZ()) then
-- caso con due facce
if Proc.Fct == 2 then
-- verifico che il versore risultante delle normali delle due facce sia orientato verso X-
local vtResult = ( EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) + EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT))
vtResult:normalize()
if vtResult:getX() < 0.5 then
return true
end
end
end
-- in base al tipo di feature attribuisco il significato dei parametri Q
AssignQIdent( Proc)
-- se può essere fatto con utensile tipo lama
local bUseBHSideMill, bHead, bHeadDir = VerifyBHSideMill( Proc, nil, nil, nil, nil, b3Raw)
if bUseBHSideMill then
Proc.HeadDir = bHeadDir
end
-- recupero box del pezzo
local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL)
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
-- verifico se è in coda
local dEndDist = Proc.Box:getMin():getX() - b3Solid:getMin():getX()
if ( dEndDist > BD.MAX_DIST_HTFEA) or bUseBHSideMill then
if not( BD.BH_MACHINE) and bUseBHSideMill and ( Proc.Box:getMax():getX() - b3Solid:getMin():getX()) < 400 and b3Solid:getDimX() > BD.LEN_VERY_SHORT_PART then
return true
-- se Front Slot e pezzo abbastanza lungo si rimanda la decisione a più avanti
elseif not ( ( Proc.Prc == 17) and ( b3Solid:getDimX() > ( BD.LEN_VERY_SHORT_PART or BD.LEN_SHORT_PART))) then
return false
end
end
-- se lunga come trave, oppure non è trave corta e la sua lunghezza supera il massimo o il 80% della lunghezza della trave
if Proc.Box:getDimX() > b3Solid:getDimX() - 1 or
( b3Solid:getDimX() > BD.LEN_SHORT_PART and Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.8 * b3Solid:getDimX())) then
return false
end
-- se interessa la coda, e pezzo lungo, si sposta dopo separazione
if b3Solid:getDimX() > BD.LEN_SHORT_PART and Proc.AffectedFaces.Left and Proc.Fct >= 2 then
return true
end
-- se una o due facce e interessa veramente la coda, allora di coda
if Proc.Fct <= 2 then
if Proc.Box:getMin():getX() < b3Solid:getMin():getX() + 1. then
return true
elseif Proc.Box:getMin():getX() > b3Solid:getMin():getX() + 5. then
return false
end
end
-- se forzata lavorazione con lama e feature aperta sulla coda potrei lavorare anche dalla coda
if Proc.AffectedFaces.Left and ( EgtGetInfo( Proc.Id, Q_SAW_PLUS_CHAIN, 'i') or 0) > 0 then
return true
end
-- deve avere la normale principale diretta verso la coda (oppure tunnel)
Topology.Classify( Proc, b3Raw)
local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc, nPartId)
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
if vtN and vtN:getZ() < BD.NZ_MINA and nFacInd2 then
ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT)
nFacInd, nFacInd2 = nFacInd2, nFacInd
dElev, dElev2 = dElev2, dElev
end
if not vtN or vtN:getX() > -0.001 or dEndDist + vtN:getX() * dElev > 0 then
return false
else
return true
end
end
---------------------------------------------------------------------
-- Classificazione della feature
function ProcessLapJoint.Classify( Proc, b3Raw)
-- se 1 faccia
if Proc.Fct == 1 then
return true, false
-- se 2 facce
elseif Proc.Fct == 2 then
-- se può essere fatto con utensile tipo lama
local bUseBHSideMill = VerifyBHSideMill( Proc, nil, nil, nil, nil, b3Raw)
if bUseBHSideMill then
return true, false
end
-- dati delle facce
local vtN = {}
vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
-- verifico se è lavorabile solo dal basso
local vtParX = vtN[1] ^ vtN[2] ; vtParX:normalize()
local bParX = ( abs( vtParX:getX()) > 0.985)
local bSmall = ( ( Proc.Head or Proc.Tail) and Proc.Box:getDimX() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ())) or
( not ( Proc.Head or Proc.Tail) and bParX and Proc.Box:getDimY() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ()))
local bDown = ( vtN[1]:getZ() < BD.NZ_MINB and vtN[2]:getZ() < BD.NZ_MINB) or
( vtN[1]:getZ() < BD.NZ_MINA and vtN[2]:getZ() < 0.5 and ( vtN[2]:getZ() < -0.1 or not bSmall)) or
( vtN[2]:getZ() < BD.NZ_MINA and vtN[1]:getZ() < 0.5 and ( vtN[1]:getZ() < -0.1 or not bSmall))
-- se forzata la lavorazione con fresa di lato da parametro Q03=2/3 non devo ruotare; se rabbet lungo X che guarda in giù sempre fresatura di lato e quindi non ruoto
local bIsRabbetAlongXTowardsBottom = ( Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2' and ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) and Proc.AffectedFaces.Bottom and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right)
local bForceSideMill = ( bIsRabbetAlongXTowardsBottom or ( EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'd') == 2 or EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'd') == 3))
bDown = ( bDown and not BD.DOWN_HEAD and not BD.TURN and not bForceSideMill)
return true, bDown
-- se più di 2 facce
else
local bClosedOrthoFaces
local nDeletedFace
-- recupero la faccia con il maggior numero di adiacenze e minor elevazione
local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL)
local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc, nPartId)
if not nFacInd or nFacInd < 0 then
if nFacInd == -1 then
bClosedOrthoFaces = nFacInd2
else
return false
end
end
-- se è presente il rinvio angolare con lavorazioni di tasca ed è una tasca perfettamente verticale da sotto, non ruoto
if BD.ANG_TRASM and Proc.Fct >= 4 and not bClosedOrthoFaces then
if AreOppositeVectorApprox( Proc.Face[nFacInd + 1].VtN, Z_AX()) and
( Proc.Fct >= 5 and ML.FindPocketing( 'Pocket_AT') or ( Proc.Fct < 5 and ML.FindPocketing( 'OpenPocket_AT'))) then
return true, false
end
end
-- se groove da sotto e possibile fresatura tipo SideMillAsBlade non ruoto
if Proc.AllRightAngles and ( Proc.Topology == 'Groove' or Proc.Topology == 'Pocket') and not( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) and AreOppositeVectorApprox( Proc.Face[nFacInd + 1].VtN, Z_AX()) then
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
if VerifySideMillAsSaw( Proc, nAddGrpId, Proc.Face[nFacInd + 1].VtN, min( Proc.Face[nFacInd + 1].Height, Proc.Face[nFacInd + 1].Width) , Proc.Face[nFacInd + 1].Elevation) then
Proc.OkFromBottom = true
return true, false
end
end
-- se scanalatura chiusa lavoro la faccia di fondo
if Proc.Topology == 'Pocket' and ( Proc.IsParallel or Proc.AllRightAngles) and not bClosedOrthoFaces then
nFacInd = Topology.GetFacesWithGivenAdjacencyNumber( Proc, nil, 4)[1]
nFacInd2 = nil
dElev = Proc.Face[ nFacInd + 1].Elevation
end
-- se facce formano un tunnel e sono ortogonali
if bClosedOrthoFaces then
-- ottengo le dimensioni del tunnel
local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
EgtErase( nSurfInt)
-- verifico se può essere fatto con svuotatura
if VerifyPocket( Proc, dDimMin) then
return true, false
elseif VerifyChainSaw( Proc, dDimMin, dDimMax) then
return true, false
else
return false
end
else
-- dati della faccia
local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
-- se può essere fatto con utensile tipo lama
local bUseBHSideMill, _, _, _, _, dTDiam = VerifyBHSideMill( Proc, nil, nil, nil, nil, b3Raw)
if bUseBHSideMill then
if vtN:getZ() > -0.5 or b3Raw:getDimZ() - Proc.Box:getDimZ() < ( BD.MAX_DIST_BH_FROM_BOTTOM or 395) - dTDiam / 2 then
return true, false
else
return true, true
end
-- altrimenti controllo se deve essere ruotato con le altre lavorazioni
else
-- cerco se c'è faccia adiacente sul lato più lungo
local nFaceAdj = GetFaceAdj( Proc, nFacInd, dH, dV) or -1
local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2)
-- verifico se è lavorabile solo dal basso
local bDown = ( vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD and not BD.TURN)
-- se verso il basso, verifico se utilizzabile seconda faccia
if bDown then
local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc))
-- se forzata la lavorazione con fresa di lato da parametro Q03=2/3 non devo ruotare
local nSideRoughTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'd')
local bForceSideMill = ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) and ( nSideRoughTool == 2 or nSideRoughTool == 3) and ( Proc.Fct == 3 or Proc.Fct == 4)
if bForceSideMill then
bDown = false
elseif nFacInd2 and dElev2 < 160 and dElev2 < 2 * dElev then
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT)
bDown = ( vtN2:getZ() < BD.NZ_MINB)
elseif not nFacInd2 and bIsL and nFaceAdj >= 0 then
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFaceAdj, GDB_ID.ROOT)
bDown = ( vtN2:getZ() < BD.NZ_MINB)
end
-- verifico se la faccia principale è sottosquadra, ha forma L ed esiste la faccia adiacente
elseif vtN:getZ() < -0.2589 and bIsL and nFaceAdj >= 0 then
-- box del pezzo
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
-- se più di 2 facce o il box della feature supera una certa distanza dalle teste allora controllo Nz della faccia ausiiaria
if Proc.Fct > 2 or ( Proc.Box:getMax():getX() < b3Solid:getMin():getX() - 150) or ( Proc.Box:getMin():getX() > b3Solid:getMax():getX() + 150) then
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFaceAdj, GDB_ID.ROOT)
bDown = ( vtN2:getZ() < BD.NZ_MINB)
end
end
local bNoRotation = ( EgtGetInfo( Proc.Id, Q_CHAINSAW_FROM_SIDE, 'i') or 0) == 1
if bDown and bNoRotation then
bDown = false
end
return true, bDown
end
end
end
end
---------------------------------------------------------------------
-- Lavorazione con fresa
---------------------------------------------------------------------
local function MakeOneFaceByMill( Proc, nPhase, nRawId, nPartId)
-- recupero l'ingombro del grezzo di appartenenza
local b3Raw = EgtGetRawPartBBox( nRawId)
-- recupero l'ingombro della trave
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- verifico il numero di facce della tacca
assert( ( Proc.Fct == 1), 'Error : MakeOneFaceByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces')
-- dati della faccia
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
-- verifico se orientata verso l'alto
local bUp = ( vtN:getZ() >= BD.NZ_MINA)
-- scelta faccia da lavorare
local nFacInd = 0
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'BirdsMouth')
if not sMilling then
local sErr = 'Error : BirdsMouth not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione di fresatura
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto uso faccia e lato correzione
if vtN:getX() > 0 then
EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_LEFT, MCH_MILL_FU.PARAL_LEFT))
else
EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_RIGHT, MCH_MILL_FU.PARAL_RIGHT))
end
-- imposto lato di correzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
if not bUp then
EgtSetMachiningParam( MCH_MP.INVERT, true)
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
end
-- imposto posizione braccio porta testa
if vtN:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- eventuale segnalazione ingombro di testa o coda
UpdateEncumbrance( Proc, nRawId, b3Raw, b3Solid)
return true
end
---------------------------------------------------------------------
local function MakeTwoFacesByMill( Proc, nPhase, nRawId, nPartId, bDownHead)
-- recupero l'ingombro del grezzo di appartenenza
local b3Raw = EgtGetRawPartBBox( nRawId)
-- recupero l'ingombro della trave
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- verifico il numero di facce della tacca
assert( ( Proc.Fct == 2), 'Error : MakeTwoFacesByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces')
-- recupero il parametro Q per uso fresa
local nUseRM = EgtGetInfo( Proc.Id, Q_USE_MILL, 'i')
-- recupero la lavorazione
local sMilling
if nUseRM and nUseRM == 1 then
sMilling = ML.FindMilling( 'LongSmallCut', nil, nil, nil, nil, not bDownHead, bDownHead)
else
sMilling = ML.FindMilling( 'BirdsMouth', nil, nil, nil, nil, not bDownHead, bDownHead)
end
if not sMilling then
local sErr = 'Error : LongSmallCut & BirdsMouth not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dTDiam = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
end
-- 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)
-- dati medi
local ptM = ( ptC[1] + ptC[2]) / 2
-- verifico non siano orientate verso il basso
local bFaceOk = {}
bFaceOk[1] = ( vtN[1]:getZ() >= BD.NZ_MINB)
bFaceOk[2] = ( vtN[2]:getZ() >= BD.NZ_MINB)
if not bDownHead and not BD.TURN and not bFaceOk[1] and not bFaceOk[2] then
local sErr = 'Error : LapJoint from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- scelta faccia da lavorare
local nFacInd
-- se entrambe possibili
if bFaceOk[1] and bFaceOk[2] then
-- se in testa, scelgo quella orientata verso la testa
if Proc.Head then
if vtN[1]:getX() > vtN[2]:getX() then
nFacInd = 0
else
nFacInd = 1
end
-- se altrimenti in coda, scelgo quella orientata verso la coda
elseif Proc.Tail then
if vtN[1]:getX() < vtN[2]:getX() then
nFacInd = 0
else
nFacInd = 1
end
-- altrimenti, scelgo quella con la normale più perpendicolare all'asse trave (se uguali, quella verso X+)
else
if abs( abs( vtN[1]:getX()) - abs( vtN[2]:getX())) < GEO.EPS_SMALL then
if ptM:getX() > b3Raw:getCenter():getX() then
nFacInd = EgtIf( vtN[1]:getX() > vtN[2]:getX(), 0, 1)
else
nFacInd = EgtIf( vtN[1]:getX() < vtN[2]:getX(), 0, 1)
end
else
nFacInd = EgtIf( abs( vtN[1]:getX()) < abs( vtN[2]:getX()), 0, 1)
end
end
elseif bFaceOk[1] then
nFacInd = 0
else
nFacInd = 1
end
local nOthInd = 1 - nFacInd
local sName
local nMchFId
local nFaceUse
-- se forzato uso fresa controllo se posso fare in una o più passate
if nUseRM and nUseRM == 1 then
-- prendo la larghezza della faccia
local _, pPt1, pPt2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nOthInd, GDB_ID.ROOT)
local dDistPoint = dist( pPt1, pPt2)
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
local dWidth = EgtIf( abs( dDistPoint - dH) < abs( dDistPoint - dV), dV, dH)
-- se larghezza faccia maggiore diametro utensile aggiungo una lavorazione
if dTDiam > 0 and dWidth > dTDiam then
-- inserisco la lavorazione di fresatura
sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_1'
nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto uso faccia e lato correzione
nFaceUse = BL.GetNearestOrthoOpposite( vtN[nOthInd+1])
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto lato di correzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- tolgo l'inversione
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- aggiungo offset laterale
EgtSetMachiningParam( MCH_MP.OFFSR , (dTDiam/2))
-- imposto posizione braccio porta testa
if vtN[nFacInd+1]:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
end
-- inserisco la lavorazione di fresatura
sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto uso faccia e lato correzione
nFaceUse = BL.GetNearestOrthoOpposite( vtN[nOthInd+1])
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto lato di correzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- tolgo l'inversione
EgtSetMachiningParam( MCH_MP.INVERT, false)
-- imposto posizione braccio porta testa
if vtN[nFacInd+1]:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- eventuale segnalazione ingombro di testa o coda
UpdateEncumbrance( Proc, nRawId, b3Raw, b3Solid)
return true
end
---------------------------------------------------------------------
local function MakePreCuts( Proc, nPhase, nRawId, nPartId, dOvmHead, b3Raw, nChamfer)
-- se interessa l'intera sezione della trave, necessaria sgrossatura
if nChamfer < 2 and Proc.Box:getDimY() > 0.9 * b3Raw:getDimY() and Proc.Box:getDimZ() > 0.9 * b3Raw:getDimZ() then
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo sgrossatura e la lavoro
local AddId = EgtSurfTmConvexHullInBBox( nAddGrpId, Proc.Id, b3Raw, GDB_RT.GLOB)
if AddId then
EgtSetName( AddId, 'AddCut_' .. tostring( Proc.Id))
-- applico lavorazione
local CutProc = { Id = AddId, Grp = Proc.Grp, Prc = Proc.Prc, Box = Proc.Box, Fct = Proc.Fct, Flg = Proc.Flg,
Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId, PartId = Proc.PartId}
CutProc.AffectedFaces = BL.GetProcessAffectedFaces( CutProc)
local nCutFacet = EgtSurfTmFacetCount( AddId)
if nCutFacet == 1 then
return Cut.Make( CutProc, nPhase, nRawId, nPartId, dOvmHead)
elseif nCutFacet == 2 then
return DoubleCut.Make( CutProc, nPhase, nRawId, nPartId, dOvmHead)
end
end
end
return true
end
---------------------------------------------------------------------
local function MakeByMill( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dElev, dCollSic, bSpecialApp, sMillMaster, nFacInd2, dFacElev2)
-- Cerco una faccia adiacente alla principale sul lato lungo
local nFacAdj, sErr = GetFaceAdj( Proc, nFacInd, dH, dV)
if nFacAdj < 0 then
EgtOutLog( sErr)
return false, sErr
end
-- Determino se estremi aperti o chiusi e faccia adiacente da aggiungere alla lavorazione
local bOpenStart = false
local bOpenEnd = false
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1]
EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3)
local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacAdj, GDB_ID.ROOT)
-- Riordino le dimensioni per avere dH > dV
if dH2 < dV2 then
dH2, dV2 = dV2, dH2
end
local nFacAdj2
for j = 1, #vAdj2 do
if vAdj2[j] == nFacInd then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == nFacInd do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == nFacInd do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
end
-- decommentare questa parte per concatenare due facce
--if bSpecialApp and vAdj2[j] >= 0 then
-- local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacAdj, vAdj2[j], GDB_ID.ROOT)
-- local dLen = dist( ptP1, ptP2)
-- if abs( dLen - dV2) < 10 * GEO.EPS_SMALL then
-- nFacAdj2 = vAdj2[j]
-- end
--end
end
-- Recupero la lavorazione di fresa
local sMilling
if bSpecialApp then
sMilling = sMillMaster
else
sMilling = ML.FindMilling( 'LongSmallCut')
if not sMilling then
sErr = 'Error : LongSmallCut not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
-- recupero i dati dell'utensile
local dTDiam = 50
local dMaxMat = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat
end
end
-- Se massimo materiale utensile è molto inferiore dell'elevazione non faccio la lavorazione e do un warning
if dMaxMat > 0 and dMaxMat + 15 < dElev + dCollSic then
sWarn = 'Warning : skipped milling; elevation bigger than max tool depth'
return true, sWarn, dMaxMat
end
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ())
-- inserisco la lavorazione di fresatura
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
if nFacAdj2 then
EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj},{ Proc.Id, nFacAdj2}})
else
EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}})
end
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_YM
if rfFac:getVersZ():getY() > 100 * GEO.EPS_ZERO then
nSCC = MCH_SCC.ADIR_YP
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- lato di lavoro e direzione
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
EgtSetMachiningParam( MCH_MP.INVERT, true)
-- tipo di attacco e uscita
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR)
-- imposto accorciamento iniziale/finale per estremi aperti/chiusi
if bSpecialApp then
-- applico gli allungamenti o accorciamenti considerando che la lavorazione è invertita
if nFacAdj2 then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, dTDiam / 2, - dTDiam / 2))
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, dTDiam / 2, - dTDiam / 2))
-- confronto la faccia applicata nella lavorazione(faccia adiacente) con la seconda faccia passata nella funzione
-- se corrispondono allora aggiungo una estensione nei lati chiusi pari all'elevazione della stessa faccia corrispondente
if nFacAdj == nFacInd2 then
if not bOpenStart then
EgtSetMachiningParam( MCH_MP.LOPERP, dFacElev2)
end
if not bOpenEnd then
EgtSetMachiningParam( MCH_MP.LIPERP, dFacElev2)
end
end
end
-- applico elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, 0, - dTDiam / 2))
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, 0, - dTDiam / 2))
end
-- eseguo
if not ML.ApplyMachining( true, false) then
_, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
return true, '', dTDiam
end
---------------------------------------------------------------------
local function ChooseCorner( Proc, nFacInd)
-- Recupero le adiacenze della faccia principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
-- Cerco i corner tra le facce adiacenti alla principale
local tFacAdj = {}
for i = 1, #vAdj do
if vAdj[i] >= 0 then
for j = i+1, #vAdj do
if vAdj[j] >= 0 then
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, vAdj[i], vAdj[j], GDB_ID.ROOT)
if ptP1 and ptP2 and dAng < 0 then
local dLen = dist( ptP1, ptP2)
table.insert( tFacAdj, { vAdj[i], vAdj[j], dLen, ptP1, ptP2, dAng})
end
end
end
end
end
-- Tra le linee dei corner determino la più lunga
local dMaxLen = 0
local nIdLine
for i = 1, #tFacAdj do
if tFacAdj[i][3] > dMaxLen then
nIdLine = i
dMaxLen = tFacAdj[i][3]
end
end
return dMaxLen, nIdLine, tFacAdj
end
---------------------------------------------------------------------
local function ChooseContour( Proc, nFacInd, bVerifyCorner)
-- Recupero le adiacenze della faccia principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
-- Se richiesto, verifico che ci siano facce adiacenti consecutive (sicuramente con angolo)
if bVerifyCorner then
local bCorner = false
for i = 1, #vAdj do
local j = EgtIf( i > 1, i - 1, #vAdj)
if vAdj[i] >= 0 and vAdj[j] >= 0 then
bCorner = true
break
end
end
if not bCorner then return {} end
end
-- Cerco le facce adiacenti con angolo convesso
local tFacAdjMain = {}
for i = 1, #vAdj do
if vAdj[i] >= 0 then
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
if ptP1 and ptP2 and dAng < 0 then
local dLen = dist( ptP1, ptP2)
table.insert( tFacAdjMain, { vAdj[i], dLen, ptP1, ptP2, dAng})
end
end
end
return tFacAdjMain
end
---------------------------------------------------------------------
local function CheckToInvert( AuxId, bPositive)
-- recupero versore estrusione
local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
-- faccio una copia del percorso
local sParnt = EgtGetParent( AuxId)
local nNewEntId = EgtCopyGlob( AuxId, sParnt)
-- chiudo il percorso
if EgtCloseCurveCompo( nNewEntId) then
local vtMPlane, dDist, dArea = EgtCurveArea( nNewEntId)
-- cancello percorso copia
EgtErase( nNewEntId)
if dArea and abs(dArea) > 1 then
local frEnt = EgtGetGlobFrame( AuxId)
if vtMPlane then
vtMPlane:toGlob(frEnt)
if dArea and dArea * ( vtMPlane * vtExtr) < 0 then
if bPositive then
return true
end
elseif dArea and dArea * ( vtMPlane * vtExtr) > 0 then
if not bPositive then
return true
end
end
end
end
else
-- cancello percorso copia
EgtErase(nNewEntId)
end
return false
end
---------------------------------------------------------------------
---
---@param Proc table la feature
---@param vtTool Vector3d il vettore direzione utensile
---@return number dAngle angolo tra la faccia d'ingresso e la direzione utensile
---@return number dSinAngle seno dell'angolo
---@return number dCosAngle coseno dell'angolo
---@return number|nil dTanAngle tangente dell'angolo
local function GetToolEntryAngle( Proc, vtTool)
local dSinAngle = -10 * GEO.EPS_SMALL
local vtNorm
if Proc.AffectedFaces.Top then
vtNorm = Z_AX()
dSinAngle = max( dSinAngle, vtTool * vtNorm)
end
if Proc.AffectedFaces.Bottom then
vtNorm = -Z_AX()
dSinAngle = max( dSinAngle, vtTool * vtNorm)
end
if Proc.AffectedFaces.Front then
vtNorm = -Y_AX()
dSinAngle = max( dSinAngle, vtTool * vtNorm)
end
if Proc.AffectedFaces.Back then
vtNorm = Y_AX()
dSinAngle = max( dSinAngle, vtTool * vtNorm)
end
if Proc.AffectedFaces.Left then
vtNorm = -X_AX()
dSinAngle = max( dSinAngle, vtTool * vtNorm)
end
if Proc.AffectedFaces.Right then
vtNorm = X_AX()
dSinAngle = max( dSinAngle, vtTool * vtNorm)
end
local dCosAngle = sqrt( 1 - sqr( dSinAngle))
local dAngle = acos( dCosAngle)
local dTanAngle
if dAngle ~= 0 and dAngle ~= 90 then
dTanAngle = sqrt( 1 - dCosAngle * dCosAngle) / dCosAngle
end
return dAngle, dSinAngle, dCosAngle, dTanAngle
end
---------------------------------------------------------------------
local function MakeRoundCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiam, bMillDown, bDoubleSide)
-- recupero la lavorazione senza considerare l'elevazione
local sMilling = ML.FindMilling( 'SmallToolContour', nil, nil, nil, nil, not ( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide)
if not sMilling then
local sMyWarn = 'Warning : SmallToolContour not found in library'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- recupero i dati dell'utensile
local dTDiam = 50
local dTMaxDepth = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
dTMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTMaxDepth
end
end
-- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco
if dTDiam > ( 0.75 * dDiam) then
local sMyWarn = 'Warning : tool diameter not enough small'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- ottengo gli angoli dove applicare il percorso con fresa più piccola
local _, _, tFacAdj = ChooseCorner( Proc, nFacInd)
-- se non trovato nessun angolo interno valido esco
if #tFacAdj == 0 then
return true
end
-- recupero la normale della faccia di fondo
local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
-- se fresatura da sotto salto la lavorazione
if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then
local sErr = 'Error : milling from bottom '
EgtOutLog( sErr)
return false, sErr
end
-- ciclo su tutti gli angoli trovati
local sMyWarn = ''
for i = 1, #tFacAdj do
local pAuxId = {}
-- le 2 facce di contatto devono essere perpendicolari e non sottosquadra rispetto alla faccia di fondo
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][1], GDB_ID.ROOT)
local _, ptP1x, ptP2x, dAngx = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][2], GDB_ID.ROOT)
if dAng >= 0 or dAng < -90 - 10 * GEO.EPS_SMALL or dAngx >= 0 or dAngx < -90 - 10 * GEO.EPS_SMALL then
goto continue
end
-- prendo la lunghezza di adiacenza delle due linee
local dLen1 = dist( ptP1, ptP2)
local dLen2 = dist( ptP1x, ptP2x)
-- cerco il punto tra le 3 facce: nIdEndPoint
local nIdIniPoint
local nIdEndPoint
if ptP1 and ptP2 then
if dist( ptP1, tFacAdj[i][4]) < GEO.EPS_SMALL or dist( ptP2, tFacAdj[i][4]) < GEO.EPS_SMALL then
nIdEndPoint = 4
nIdIniPoint = 5
elseif dist( ptP1, tFacAdj[i][5]) < GEO.EPS_SMALL or dist( ptP2, tFacAdj[i][5]) < GEO.EPS_SMALL then
nIdEndPoint = 5
nIdIniPoint = 4
end
end
-- devo avere un punto comune
if not nIdEndPoint then
goto continue
end
-- calcolo lunghezza minima in base all'angolo tra le due pareti
local dMinDist = (( dDiam / 2) / tan( ( 180 + tFacAdj[i][6]) / 2)) + 2
-- verifico che entrambe le linee siano maggiori delle lunghezza minima
if dLen1 <= dMinDist or dLen2 <= dMinDist then
sMyWarn = 'Warning : impossible make clean corner path'
goto continue
end
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
local ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1) < 10 * GEO.EPS_SMALL, ptP2, ptP1)
-- prima linea
local nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[i][nIdEndPoint], GDB_RT.GLOB)
-- calcolo arretramento
local dTrimDist = dLen1 - dMinDist
-- se arretramento valido
if dTrimDist > 100 * GEO.EPS_SMALL then
EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint , GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- se il punto finale corrisponde con il punto comune, uso l'altro
ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1x) < 10 * GEO.EPS_SMALL, ptP2x, ptP1x)
-- seconda linea
nAuxId = EgtLine( nAddGrpId, tFacAdj[i][nIdEndPoint], ptApPoint, GDB_RT.GLOB)
-- calcolo arretramento
dTrimDist = dLen2 - dMinDist
-- se arretramento valido
if dTrimDist > 100 * GEO.EPS_SMALL then
EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint , GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- trasformo in percorso
local AuxId
if #pAuxId > 0 then
AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true)
end
-- deve esserci il percorso
if not AuxId then
sMyWarn = 'Warning : impossible make clean corner path'
goto continue
end
-- modifico versore direzione
EgtModifyCurveExtrusion( AuxId, vtN1, GDB_RT.GLOB)
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling
goto continue
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- imposto lato di lavoro sinistro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- tipo attacco e uscita
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
-- annullo allungamenti iniziale e finale
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
-- setto massimo affondamento possibile
local dDepth = 0
if tFacAdj[i][3] > dTMaxDepth then
dDepth = dTMaxDepth - tFacAdj[i][3]
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- setto se devo invertire il percorso
local bInvert = CheckToInvert( AuxId, true)
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( ( tFacAdj[i][3] + dDepth), 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if ML.ApplyMachining( true, false) then
_, sMyWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
end
-- altrimenti lavorazione non applicata
else
_, sMyWarn = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
end
::continue::
end
if #sMyWarn > 0 then
EgtOutLog( sMyWarn)
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeRoundCleanContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiam, nFunction, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid,
dDepth, bOneShot)
-- recupero la lavorazione senza considerare l'elevazione perché viene calcolata l'elevazione utile
local sMilling = ML.FindMilling( 'SmallToolContour', nil, nil, nil, nil, not( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide)
if not sMilling then
local sMyWarn = 'Warning : SmallToolContour not found in library'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- recupero i dati dell'utensile
local dTDiam = 50
local dTMaxDepth = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
dTMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTMaxDepth
end
end
local sMillingDn = ML.FindMilling( 'SmallToolContour', nil, nil, nil, nil, not( bMillDown and bDoubleSide), bMillDown and bDoubleSide)
if not sMillingDn then
local sMyWarn = 'Warning : Opposite SmallToolContour not found in library'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- recupero i dati dell'utensile testa da sotto
local dTDiamDn = 50
local dTMaxDepthDn = 0
if EgtMdbSetCurrMachining( sMillingDn) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dTDiamDn = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiamDn
dTMaxDepthDn = EgtTdbGetCurrToolMaxDepth() or dTMaxDepthDn
end
end
-- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco
if dTDiam > ( 0.75 * dDiam) then
local sMyWarn = 'Warning : tool diameter not enough small'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
local vtN1
local nFirstId, nNumId
local dMaxElev
local dCollSic = 0
local dExtraDepth = 0
-- se non ho la faccia aggiunta
if not nPathInt then
-- cerco gli angoli dove applicare il percorso con fresa piú piccola e i lati in comune
local tFacAdjMain = ChooseContour( Proc, nFacInd, true)
-- se non trovato nessun angolo interno da pulire esco
if #tFacAdjMain == 0 then
return true
end
-- normale alla faccia di fondo
vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
-- se fresatura da sotto salto la lavorazione
if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then
local sErr = 'Error : milling from bottom'
EgtOutLog( sErr)
return false, sErr
end
-- distanza di sicurezza per evitare collisioni
dCollSic = BL.CalcCollisionSafety( vtN1)
-- elevazione massima della faccia
dMaxElev = BL.GetFaceElevation( Proc, nFacInd, b3Solid)
-- ciclo tutta la tabella
local tPaths = {}
local ptIniPath
local ptMidDist
local dMaxLen = 0
for i = 1, #tFacAdjMain do
-- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo
local ptP1, ptP2, dAng
ptP1 = tFacAdjMain[i][3]
ptP2 = tFacAdjMain[i][4]
dAng = tFacAdjMain[i][5]
if ( dAng < 0 and dAng >= -90 - 10 * GEO.EPS_SMALL) then
-- creo la linea da P1 a P2
local nAuxId = EgtLine( nAddGrpId, ptP1, ptP2, GDB_RT.GLOB)
table.insert( tPaths, nAuxId)
-- prendo la lunghezza massima e il punto medio
if tFacAdjMain[i][2] > dMaxLen then
ptIniPath = ptP1
dMaxLen = tFacAdjMain[i][2]
ptMidDist = ( ptP1 + ptP2) / 2
end
end
end
-- costruisco il/i percorso/i
nFirstId, nNumId = EgtCurveCompoByReorder( nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB)
if nFirstId then
-- se un solo percorso e chiuso cambio il punto di inizio nell'entitá piú lunga
if nNumId == 1 and EgtCurveIsClosed( nFirstId) then
EgtChangeClosedCurveStartPoint( nFirstId, ptMidDist, GDB_RT.GLOB)
end
-- modifico versore direzione
for i = 1, nNumId do
EgtModifyCurveExtrusion( nFirstId + i - 1, vtN1, GDB_RT.GLOB)
end
end
-- alrimenti ho la faccia aggiunta
else
-- assegno il percorso
nFirstId = EgtCopyGlob( nPathInt, nAddGrpId)
nNumId = 1
-- distanza di sicurezza per evitare collisioni
dCollSic = BL.CalcCollisionSafety( vtOrtho)
-- calcolo elevazione dalla faccia trasversale aggiunta
local dSurfIntElev = BL.GetFaceElevation( nSurfInt, 0, b3Solid)
if bDoubleSide then
dMaxElev = dSurfIntElev
else
dMaxElev = dDepth
-- se la precedente svuotatura è stata fatta completamente in una sola volta
-- valuto di nuovo se devo fare due passate o una sola
if bOneShot then
-- se non è possibile svuotare completamente da una sola parte
if dTMaxDepth <= ( dMaxElev + BD.CUT_EXTRA + dCollSic) then
bDoubleSide = true
dMaxElev = BL.GetFaceElevation( nSurfInt, 0, b3Solid)
else
dExtraDepth = dMaxElev - BL.GetFaceElevation( nSurfInt, 0, b3Solid)
end
-- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie
else
dExtraDepth = dMaxElev - BL.GetFaceElevation( nSurfInt, 0, b3Solid)
end
end
-- normale alla faccia aggiunta
vtN1 = Vector3d( vtOrtho)
-- imposto i lati aperti
BL.SetOpenSide( nFirstId, b3Solid)
BL.ChangeOrOpenStart( nFirstId, 2)
end
-- se non trovato il percorso, esco
if not nFirstId then
local sMyWarn = 'Warning : impossible make clean corner path'
EgtOutLog( sMyWarn)
return true, sMyWarn
end
-- assegno lavorazioni ad ogni percorso
local sMyWarn = ''
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling
goto continue
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ nIdPath, -1}})
-- imposto lato di lavoro sinistro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- inversione direzione utensile
local bInvertMach = false
if nPathInt then
-- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale)
if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
-- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti
elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
end
end
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- gestione attacco e uscita
if EgtCurveIsClosed( nIdPath) then
-- attacco e uscita a quarto di cerchio senza allungamenti a inizio e fine
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, 0.5 * dTDiam)
EgtSetMachiningParam( MCH_MP.LIELEV, 0)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
else
-- nessun attacco e uscita, allungo inizio e fine di raggio utensile + 5mm (per evitare controllo collisioni)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2 + 5)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2 + 5)
end
-- setto massimo affondamento possibile
local dMachDepth = 0
if ( dMaxElev + dCollSic) > dTMaxDepth then
dMachDepth = dTMaxDepth - ( dMaxElev + dCollSic)
end
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth + dExtraDepth)
-- setto se devo invertire il percorso
local bInvert = CheckToInvert( nIdPath, true)
EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertMach, not bInvert, bInvert))
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev + dMachDepth, 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if ML.ApplyMachining( true, false) then
_, sMyWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
end
-- altrimenti lavorazione non applicata
else
_, sMyWarn = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
end
-- se devo applicare la contornatura anche sul lato opposto
if bDoubleSide then
if bMillDown then
sMilling = sMillingDn
dTDiam = dTDiamDn
dTMaxDepth = dTMaxDepthDn
end
sName = 'CleanOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling
goto continue
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ nIdPath, -1}})
-- imposto lato di lavoro sinistro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- imposto direzione utensile opposta
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- tipo attacco e uscita
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
-- allungo inizio e fine di 3/4 del diametro utensile
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam * 0.75)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam * 0.75)
-- setto massimo affondamento possibile
local dMachDepth = 0
if ( dMaxElev + dCollSic) > dTMaxDepth then
dMachDepth = dTMaxDepth - ( dMaxElev + dCollSic)
end
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth)
-- setto se devo invertire il percorso
local bInvert = CheckToInvert( nIdPath, true)
EgtSetMachiningParam( MCH_MP.INVERT, not bInvert)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev + dMachDepth, 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if ML.ApplyMachining( true, false) then
_, sMyWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
end
-- altrimenti lavorazione non applicata
else
_, sMyWarn = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
end
end
::continue::
end
if #sMyWarn > 0 then
EgtOutLog( sMyWarn)
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiam, nFunction, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid,
dDepth, bOneShot)
-- se modalitá pulitura spigoli e lavorazione di lato forzo a fare il contorno
if nFunction == 2 and nPathInt then
nFunction = 1
end
-- se richiesta pulitura del contorno
if nFunction == 1 then
return MakeRoundCleanContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiam, nFunction, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid,
dDepth, bOneShot)
-- se richiesta pulitura dei soli corner
elseif nFunction == 2 then
return MakeRoundCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiam, bMillDown, bDoubleSide)
-- altri casi non previsti
else
return true
end
end
---------------------------------------------------------------------
local function MakeSharpCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam)
local sMyWarn = ''
local pAuxId = {}
local nAuxId
local AuxId
local ptApPoint
local dLenTrimExt
local sMilling
local dMaxDepth = 0
-- cerco l'angolo di riferimento dove applicare il percorso di pulitura, altrimenti esco
local _, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd)
if #tFacAdj == 0 then
return true
end
-- prendo il primo versore
local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local vtN3 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT)
-- trovo il punto sulla superfice di riferimento
local _, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local nIdIniPoint
local nIdEndPoint
if ptLocP1 and ptLocP2 then
if dist( ptLocP1, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL or dist( ptLocP2, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL then
nIdEndPoint = 4
nIdIniPoint = 5
elseif dist( ptLocP1, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL or dist( ptLocP2, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL then
nIdEndPoint = 5
nIdIniPoint = 4
end
end
-- versore direzione
local vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint]
vtExtr:normalize()
-- inserisco le prime tre linee
if nIdIniPoint and nIdEndPoint then
-- se fresatura da sotto salto la lavorazione
if vtExtr:getZ() < BD.DRILL_VZ_MIN then
local sErr = 'Error : clean corner milling from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- sommo i tre versori per avre una direzione media
vtExtr = vtN1 + vtN2 + vtN3
vtExtr:normalize()
-- recupero la lavorazione non calcolando l'elevazione
sMilling = ML.FindMilling( 'CleanCorner', ( 0.5 * dDiam))
if not sMilling then
local sErr = 'Error : CleanCorner not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile ( temporaneo, per compensare errore nella lavorazione)
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth
end
end
-- l'altezza di taglio del tagliente corrisponde al raggio del raccordo che si riesce a coprire
-- quindi confronto l'elevazione con il raggio utensile utilizzato per la svuotatura
if dMaxDepth < ( dDiam * 0.5) - 100 * GEO.EPS_SMALL then
sMyWarn = 'Warning : skip clean corner (the cut heigth is smaller to machine the corner radius)'
EgtOutLog( sMyWarn)
return false, sMyWarn
end
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdIniPoint], tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB)
dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - (( dDiam/2) + 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 , GDB_RT.GLOB)
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- inserisco le ultime tre linee + uscita discostata rispetto all'ingresso
-- trovo il secondo punto sulla superfice di riferimento
_, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][2], GDB_ID.ROOT)
if ptLocP1 and ptLocP2 then
-- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro
if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then
ptApPoint = ptLocP2
else
ptApPoint = ptLocP1
end
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB)
dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - (( dDiam/2) + 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 , GDB_RT.GLOB)
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB)
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- piccolo scostamento di 2mm dall'angolo
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- ultima linea di risalita
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), tFacAdj[nIdLine][nIdIniPoint] + ( 2 * vtExtr), GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
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)
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- tipo attacco e uscita
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
-- allungo inizio e fine di 10mm
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10)
-- setto affondamento 0
EgtSetMachiningParam( MCH_MP.DEPTH, 0)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxDepth, 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
else
local _, sWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
return false, sWarn
else
return true, ( sMyWarn or sWarn)
end
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeDrillOnCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam, bSpecialMach)
local sMyWarn = ''
-- ottengo l'angolo dove applicare il foro
local dMaxLen, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd)
-- se non trovato nessun angolo interno valido esco
if #tFacAdj == 0 then
return true, sMyWarn
end
-- trovo il punto sulla superfice di riferimento
local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local nIdIniPoint
local nIdEndPoint
if ptLocP1 and ptLocP2 then
if ( dist( ptLocP1, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL) then
nIdEndPoint = 4
nIdIniPoint = 5
elseif ( dist( ptLocP1, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL) then
nIdEndPoint = 5
nIdIniPoint = 4
end
end
-- inserisco foro
if nIdIniPoint and nIdEndPoint then
local vtExtr
if bSpecialMach then
local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
local _, vtN1 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT)
local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT)
vtExtr = vtN0 + vtN1 + vtN2
else
-- versore direzione
vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint]
end
vtExtr:normalize()
-- se foratura da sotto salto la lavorazione
if vtExtr:getZ() < BD.DRILL_VZ_MIN then
local sErr = 'Error : drilling from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
-- recupero la lavorazione
local sDrilling, nType = ML.FindDrilling( dDiam)
if not sDrilling then
local sErr = 'Error : drilling not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- recupero i dati dell'utensile
local dMaxDepth = 20
local dDiamTool = 20
local dDiamTh = 35
local bIsDrilling
if EgtMdbSetCurrMachining( sDrilling) then
bIsDrilling = ( EgtMdbGetCurrMachiningParam( MCH_MP.TYPE) == MCH_MY.DRILLING)
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
if bIsDrilling then
dMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth
else
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
end
dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
dDiamTh = EgtTdbGetCurrToolThDiam()
end
end
-- se foro inclinato, limito il massimo affondamento
local CosB = abs( vtExtr:getX())
if CosB < BD.DRILL_VX_MAX then
local TgA = CosB / sqrt( 1 - CosB * CosB)
dMaxDepth = dMaxDepth - dDiamTh / 2 * TgA
else
dMaxDepth = 0
end
-- setto griglia
if bSpecialMach then
EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdEndPoint], vtExtr))
else
EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdIniPoint], vtExtr))
end
-- creo geometria
local AuxId = EgtCircle( nAddGrpId, {0,0,0}, EgtIf( bIsDrilling, dDiamTool/2, ( dDiamTool/2) + 0.1), GDB_RT.GRID)
-- riporto la griglia a globale
EgtSetGridFrame()
-- calcolo spessore
local dDepthBore = dMaxLen
if bSpecialMach then
-- calcolo l'elevazione
local dLenIn, dLedOut = BL.GetPointDirDepth( nPartId, tFacAdj[nIdLine][nIdEndPoint], vtExtr)
if dLenIn > 0 then
dDepthBore = dLenIn
elseif dLedOut then
dDepthBore = dLedOut
end
EgtModifyCurveThickness( AuxId, dDepthBore)
else
EgtModifyCurveThickness( AuxId, -dMaxLen)
end
-- inserisco la lavorazione
local sName = 'Drill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = EgtAddMachining( sName, sDrilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sDrilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.ADIR_YM
if vtExtr:getY() > 100 * GEO.EPS_ZERO then
nSCC = MCH_SCC.ADIR_YP
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- aggiusto l'affondamento
local dDepth
if bSpecialMach then
dDepth = dDepthBore
else
dDepth = dMaxLen
if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then
sMyWarn = 'Warning in drill : depth (' .. EgtNumToString( dDepth, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')'
dDepth = dMaxDepth
EgtOutLog( sMyWarn)
end
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- imposto il valore della distanza di sicurezza per l'attacco. Se il valore del db utensili è troppo basso lo alzo a 10.
local dToolDbStartPos = EgtGetMachiningParam( MCH_MP.STARTPOS)
local dMinStartPos = 10
local dStartPos = max( dMinStartPos, dToolDbStartPos)
EgtSetMachiningParam( MCH_MP.STARTPOS, dStartPos)
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione (coincide con affondamento)
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dDepth, 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
else
local _, sWarn = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
return false, sWarn
else
return true, ( sMyWarn or sWarn)
end
end
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function ExtractExternalPaths( nPathInt, nNumIdAux, vtOrtho, b3Solid, nAddGrpId)
local nAuxId1, nAuxId2
if nNumIdAux == 1 then
-- fondo tra loro le curve compatibili
EgtMergeCurvesInCurveCompo( nPathInt)
-- esplodo il percorso in modo da avere entià separate per poterle controllare
local nStartId, nNumIds = EgtExplodeCurveCompo( nPathInt)
if nStartId then
local sDeleteByDir
-- Se normale lungo la Z elimino le entità che hanno differenza in Z
if abs(vtOrtho:getZ()) > 0.7 then
sDeleteByDir = 'Z'
-- altrimenti se normale lungo la Y elimino le entità che hanno variazione in Y
-- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.7 then
elseif abs(vtOrtho:getY()) > 0.7 then
sDeleteByDir = 'Y'
-- caso che non dovrebbe mai capitare ma gestito per completezza
-- altrimenti se normale lungo la X elimino le entità che hanno variazione in X
-- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.7 then
elseif abs(vtOrtho:getX()) > 0.7 then
sDeleteByDir = 'X'
end
if sDeleteByDir then
for i = 1, nNumIds do
local ptP1 = EgtSP( ( nStartId + i - 1), GDB_RT.GLOB)
local ptP2 = EgtEP( ( nStartId + i - 1), GDB_RT.GLOB)
if sDeleteByDir == 'Z' then
-- se hanno variazione in Z cancello l'entità
if abs( ptP1:getZ() - ptP2:getZ()) > 10 * GEO.EPS_SMALL then
EgtErase( nStartId + i - 1)
end
elseif sDeleteByDir == 'Y' then
-- se hanno variazione in Y cancello l'entità
if abs( ptP1:getY() - ptP2:getY()) > 10 * GEO.EPS_SMALL then
EgtErase( nStartId + i - 1)
end
elseif sDeleteByDir == 'X' then
-- se hanno variazione in X cancello l'entità
if abs( ptP1:getX() - ptP2:getX()) > 10 * GEO.EPS_SMALL then
EgtErase( nStartId + i - 1)
end
end
end
-- ricreo i vari percorsi
local dLocalVal
local tPaths = {}
local nNumPaths
local dMaxVal
local dMinVal
for i = 1, nNumIds do
local ptP1 = EgtSP( ( nStartId + i - 1), GDB_RT.GLOB)
if ptP1 then
if sDeleteByDir == 'Z' then
local bInsTab
for j = 1, #tPaths do
local dLocalVal = tPaths[j][2]
if abs( ptP1:getZ() - dLocalVal) < 10 * GEO.EPS_SMALL then
local tLocIds = tPaths[j][1]
table.insert( tLocIds, ( nStartId + i - 1))
tPaths[j][1] = tLocIds
bInsTab = true
end
end
-- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella
if not bInsTab then
table.insert( tPaths, {{( nStartId + i - 1)}, ptP1:getZ()})
dMaxVal = b3Solid:getMax():getZ()
dMinVal = b3Solid:getMin():getZ()
end
elseif sDeleteByDir == 'Y' then
local bInsTab
for j = 1, #tPaths do
local dLocalVal = tPaths[j][2]
if abs( ptP1:getY() - dLocalVal) < 10 * GEO.EPS_SMALL then
local tLocIds = tPaths[j][1]
table.insert( tLocIds, ( nStartId + i - 1))
tPaths[j][1] = tLocIds
bInsTab = true
end
end
-- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella
if not bInsTab then
table.insert( tPaths, {{( nStartId + i - 1)}, ptP1:getY()})
dMaxVal = b3Solid:getMax():getY()
dMinVal = b3Solid:getMin():getY()
end
elseif sDeleteByDir == 'X' then
local bInsTab
for j = 1, #tPaths do
local dLocalVal = tPaths[j][2]
if abs( ptP1:getX() - dLocalVal) < 10 * GEO.EPS_SMALL then
local tLocIds = tPaths[j][1]
table.insert( tLocIds, ( nStartId + i - 1))
tPaths[j][1] = tLocIds
bInsTab = true
end
end
-- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella
if not bInsTab then
table.insert( tPaths, {{( nStartId + i - 1)}, ptP1:getX()})
dMaxVal = b3Solid:getMax():getX()
dMinVal = b3Solid:getMin():getX()
end
end
end
end
if tPaths then
local tChamPath = {}
-- elimino quelle che non corrispondono agli estremi
for i = 1, #tPaths do
-- se non corrisponde ai limiti elimino l'elemento
if abs( tPaths[i][2] - dMaxVal) > 10 * GEO.EPS_SMALL and abs( tPaths[i][2] - dMinVal) > 10 * GEO.EPS_SMALL then
tPaths[i] = nil
end
end
for i = 1, #tPaths do
if tPaths[i] then
local tNoMatch = {}
local tPathLoc = tPaths[i][1]
local pIniLoc = EgtSP( tPathLoc[1], GDB_RT.GLOB)
local pEndLoc = EgtEP( tPathLoc[1], GDB_RT.GLOB)
-- ciclo sui percorsi per trovare i punti non coincidenti (se percorso non chiuso)
for j = 2, #tPathLoc do
-- prendo i punti del percorso successivo
local pAddIni = EgtSP( tPathLoc[j], GDB_RT.GLOB)
local pAddEnd = EgtEP( tPathLoc[j], GDB_RT.GLOB)
-- se consecutivi
if AreSamePointApprox( pEndLoc, pAddIni) then
pEndLoc = pAddEnd
elseif AreSamePointApprox( pIniLoc, pAddEnd) then
pIniLoc = pAddIni
else
table.insert( tNoMatch, tPathLoc[j])
end
end
-- controllo eventuali percorsi scartati
for j = 1, #tNoMatch do
-- prendo i punti del percorso successivo
local pAddIni = EgtSP( tNoMatch[j], GDB_RT.GLOB)
local pAddEnd = EgtEP( tNoMatch[j], GDB_RT.GLOB)
-- se consecutivi
if AreSamePointApprox( pEndLoc, pAddIni) then
pEndLoc = pAddEnd
elseif AreSamePointApprox( pIniLoc, pAddEnd) then
pIniLoc = pAddIni
end
end
-- creo concatenamento partendo dal punto iniziale
local nIdLoc = EgtCurveCompoByReorder( nAddGrpId, tPathLoc, pIniLoc, true)
if nIdLoc then
table.insert( tChamPath, nIdLoc)
end
end
end
for i = 1, #tChamPath do
local ptP1 = EgtSP( tChamPath[i], GDB_RT.GLOB)
-- modifico estrusione percorso
if sDeleteByDir == 'Z' then
if abs(ptP1:getZ() - dMaxVal) < 10 * GEO.EPS_SMALL then
EgtModifyCurveExtrusion( tChamPath[i], Z_AX(), GDB_RT.GLOB)
else
EgtModifyCurveExtrusion( tChamPath[i], -Z_AX(), GDB_RT.GLOB)
end
elseif sDeleteByDir == 'Y' then
if abs(ptP1:getY() - dMaxVal) < 10 * GEO.EPS_SMALL then
EgtModifyCurveExtrusion( tChamPath[i], Y_AX(), GDB_RT.GLOB)
else
EgtModifyCurveExtrusion( tChamPath[i], -Y_AX(), GDB_RT.GLOB)
end
elseif sDeleteByDir == 'X' then
if abs(ptP1:getX() - dMaxVal) < 10 * GEO.EPS_SMALL then
EgtModifyCurveExtrusion( tChamPath[i], X_AX(), GDB_RT.GLOB)
else
EgtModifyCurveExtrusion( tChamPath[i], -X_AX(), GDB_RT.GLOB)
end
end
end
if #tChamPath == 1 then
return tChamPath[1], 1, nil
elseif #tChamPath == 2 then
return tChamPath[1], 2, tChamPath[2]
else
for i = 1, nNumIds do
EgtErase( nStartId + i - 1)
end
for i = 1, #tChamPath do
EgtErase( tChamPath[i])
end
end
else
for i = 1, nNumIds do
EgtErase( nStartId + i - 1)
end
end
-- altrimenti cancello tutte le emtità e restituisco nil
else
for i = 1, nNumIds do
EgtErase( nStartId + i - 1)
end
end
end
end
return nil, 0, nil
end
---------------------------------------------------------------------
local function MakeChamfer( Proc, bIs3Faces, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
-- Se variabile globale indica che lo smusso è già stato fatto, esco
if bMadeChamfer then
return 0
end
bMadeChamfer = true
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'Mark')
if not sMilling then
local sErr = 'Error : Mark not found in library'
EgtOutLog( sErr)
return -1, sErr
end
-- ottengo le curve di contorno libero
local nAuxId1, nAuxId2, nNumIdAux
local bIsOpenPath = false
if bIs3Faces then
-- estraggo i percorsi
nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, nAddGrpId)
-- se percorso creato estraggo solo i percorsi delle facce interessate, non di testa
if nAuxId1 then
nAuxId1, nNumIdAux, nAuxId2 = ExtractExternalPaths( nAuxId1, nNumIdAux, vtOrtho, b3Solid, nAddGrpId)
end
else
nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, nAddGrpId)
if not nNumIdAux then nNumIdAux = 0 end
-- se non è una curva chiusa bisogna estrarre le sole curve da lavorare
if Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' then
local IdsToMachine = {}
bIsOpenPath = true
local nFirstId, nIdCount = EgtExplodeCurveCompo( nAuxId1)
for i = nFirstId, nFirstId + nIdCount - 1, 1 do
-- se segmento di retta
if EgtGetType( i) == GDB_TY.CRV_LINE then
local _, nEntitiesCount = EgtCurveDomain(i)
for j = 0, nEntitiesCount - 1 do
local ptStart = EgtUP( i, j, GDB_RT.GLOB)
local ptEnd = EgtUP( i, j + 1, GDB_RT.GLOB)
if ( AreSameVectorApprox( vtOrtho, X_AX()) and ( abs( ptStart:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL and abs( ptEnd:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL) or
AreSameVectorApprox( vtOrtho, -X_AX()) and ( abs( ptStart:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL and abs( ptEnd:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL) or
AreSameVectorApprox( vtOrtho, Y_AX()) and ( abs( ptStart:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL and abs( ptEnd:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL) or
AreSameVectorApprox( vtOrtho, -Y_AX()) and ( abs( ptStart:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL and abs( ptEnd:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL) or
AreSameVectorApprox( vtOrtho, Z_AX()) and ( abs( ptStart:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL and abs( ptEnd:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL) or
AreSameVectorApprox( vtOrtho, -Z_AX()) and ( abs( ptStart:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL and abs( ptEnd:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL)
) then
table.insert( IdsToMachine, i)
end
end
else
return 0
end
end
local ptNear = EgtSurfTmFacetCenter(Proc.Id, 0, GDB_ID.ROOT)
nAuxId1 = EgtCurveCompoByReorder( nAddGrpId, IdsToMachine, ptNear, true, GDB_ID.ROOT)
nNumIdAux = 1
end
end
local dExtra = 2
for i = 1, nNumIdAux do
local AuxId
local vtExtr
if bIs3Faces then
if i == 1 then
AuxId = nAuxId1
else
-- faccio la copia del percorso
-- AuxId = EgtCopyGlob( nAuxId1, nAddGrpId)
AuxId = nAuxId2
end
if AuxId then
vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
end
else
AuxId = nAuxId1 + i - 1
if bIsOpenPath then
_, vtExtr = EgtCurveIsFlat( AuxId)
else
vtExtr, _, _ = EgtCurveArea( AuxId)
end
if vtExtr then
local fFrCurve = EgtGetGlobFrame( AuxId)
vtExtr:toGlob( fFrCurve)
if bIsOpenPath and vtExtr * vtOrtho < GEO.EPS_SMALL then
vtExtr = -vtExtr
end
end
end
if vtExtr then
-- if bIs3Faces and i == nNumIdAux then
-- vtExtr = -vtExtr
-- end
-- Se normale entro certi limiti
-- if vtExtr:getZ() > -0.707 and ( abs(vtOrtho:getX()) > 0.99 or abs(vtOrtho:getY()) > 0.99 or abs(vtOrtho:getZ()) > 0.99) then
if vtExtr:getZ() > -0.707 and ( abs(vtExtr:getX()) > 0.99 or abs(vtExtr:getY()) > 0.99 or abs(vtExtr:getZ()) > 0.99) then
-- inserisco la lavorazione
local sNameCh = 'Cham_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local nMchId = EgtAddMachining( sNameCh, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sNameCh .. '-' .. sMilling
EgtOutLog( sErr)
return -1, sErr
end
-- modifico estrusione percorso
EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ AuxId, -1}})
-- imposto posizione braccio porta testa
if vtExtr:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
-- assegno affondamento e offset radiale
-- EgtSetMachiningParam( MCH_MP.DEPTH, dDepthCham + dExtra - EgtIf( bIs3Faces, (dDepth / 2), 0))
EgtSetMachiningParam( MCH_MP.DEPTH, dDepthCham + dExtra)
EgtSetMachiningParam( MCH_MP.OFFSR, dExtra)
-- se opero su 3 facce e sono al secondo e ultimo percorso inverto la lavorazione
-- if bIs3Faces and i == nNumIdAux then
-- EgtSetMachiningParam( MCH_MP.INVERT, true)
-- end
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return -1, sErr
end
-- se non perpendicolare emetto un warning
-- else
-- sWarn = 'Warning : chamfer skipped because not perpendicular to face or from bottom'
-- EgtOutLog( sWarn)
end
--emetto un warning
-- else
-- sWarn = 'Warning : chamfer skipped because not perpendicular to face'
-- EgtOutLog( sWarn)
end
end
return 0
end
---------------------------------------------------------------------
local function MakeByMillAsSaw( Proc, nPhase, nRawId, nPartId, nFacInd,
rfFac, dH, dV, dElev,
nBottomFace, nAddGrpId, b3Solid, dSawMaxDepth, sMillingOnSide,
dSawDiam, dSawThick, bIgnoreCaps)
local sWarn
-- ingombro del grezzo
local b3Raw = EgtGetRawPartBBox( nRawId)
-- ottengo la distanza tra la fine del pezzo e il pezzo successivo
local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase)
-- verifico definizione faccia con il maggior numero di adiacenze
if not nFacInd then
local sErr = 'Error : MakeByMillAsSaw could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
-- Recupero le facce adiacenti alla principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[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, nFacInd, vAdj[i], GDB_ID.ROOT)
local dLen = dist( ptP1, ptP2)
if abs( dLen - dMaxLen) < 5 then
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT)
local bPositionedToYm = Proc.Box:getMax():getY() < ( b3Raw:getMin():getY() + b3Raw:getMax():getY()) / 2
if ( bPositionedToYm and vtN:getY() < 0.5) or ( not bPositionedToYm and vtN:getY() > 0.5) or vtN:getZ() > 0.5 then
nFacAdj = vAdj[i]
dMaxLen = dLen
end
elseif dLen > dMaxLen then
nFacAdj = vAdj[i]
dMaxLen = dLen
end
end
end
if not nFacAdj then
local sErr = 'Error : long adjacent face not found'
EgtOutLog( sErr)
return false, sErr
end
-- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT)
if abs( vtN * rfFac:getVersX()) > abs( vtN * rfFac:getVersY()) then
dH, dV = dV, dH
end
-- Determino se estremi aperti o chiusi
local bOpenStart = bIgnoreCaps
local bOpenEnd = bIgnoreCaps
local vtNS, vtNE
-- se non ho la faccia di fondo ( che comporta essere una fessura) e non da ignorare verifico se ho lati aperti
if not nBottomFace and not bIgnoreCaps then
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1]
EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3)
for j = 1, #vAdj2 do
if vAdj2[j] == nFacInd then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == nFacInd do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- se è chiusa acquisisco vettore faccia tappo
if not bOpenStart and vAdj2[i] >= 0 then
vtNS = EgtSurfTmFacetNormVersor( Proc.Id, vAdj2[i], GDB_ID.ROOT)
end
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == nFacInd do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
-- se è chiusa acquisisco vettore faccia tappo
if not bOpenEnd and vAdj2[k] >= 0 then
vtNE = EgtSurfTmFacetNormVersor( Proc.Id, vAdj2[k], GDB_ID.ROOT)
end
end
end
end
-- Recupero la lavorazione di lama
local sCutting = sMillingOnSide
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestOrthoOpposite( rfFac:getVersZ())
local dStartDist = -1
local dEndDist = -1
-- calcolo eventuali arretramenti lama
if not bOpenStart then
local dRadius = dSawDiam / 2
local dCat1 = dRadius - dElev
dStartDist = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1))
end
if not bOpenEnd then
if not bOpenStart then
dEndDist = dStartDist
else
local dRadius = dSawDiam / 2
local dCat1 = dRadius - dElev
dEndDist = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1))
end
end
-- Eseguo i tagli
local nStep = ceil( ( dV - 100 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( dV - dSawThick) / ( nStep - 1)
end
local dVzLimDwnUp = -0.01
for i = 1, nStep do
local dOffs = ( i - 1) * dStep
if vtN:getZ() < dVzLimDwnUp then dOffs = dOffs + dSawThick end
-- forzatura lavorazione discorde in base a parametro Q su feature
local nQ14Param = EgtGetInfo( Proc.Id, Q_CONVENTIONAL_MILLING, 'd') or 0
local bForceInvert = nQ14Param == 1 or ( nQ14Param == 2 and vtN:getX() < 0.1 and Proc.AffectedFaces.Bottom)
if bForceInvert and i == 1 then
dStartDist, dEndDist = dEndDist, dStartDist
end
local bOk, sErr, nMchId = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, dVzLimDwnUp, 0, BD.CUT_SIC, dOffs, dStartDist, dEndDist, nil, b3Raw, bForceInvert)
if not bOk then return bOk, sErr end
-- setto l'elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', 0)
-- applico elevazione
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- tolgo eventuale step
EgtSetMachiningParam( MCH_MP.STEP, 0)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
end
-- in base all'elevazione calcolo l'impronta della lama
local dUsedBladeLen = sqrt( ((dSawDiam / 2)*(dSawDiam / 2)) - ( ( (dSawDiam / 2) - dElev) * ( (dSawDiam / 2) - dElev)))
-- controllo direzione taglio e se il minimo della feature sborda in coda
if abs( vtN:getX()) < GEO.EPS_SMALL and abs( b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then
-- do avviso che la lama può sbordare nel pezzo successivo
sWarn = 'Warning on mill side as blade : Cut machining can damage next piece'
EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')')
end
return true, sWarn
end
---------------------------------------------------------------------
local function MakeByChainOrSaw( Proc, nPhase, nRawId, nPartId, nFacInd,
rfFac, dH, dV, dElev, bForceUseBlade,
dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace,
bOrthoFacesMaster, nBottomFace, nChamfer, nAddGrpId, b3Solid,
dDepthCham, nSurfInt)
local sWarn
-- ingombro del grezzo
local b3Raw = EgtGetRawPartBBox( nRawId)
-- ottengo la distanza tra la fine del pezzo e il pezzo successivo
local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase)
-- angolo d'ingresso dell'utensile
local dToolEntryAngle, _, _, dTanToolEntryAngle = GetToolEntryAngle( Proc, rfFac:getVersZ())
-- verifico se fessura con 3 facce o tunnel
local bOrthoFaces
local bIs3Faces = ( Proc.Fct == 3)
if bIs3Faces then
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local nFacInd1, dFacElev1, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc, nPartId, bIs3Faces)
if not nFacInd1 or nFacInd1 < 0 then
if nFacInd1 == -1 then
bOrthoFaces = nFacInd2
else
local sErr = 'Error : MakeByChainOrSaw could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
end
else
bOrthoFaces = bOrthoFacesMaster
end
-- eventuale massima elevazione imposta dall'utente
local dMaxElev = EgtGetInfo( Proc.Id, Q_MAX_ELEVATION, 'd')
if dMaxElev and dMaxElev < 1 then dMaxElev = nil end
dElev = dMaxElev or dElev
if bOrthoFaces then
-- ottengo le dimensioni del tunnel
dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
-- verifico la direzione
-- se devo inserire il chamfer
if nChamfer > 0 then
local nOk, sErr = MakeChamfer( Proc, bIs3Faces, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return false, sErr end
end
-- slot aperta su due lati
elseif Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' then
if nChamfer > 0 then
local nOk, sErr = MakeChamfer( Proc, false, nAddGrpId, rfFac:getVersZ(), b3Solid, nil, dDepthCham)
if nOk < 0 then return false, sErr end
end
end
if not dDepth then dDepth = dElev end
-- Recupero le facce adiacenti alla principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[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 vtAdjN = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT)
if not bIs3Faces or abs( rfFac:getVersZ():getY()) < 0.174 or abs( rfFac:getVersZ():getY()) > 0.984 or vtAdjN:getY() * rfFac:getVersZ():getY() > -0.1 then
local _, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
local dLen = dist( ptP1, ptP2)
if dLen > dMaxLen 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
end
if not nFacAdj then
local sErr = 'Error : long adjacent face not found'
EgtOutLog( sErr)
return false, sErr
end
-- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare
local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacAdj, GDB_ID.ROOT)
if abs( vtN * rfFac:getVersX()) > abs( vtN * rfFac:getVersY()) then
dH, dV = dV, dH
end
-- Determino se estremi aperti o chiusi
local bOpenStart = false
local bOpenEnd = false
local vtNS, vtNE
-- se non ho la faccia di fondo ( che comporta essere una fessura) verifico se ho lati aperti
if not nBottomFace then
local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1]
EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3)
for j = 1, #vAdj2 do
if vAdj2[j] == nFacInd then
-- Se non esiste faccia adiacente a lato precedente -> inizio aperto
local i = EgtIf( j > 1, j - 1, #vAdj2)
while vAdj2[i] == nFacInd do
i = EgtIf( i > 1, i - 1, #vAdj2)
end
bOpenStart = ( vAdj2[i] < 0)
-- se è chiusa acquisisco vettore faccia tappo
if not bOpenStart and vAdj2[i] >= 0 then
_, vtNS = EgtSurfTmFacetCenter( Proc.Id, vAdj2[i], GDB_ID.ROOT)
end
-- Se non esiste faccia adiacente a lato successivo -> fine aperto
local k = EgtIf( j < #vAdj2, j + 1, 1)
while vAdj2[k] == nFacInd do
k = EgtIf( k < #vAdj2, k + 1, 1)
end
bOpenEnd = ( vAdj2[k] < 0)
-- se è chiusa acquisisco vettore faccia tappo
if not bOpenEnd and vAdj2[k] >= 0 then
_, vtNE = EgtSurfTmFacetCenter( Proc.Id, vAdj2[k], GDB_ID.ROOT)
end
end
end
end
-- escludo caso per L20 che porterebbe ad una lavorazione con lama non corretta; ritorno anche 'MNF' in modo da forzare una lavorazione tasca
if Proc.Prc == 20 and Proc.Fct >= 4 and bOpenStart and bOpenEnd and #vAdj >= 3 then
local sErr = 'Error: improper use of L020 feature'
return false, sErr, 'MNF'
end
-- verifico se uso lama da sotto
local bCutDown = ( BD.DOWN_HEAD and rfFac:getVersZ():getZ() < - 0.5)
-- Recupero il massimo affondamento possibile con la lama
local dSawMaxDepth = 0
local sCutting = ML.FindCutting( 'HeadSide', not bCutDown, bCutDown)
if sCutting then
if EgtMdbSetCurrMachining( sCutting) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dSawMaxDepth = EgtTdbGetCurrToolMaxDepth() or dSawMaxDepth
end
end
end
-- se lavorazione sulle teste e altezza trave supera il limite ( che causa collisione con la forcella) e direzione taglio lungo la Z
-- e limite profondità BeamData è maggiore del taglio massimo lama, assegno il massimo affondamento pari al limite profondità del BeamData
if bOpenStart and bOpenEnd and bForceUseBlade and ( Proc.Head or Proc.Tail) and abs(rfFac:getVersY():getY()) > 0.866 and
b3Solid:getDimZ() > BD.MIN_DIM_HBEAM and dSawMaxDepth > BD.MAX_DIM_HTCUT_HBEAM then
dSawMaxDepth = BD.MAX_DIM_HTCUT_HBEAM
end
-- Se entrambi gli estremi sono aperti e possibile, lavoro con la lama
if bOpenStart and bOpenEnd and bForceUseBlade and dElev < dSawMaxDepth + 10 * GEO.EPS_SMALL then
-- recupero altri dati dell'utensile
local dSawDiam = 400
local dSawThick = 4
if EgtMdbSetCurrMachining( sCutting) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam
dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
end
end
if dSawThick > dV + 10 * GEO.EPS_SMALL then
local sErr = 'Error : sawblade too thick'
EgtOutLog( sErr)
return false, sErr
end
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestOrthoOpposite( rfFac:getVersZ())
-- Eseguo i tagli
local nStep = ceil( ( dV - 100 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( dV - dSawThick) / ( nStep - 1)
end
for i = 1, nStep do
local dOffs = ( i - 1) * dStep
local bOk, sErr = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 0, BD.CUT_SIC, dOffs, 0, 0, nil, b3Raw)
if not bOk then return bOk, sErr end
end
-- in base all'elevazione calcolo l'impronta della lama
local dUsedBladeLen = sqrt( ((dSawDiam / 2)*(dSawDiam / 2)) - ( ( (dSawDiam / 2) - dElev) * ( (dSawDiam / 2) - dElev)))
-- controllo direzione taglio e se il minimo della feature sborda in coda
if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then
-- do avviso che la lama può sbordare nel pezzo successivo
sWarn = 'Warning on saw cut : Cut machining can damage next piece'
EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')')
end
-- altrimenti con sega a catena
else
-- Recupero la lavorazione
local sSawing = ML.FindSawing( 'Sawing', dDepth, true)
-- se non trovo alcuna sega a catena lunga a sufficienza, accetto di non arrivare sul fondo della tasca
if not sSawing then
sSawing = ML.FindSawing( 'Sawing', nil, nil, 'Longest')
end
-- se non trova una lavorazione di sawing esco
if not sSawing then
local sErr = 'Error : Sawing 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
local bGoFromHead = true
local bAttackFromSide = ( ( EgtGetInfo( Proc.Id, Q_CHAINSAW_FROM_SIDE, 'i') or 0) == 1)
and ( Proc.Fct == 4) and ( Proc.Topology == 'Groove')
-- se normale lungo Z è da sopra: si tenta attacco laterale se richiesto
if AreSameOrOppositeVectorApprox( Proc.Face[ nFacInd + 1].VtN, Z_AX()) then
if bAttackFromSide then
bGoFromHead = false
end
elseif dElev > dMaxDepth + 10 * GEO.EPS_SMALL then
if bAttackFromSide then
bGoFromHead = false
-- continuo di testa se fessura con tre facce o non è tunnel
else
bGoFromHead = (( bIs3Faces and dMaxElev) or not bOrthoFaces)
end
end
-- se continuo a lavorare di testa
if bGoFromHead then
-- Calcolo normale faccia adiacente
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT)
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ(), vtN)
-- Verifico se necessarie più passate
local nStep = ceil( ( dV - 100 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( dV - dSawThick) / ( nStep - 1)
end
-- se necessario riduco la profondità di lavoro per considerare l'ingombro della testa
local dChainSawTHLength = EgtIf( EgtTdbGetCurrToolThLength() > 10 * GEO.EPS_SMALL, EgtTdbGetCurrToolThLength(), 88)
local dChainSawExtraLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) - dChainSawTHLength - dMaxDepth
local dMaxMatReduction = 0
if dToolEntryAngle > 10 * GEO.EPS_ANG_SMALL and dToolEntryAngle < 90 - 10 * GEO.EPS_ANG_SMALL then
dMaxMatReduction = max( ( ( 2 * BD.C_SIMM_ENC - dSawWidth) / ( 2 * dTanToolEntryAngle) - dChainSawExtraLength) - 5, 0)
end
dMaxDepth = dMaxDepth - dMaxMatReduction
for i = 1, nStep do
-- Applico la lavorazione con sega a catena a questa faccia
local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local nMchFId = EgtAddMachining( sName, sSawing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}})
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- controllo direzione taglio e se il minimo della feature sborda in coda
if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL then
-- se ho lato partenza aperto e lato uscita chiuso e direzione lato chiuso è negativa, allora controllo uscita lama
if bOpenStart and not bOpenEnd and vtNE:getX() < -0.99 and dDistToNextPiece < (dSawWidth / 2) then
-- imposto accorciamento iniziale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dDistToNextPiece - 1 - (dSawWidth / 2))
else
-- imposto accorciamento iniziale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2))
end
-- se ho lato uscita aperto e lato partenza chiuso e direzione lato partenza è negativa, allora controllo uscita lama
if bOpenEnd and not bOpenStart and vtNS:getX() < -0.99 and dDistToNextPiece < (dSawWidth / 2) then
-- imposto accorciamento finale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dDistToNextPiece - 1 - (dSawWidth / 2))
else
-- imposto accorciamento finale per estremi aperti/chiusi
EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2))
end
else
-- 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))
end
-- imposto angolo 3° asse rot e eventuale angolo suggerito per inizio
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sSawing, 'perpendicular'))
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtN, rfFac:getVersZ(), 1))
-- imposto offset radiale
local dOffs = ( i - 1) * dStep
EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
-- se necessario, avverto limitazione dell'affondamento
if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.DEPTH, dMaxDepth)
sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')'
EgtOutLog( sWarn)
--local dDepth = dMaxDepth - dElev
--EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH '..EgtNumToString( dDepth, 1))
end
-- imposto massima elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 2))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
if EgtGetOutstrokeInfo() then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- impostazione alternativa angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sSawing, 'parallel'))
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtN, rfFac:getVersZ(), 2))
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
if EgtIsMachiningEmpty() then
_, sWarn = EgtGetMachMgrWarning( 0)
EgtSetOperationMode( nMchFId, false)
return false, sWarn
end
end
-- altrimenti sega a catena di fianco
-- si arriva qui anche per groove 4 lati con rotazione esclusa
else
local vtRef = Vector3d( vtOrtho)
if vtRef and ( vtRef:getY() > 0.5 or vtRef:getZ() < -0.1) then
vtRef = -vtRef
end
if bAttackFromSide then
dDimMin = min( Proc.Face[ nFacInd + 1].Width, Proc.Face[ nFacInd + 1].Height)
dDimMax = min( Proc.Face[ nFacAdj + 1].Width, Proc.Face[ nFacAdj + 1].Height)
nLundIdFace = nFacAdj
local nFaceZ
if not vtRef then
if Proc.AffectedFaces.Top then
vtRef = Z_AX()
nFaceZ = BL.FindFaceBestOrientedAsAxis( Proc, Z_AX())
else
vtRef = -Z_AX()
nFaceZ = BL.FindFaceBestOrientedAsAxis( Proc, -Z_AX())
end
else
nFaceZ = nFacInd
end
dDepth = Proc.Face[ nFaceZ + 1].Elevation
end
local bMakeChainSaw, sSawing2, dMaxMat2, dSawCornerRad2, dSawThick2 = VerifyChainSaw( Proc, dDimMin, dDimMax, dDepth)
if bMakeChainSaw then
-- Calcolo normale faccia da lavorare
local vtNL = EgtSurfTmFacetNormVersor( Proc.Id, nLundIdFace, GDB_ID.ROOT)
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( vtRef, vtNL)
-- Verifico se necessarie più passate
local nStep = ceil( ( dDimMin - 100 * GEO.EPS_SMALL) / dSawThick2)
local dStep = 0
if nStep > 1 then
dStep = ( dDimMin - dSawThick2) / ( nStep - 1)
end
for i = 1, nStep do
-- inserisco la lavorazione di sawing
local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
local nMchFId = EgtAddMachining( sName, sSawing2)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing2
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nLundIdFace}})
-- imposto uso del lato faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sSawing, 'perpendicular'))
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtNL, vtOrtho, 1))
-- imposto offset radiale
local dOffs = ( i - 1) * dStep
EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
local dMachiningDepth = dDepth
if not bAttackFromSide then
-- se possibile aumento l'affondamento pari al raggio corner + 1
if dMaxMat2 > ( dDepth + dSawCornerRad2 + 1) then
dMachiningDepth = ( dDepth + dSawCornerRad2 + 1)
-- se massimo affondamento supera altezza fessura, uso massimo affondamento
elseif dMaxMat2 > ( dDepth + 1) then
dMachiningDepth = (dMaxMat2 - 1)
-- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning
elseif dMaxMat2 < dDepth then
dMachiningDepth = dMaxMat2
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
EgtSetMachiningParam( MCH_MP.DEPTH, dMachiningDepth)
else
-- se possibile si lavora tutta la profondità
if dMaxMat2 > (dDepth - 100 * GEO.EPS_SMALL) then
dMachiningDepth = dDepth
-- in alternativa si arriva al massimo materiale
else
dMachiningDepth = dMaxMat2
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
EgtSetMachiningParam( MCH_MP.DEPTH, dMachiningDepth)
-- si decidono lato di lavoro, inversione e estensione in base al lato aperto
local nEdgeIndex = BL.GetEdgeToMachineFromVector( Proc.Id, nFacAdj, vtRef)
local EdgesEgt = BL.GetEdgesInfo( Proc, Proc.Face[nFacAdj+1])
local CurrentEdge = EdgesEgt[nEdgeIndex+1]
local dStartAddLen = 0
local dEndAddLen = 0
if CurrentEdge.IsStartOpen then
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MORTISE_WS.RIGHT)
EgtSetMachiningParam( MCH_MP.INVERT, false)
else
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MORTISE_WS.LEFT)
EgtSetMachiningParam( MCH_MP.INVERT, true)
end
dStartAddLen = dSawWidth / 2 + EgtMdbGetGeneralParam( MCH_GP.SAFEZ) + EgtMdbGetGeneralParam( MCH_GP.SAFEAGGRBOTTZ)
dEndAddLen = - dSawWidth / 2
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dStartAddLen)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEndAddLen)
end
-- in caso di attacco esterno si setta in modo da fare un primo step adeguato per evitare finecorsa
-- si riduce la feed opportunamente
if bAttackFromSide then
local dMachiningStep = EgtGetMachiningParam( MCH_MP.STEP) or 0
-- TODO qui sostituire con valore preciso da GetSetupInfo
if BD.C_SIMM then
dMachiningStep = 175
if vtRef:getZ() < - 10 * GEO.EPS_SMALL then
dMachiningStep = 260
end
end
local dActualStep = ( dMachiningDepth - dMachiningStep) / ( 2 + 1)
dElev = dMachiningDepth - dMachiningStep + dActualStep - 0.1
if dActualStep < 0 then
dActualStep = 1
dElev = 2
end
EgtSetMachiningParam( MCH_MP.STEP, dActualStep)
local dFeed = EgtGetMachiningParam( MCH_MP.FEED) / 2
EgtSetMachiningParam( MCH_MP.FEED, dFeed)
end
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 1))
if bAttackFromSide then
sUserNotes = EgtSetValInNotes( sUserNotes, 'Plunge', 10)
end
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
if EgtGetOutstrokeInfo() then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- impostazione alternativa angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sSawing, 'parallel'))
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtNL, vtOrtho, 2))
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
if EgtIsMachiningEmpty() then
_, sWarn = EgtGetMachMgrWarning( 0)
EgtSetOperationMode( nMchFId, false)
return false, sWarn
end
end
end
end
end
return true, sWarn
end
---------------------------------------------------------------------
local function MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth, bMillDown)
-- Recupero la lavorazione di lama
local sCutting = ML.FindCutting( 'HeadSide', not bMillDown, bMillDown)
if not sCutting then
local sErr = 'Error : HeadSide (cutting) not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- valuto l'angolo tra le due facce
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacet, GDB_ID.ROOT)
if not bAdj then
local sErr = 'Error : Faces not adjacent'
EgtOutLog( sErr)
return false, sErr
end
local ptPm = (ptP1+ptP2)/2
-- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta l'elevazione della faccia
-- laterale sul punto medio della linea in comune
local frFc = Frame3d( ptPm, vtN) ;
local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc)
dDepth = b3BoxLoc:getDimZ() or 0
-- recupero i dati dell'utensile
local dSawDiam = 400
local dSawThick = 0
local dMaxDepth = 0
local bSawCCW = false
if EgtMdbSetCurrMachining( sCutting) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam
dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
bSawCCW = ( EgtTdbGetCurrToolParam( MCH_TP.SPEED) < 0)
end
end
local dExtraOffs = 0
-- se il taglio è praticamente verticale, riduto massimo materiale lama
if BD.DECR_VERT_CUT and vtN:getZ() > 0.985 then
dMaxDepth = dMaxDepth - BD.DECR_VERT_CUT - BD.COLL_SIC
end
-- se profondità superiore al massimo lama modifico elevazione
if dDepth > dMaxDepth then
dExtraOffs = dMaxDepth - dDepth
end
-- se devo ridurre l'affondamento
if bReduceDepth then
local dLimitDepth = 100
-- se ho ridotto l'affondamento ne riduco ulteriormente l'affondamento (50mm)
if abs(dExtraOffs) > 0 then
if dMaxDepth > dLimitDepth then
dExtraOffs = dLimitDepth - dDepth
end
else
if dDepth > dLimitDepth then
dExtraOffs = dLimitDepth - dDepth
else
dExtraOffs = - (dDepth/2)
end
end
end
-- eseguo il taglio
local vtNfac = EgtSurfTmFacetNormVersor( Proc.Id, nFacet, GDB_ID.ROOT)
local dVzLimDwnUp = EgtIf( BD.TURN, -2, BL.GetNzLimDownUp( b3Raw, vtNfac, vtN))
local bInvert = ( bSawCCW ~= ( vtNfac:getZ() < dVzLimDwnUp))
local bMadeASbyBld, sWarn, nIdMach = Fbs.MakeOne( Proc.Id, nFacet, sCutting, dSawDiam, vtN, dVzLimDwnUp, ( -0.5 + dExtraOffs), BD.CUT_SIC, 0, 0, 0, nil, b3Raw, bInvert)
if bMadeASbyBld then
sWarn = nil
if not bReduceDepth and abs(dExtraOffs) > 0 then
sWarn = 'Warning : antisplint elevation is bigger than max tool depth'
end
end
return bMadeASbyBld, sWarn, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs
end
---------------------------------------------------------------------
local function MakePocket( Proc, nPartId, b3Solid, ptPs, tvtN, nFaceRef, sMchFind, nUseRoughTool, sMasterPocket, dPrevFaceElev, tDimAndRef, dAng, bOpenOutRaw, bLapJointAngTrasm, nPhase, nRawId, dCustomMaxElev)
-- distanza dal pezzo successivo
local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase)
-- calcolo l'elevazione dal punto medio
local dElev
local dLenIn, dLedOut = BL.GetPointDirDepth( nPartId, ptPs, tvtN[2])
if dLenIn > 0 then
dElev = dLenIn
elseif dLedOut then
dElev = dLedOut
end
local dCollSic = 2 * BD.COLL_SIC
-- calcolo il diametro utensile
local dFaceDiamTool
if tDimAndRef then
-- prendo il valore dalle dimensioni minime delle facce
dFaceDiamTool = min( tDimAndRef[2][1], tDimAndRef[2][2])
end
-- se ho lavorazione precedente ricalcolo grossolanamente l'elevazione
if dPrevFaceElev and dPrevFaceElev > 0 and dAng then
dElev = dElev + ( sqrt( ( dElev * dElev) - ( dPrevFaceElev * dPrevFaceElev)) * sin(dAng))
elseif dPrevFaceElev and dPrevFaceElev > dElev then
dElev = dPrevFaceElev
end
local sPocketing
if sMasterPocket then
sPocketing = sMasterPocket
else
sPocketing = ML.FindPocketing( sMchFind, dFaceDiamTool, dElev + dCollSic)
end
if not sPocketing then
local sErr = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr)
return false, sErr
end
local sTuuidPk
local dDiamTool = 20
local dMaxDepth = 0
local bTipMill = false
if EgtMdbSetCurrMachining( sPocketing) then
sTuuidPk = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then
dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dDiamTool
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
bTipMill = (( EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) or 0) > 1)
end
end
-- se nome svuotatura non è stato ricalcolato, confronto il diametro utensile utilizzato con il minimo faccia e se non sono compatibili esco
if sMasterPocket and dFaceDiamTool and dDiamTool >= dFaceDiamTool then
return false, '', sTuuidPk, dDiamTool, dElev
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. 'F' .. tostring( nFaceRef)
local nMchFId = EgtAddMachining( sName, sPocketing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria (se presente curva si lavora quella)
if Proc.LoopIdFacInd then
EgtSetMachiningGeometry( { Proc.LoopIdFacInd})
else
EgtSetMachiningGeometry( {{ Proc.Id, (nFaceRef)}})
end
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
-- se si lavora una faccia orizzontale e la dimensione X della feature è sufficiente, blocco l'asse B per evitare sollecitazioni inutili
local b3Face = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD)
if BD.C_SIMM and AreSameOrOppositeVectorApprox( tvtN[2], Z_AX()) and b3Face:getDimX() > BD.LONGCUT_ENDLEN then
nSCC = MCH_SCC.ADIR_YM
end
if bLapJointAngTrasm then
nSCC = MCH_SCC.ADIR_NEAR
elseif not BD.C_SIMM and not BD.TURN then
nSCC = MCH_SCC.ADIR_YM
if AreSameVectorApprox( tvtN[2], Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( tvtN[2]:getX()) < 0.1 then
local bNearTail = ( Proc.Box:getMax():getX() < b3Solid:getCenter():getX() + 50 and
Proc.Box:getMax():getX() - b3Solid:getMin():getX() < 1000)
local bVeryShortPart = ( BD.LEN_VERY_SHORT_PART and b3Solid:getDimX() < BD.LEN_VERY_SHORT_PART)
nSCC = EgtIf( BL.IsPartFinalPhase( EgtGetCurrPhase()) or ( bNearTail and not bVeryShortPart), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif tvtN[2]:getY() > 0.1 then
nSCC = MCH_SCC.ADIR_YP
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- se tasca aperta e non lavorata col truciolatore, imposto opportuno attacco
if ( sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2') and nUseRoughTool == 0 then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
if sMchFind == 'OpenPocket' and dDiamTool < 90 then
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFaceRef, GDB_ID.ROOT)
local bL = ( Proc.Fct < 4 or TestElleShape4( Proc) == 2)
if bL and min( dH, dV) < 1.5 * dDiamTool then
EgtSetMachiningParam( MCH_MP.INVERT, false)
if not bTipMill then
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_POCK_LI.HELIX)
EgtSetMachiningParam( MCH_MP.LITANG, dDiamTool)
EgtSetMachiningParam( MCH_MP.LIELEV, 2)
end
end
end
-- eventuale massima elevazione forzata
if dCustomMaxElev and dCustomMaxElev < 1 then dCustomMaxElev = nil end
-- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente
dElev = dCustomMaxElev or dElev
local sWarn
local dDepth = dElev
if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then
dDepth = dMaxDepth - dElev
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
dElev = dMaxDepth
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 1))
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
-- Se forzato lato aperto lavorazione da curva forzo OpenOutRaw
if( Proc.LoopIdFacInd and ( EgtGetInfo( Proc.LoopIdFacInd, 'OPEN', 'i') or -1) > -1) then
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFaceRef, GDB_ID.ROOT)
-- Se larghezza tasca uguale a larghezza utensile non permetto Invert
if abs( min( dH, dV) - dDiamTool) < 50 * GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.INVERT, false)
end
bOpenOutRaw = true
end
if bOpenOutRaw then
sUserNotes = EgtSetValInNotes( sUserNotes, 'OpenOutRaw', 1)
end
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
if not ML.ApplyMachining( true, false) then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
-- se percorso a Zig-Zag, provo a cambiarlo in spirale
local nPocketSubType = EgtGetMachiningParam( MCH_MP.SUBTYPE)
if nPocketSubType == MCH_POCK_SUB.ZIGZAG then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
-- se la lavorazione rovina il pezzo successivo emetto warning
if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and dDistToNextPiece < dDiamTool / 2 then
sWarn = 'Warning on pocketing ' .. sName .. ': machining can damage next piece. Minimum distance needed : ' .. ( 1 + dDiamTool / 2) .. ' mm'
EgtOutLog( sWarn)
end
if BD.TURN and BD.TURN ~= 2 then
-- centro del pezzo
local ptCen = ORIG()
if b3Solid then ptCen = b3Solid:getCenter() end
-- punto inizio lavorazione
local ptStart = EgtGetMachiningStartPoint() or ORIG()
-- orientamento braccio
local nSCC = MCH_SCC.NONE
-- se faccia verso alto o basso
if abs( tvtN[2]:getZ()) > abs( tvtN[2]:getY()) then
nSCC = EgtIf( ptStart:getY() > ptCen:getY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
-- altrimenti faccia verso davanti o dietro
else
nSCC = EgtIf( ptStart:getZ() > ptCen:getZ(), MCH_SCC.ADIR_ZP, MCH_SCC.ADIR_ZM)
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
ML.ApplyMachining( true, false)
end
return true, sWarn, sTuuidPk, dDiamTool, dDepth
end
---------------------------------------------------------------------
local function MachineByMill( Proc, nPhase, nRawId, nPartId, b3Solid, tvtN, nBaseFace, nSideFace, ptPs, tDimAndRef,
b3Raw, nDiffWidth, nUseRoughTool, dAng, sPocketing, sTuuidPk, dPrevFaceElev)
local sMchFind = 'Pocket'
local dAngLimit = 40
local sWarn
-- se feature é larga come trave imposto openpocket
if nDiffWidth == 0 then
sMchFind = 'OpenPocket'
-- altrimenti non è passante disabilito il truciolatore
else
nUseRoughTool = 0
end
-- se angolo tra le facce maggiore di 90, inserisco la contornatura o svuotatura del lato più corto
if ( 180 + dAng) > 90.1 then
-- calcolo l'angolo dalla verticale dall'angolo tra le due facce, perchè la feature potrebbe essere ruotata sulla Z locale della
-- faccia principale e quindi la componente X del versore della faccia potrebbe dare un valore non coerente
local dDiffFromSqAng = dAng + 90
-- informazioni sul lato da lavorare
local Edges = BL.GetEdgesInfo( Proc, Proc.Face[nSideFace + 1])
local EdgeToMachine = {}
for i = 1, #Edges do
local CurrentEdge = Edges[i]
if CurrentEdge.AdjacentFaceId == nBaseFace then
EdgeToMachine = CurrentEdge
end
end
-- se l'angolo dalla verticale si discosta di più dell'angolo limite impostato, utilizzo la svuotatura
if cos( dDiffFromSqAng) < cos( dAngLimit) then
-- applico la svuotatura
local bOk, sWarn, sTuuidPk, dDiamTool, dElev = MakePocket( Proc, nPartId, b3Solid, ptPs, tvtN, nSideFace, sMchFind, nUseRoughTool, sPocketing, dPrevFaceElev, tDimAndRef, dAng, nil, nil, nPhase, nRawId)
if not bOk then
-- se ho id utensile e diametro è perchè non ha fatto svuotatura perchè la faccia è più stretta del diametro utensile
-- e provo ad inserire singola passata di testa
if sTuuidPk and dDiamTool then
-- recupero la lavorazione
local sMilling = ML.FindMilling( 'Long2Cut', dElev, sTuuidPk)
if not sMilling then
local sErr = 'Error : Long2Cut not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione
local sName = 'Prof_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nSideFace}})
-- imposto vettore direzione e faceUse
local vtFaceUse = EdgeToMachine.ToolDirection
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VtFaceUse', EgtNumToString( vtFaceUse:getX(), 3) .. ',' .. EgtNumToString( vtFaceUse:getY(), 3) .. ',' .. EgtNumToString( vtFaceUse:getZ(), 3))
local nFaceUse = BL.GetNearestOrthoOpposite( vtFaceUse)
-- aggiusto i parametri
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH')
EgtSetMachiningParam( MCH_MP.OFFSR, 0)
EgtSetMachiningParam( MCH_MP.INVERT, false)
EgtSetMachiningParam( MCH_MP.WORKSIDE, 1)
-- imposto allungamenti iniziale e finale
if EdgeToMachine.IsStartOpen then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dDiamTool / 2)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, -dDiamTool / 2)
end
if EdgeToMachine.IsEndOpen then
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dDiamTool / 2)
else
EgtSetMachiningParam( MCH_MP.ENDADDLEN, -dDiamTool / 2)
end
-- imposto posizione braccio porta testa
if tvtN[2]:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- imposto elevazione e dichiaro non si generano sfridi per VMill
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 1))
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
return false, sErr
end
else
return false, sWarn
end
else
return bOk, sWarn
end
-- altrimenti contornatura di fianco
else
local bOpenStart = false
local bOpenEnd = false
if nDiffWidth == 0 then
bOpenStart = true
bOpenEnd = true
else
bOpenStart = EdgeToMachine.IsStartOpen
bOpenEnd = EdgeToMachine.IsEndOpen
end
local sMilling
if nUseRoughTool > 0 then
sMilling = ML.FindMilling( 'Long2Cut', nil, sTuuidPk)
if not sMilling then sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk) end
else
sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk)
if not sMilling then sMilling = ML.FindMilling( 'Long2Cut', nil, sTuuidPk) end
end
if not sMilling then
sMilling = ML.FindMilling( 'LongSmallCut')
if not sMilling then sMilling = ML.FindMilling( 'Long2Cut') end
if not sMilling then
local sErr = 'Error : Long2Cut & LongSmallCut not found in library'
EgtOutLog( sErr)
return false, sErr
else
sWarn = 'Warning : lapjoint angled face machined with different tool'
end
end
-- recupero i dati dell'utensile
local dTDiam = 50
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
end
end
-- se utensile troppo più grande dell'originale salto la lavorazione
if sTuuidPk and EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then
local dTDiamOriginalTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0
if dTDiam > 2 * dTDiamOriginalTool then
sWarn = 'Warning : lapjoint angled face skipped (no compatible tool)'
EgtOutLog( sWarn)
return true, sWarn
end
end
-- Calcolo uso faccia
local nFaceUse = BL.GetNearestParalOpposite( tDimAndRef[1][3]:getVersZ())
-- inserisco la lavorazione di fresatura
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, (nSideFace)}})
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- sistemazione inversione del percorso
local nWrkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE)
local bInvert = nWrkSide ~= MCH_MILL_WS.RIGHT
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
if bInvert then
bOpenStart, bOpenEnd = bOpenEnd, bOpenStart
end
-- setto a 0 eventuali offset
EgtSetMachiningParam( MCH_MP.OFFSR, 0)
-- calcolo elevazione per allungamenti attacchi con fianchi chiusi
local dElev
local dLenIn, dLedOut = BL.GetPointDirDepth( nPartId, ptPs, tvtN[2])
if dLenIn > 0 then
dElev = dLenIn
elseif dLedOut then
dElev = dLedOut
end
-- applico gli allungamenti o accorciamenti
if bOpenStart then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2)
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, -dTDiam / 2)
-- forzo attacco lineare
if dElev > 0 then
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, dElev)
if bOpenEnd then
EgtSetMachiningParam( MCH_MP.LOPERP, 0)
else
EgtSetMachiningParam( MCH_MP.LOPERP, dElev)
end
end
end
if bOpenEnd then
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2)
else
EgtSetMachiningParam( MCH_MP.ENDADDLEN, -dTDiam / 2)
-- forzo attacco lineare
if dElev > 0 then
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LOPERP, dElev)
if bOpenStart then
EgtSetMachiningParam( MCH_MP.LIPERP, 0)
else
EgtSetMachiningParam( MCH_MP.LIPERP, dElev)
end
end
end
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
end
return true, sWarn
end
---------------------------------------------------------------------
local function GetUShapeWidth( Proc, nFacInd)
-- Recupero le facce adiacenti alla principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
-- se non ho facce adiacenti esco subito
if not vAdj or #vAdj == 0 then return 0 end
-- Normale della faccia
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
-- Cerco le facce adiacenti alla principale con angolo concavo >= 90
local dWidth = 0
for i = 1, #vAdj do
if vAdj[i] >= 0 then
-- verifico l'angolo tra le facce ( esco se angolo compreso < 90)
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
if bAdj and dAng < -90 - 20 * GEO.EPS_ANG_SMALL then return nil end
-- larghezza della faccia ortogonalmente alla adiacente
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT)
local vtX = vtN2 ^ vtN
local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2)
local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef)
if b3Ref then
dWidth = max( dWidth, b3Ref:getDimY())
end
end
end
return dWidth
end
---------------------------------------------------------------------
local function MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMchFindMaster, bIs3Faces, b3Solid, bOrthoFacesMaster, bMillDown, bSetOpenBorders, bIsU, bIsL)
local nFirstMachId
local bOrthoFaces
local sWarn
local sMchFind = 'Pocket'
local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt
local bBadMach = false
-- minima altezza della tasca sotto alla quale fa una contornatura invece di una svuotatura
local dMinFaceElevForPocket = 20
if sMchFindMaster and #sMchFindMaster > 0 then
sMchFind = sMchFindMaster
end
if bIs3Faces then
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc, nPartId, bIs3Faces)
if not nFacInd or nFacInd < 0 then
if nFacInd == -1 then
bOrthoFaces = nFacInd2
else
local sErr = 'Error : MakeByPockets could not find reference face'
EgtOutLog( sErr)
return -1, sErr
end
end
else
bOrthoFaces = bOrthoFacesMaster
end
-- se è un tunnel verifico se è possibile usare la svuotatura
if bOrthoFaces then
-- ottengo le dimensioni del tunnel
dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
-- se due facce posso utilizzare utensile con diametro doppio della dimensione minima
if Proc.Fct == 2 then
dDimMin = 2 * dDimMin
-- se tre facce aumento il diametro di quanto possibile
elseif Proc.Fct == 3 then
local nFacInd = BL.GetFaceWithMostAdj( Proc, nPartId, false)
local dWidth = GetUShapeWidth( Proc, nFacInd or -1) or dDimMin
if dWidth > dDimMin then
dDimMin = min( 2 * dDimMin, dWidth)
end
end
-- se devo inserire il chamfer
if nChamfer > 0 then
local nOk, sErr = MakeChamfer( Proc, bIs3Faces, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return -1, sErr end
end
-- se smusso non è esclusivo
local nPathInt
if nChamfer < 2 then
-- ricalcolo se è lavorabile da sotto
bMillDown = ( BD.DOWN_HEAD == true)
-- verifico se può essere fatto con svuotatura
local bMakePocket, sPocketing, dMaxDepth, dDiamTool = VerifyPocket( Proc, dDimMin, dDepth / 2, nil, sMchFind)
local bMakePocketDn, sPocketingDn, dMaxDepthDn, dDiamToolDn
if bMillDown then
bMakePocketDn, sPocketingDn, dMaxDepthDn, dDiamToolDn = VerifyPocket( Proc, dDimMin, dDepth / 2, nil, sMchFind, nil, true)
-- se è negativo inverto il versore e la faccia
if vtOrtho:getZ() < 0 then
vtOrtho = -vtOrtho
EgtInvertSurf( nSurfInt)
end
end
local nFacInd, dFacElev = BL.GetFaceWithMostAdj( Proc, nPartId)
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
local bMakeContour = false
local sMilling
if dFacElev < dMinFaceElevForPocket and ( bIsU or bIsL) and ( Proc.Fct == 2 or Proc.Fct == 3) and abs( vtN:getZ()) > 0.996 then
-- recupero la lavorazione di contornatura
sMilling = ML.FindMilling( 'Prof', nil, nil, nil, nil, not bMillDown, bMillDown)
if not sMilling then
local sMyWarn = 'Warning : Prof not found in library'
EgtOutLog( sMyWarn)
end
-- recupero i dati dell'utensile
dDiamTool = 50
dMaxDepth = 0
if sMilling and EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dToolMaxDepth
bMakeContour = true
end
end
end
if bMakePocket or bMakeContour then
-- gestione svuotatura da un solo lato o anche dal lato opposto (se non verticale)
-- estraggo il contorno dalla superfice per evitare i problemi con la svuotatura
-- e assegno l'estrusione
nPathInt = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId)
EgtModifyCurveExtrusion( nPathInt, vtOrtho, GDB_RT.GLOB)
-- se ho 3 facce oppure se forzato, ciclo sulle entià del percorso per segnare quelle che sono aperte.
if bIs3Faces or bSetOpenBorders then
BL.SetOpenSide( nPathInt, b3Solid)
end
-- variabili per parametri lavorazione
local dMachDepth
local dElev = 0
local bDoubleSide
local bOneShot
local bComplete = true
-- imposto altezza aggiuntiva di elevazione
local dCollSic = BL.CalcCollisionSafety( vtOrtho)
-- se possibile svuotare completamente da una sola parte
if dMaxDepth > ( dDepth + BD.CUT_EXTRA + dCollSic) then
dMachDepth = ( dDepth / 2) + BD.CUT_EXTRA
dElev = dDepth + BD.CUT_EXTRA
bOneShot = true
else
-- se direzione verso la verticale setto max affondamento possibile ed
-- emetto messaggio di warning perché non lavorabile interamente
if abs( vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD and not bMakeContour then
dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic
dElev = dMaxDepth
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
bComplete = false
-- altrimenti setto il flag per fare la svuotatura da due parti
else
-- se l'altezza utensile riesce a lavorare completamente da due parti
if dMaxDepth > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then
dMachDepth = BD.CUT_EXTRA_MIN
dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN
-- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione
else
dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic
dElev = dMaxDepth
-- se molto inclinato rispetto alla normale della faccia di riferimento, lavorazione non idonea per probabili collisioni
local vtRef = Y_AX()
if abs( vtOrtho:getX()) > abs( vtOrtho:getY()) and abs( vtOrtho:getX()) > abs( vtOrtho:getZ()) then
vtRef = X_AX()
elseif abs( vtOrtho:getZ()) > abs( vtOrtho:getX()) and abs( vtOrtho:getZ()) > abs( vtOrtho:getY()) then
vtRef = Z_AX()
end
if abs( vtOrtho * vtRef) < 0.5 then
bBadMach = true
end
end
bDoubleSide = true
end
end
-- se lavorazione non idonea esco
if bIs3Faces and bBadMach then
local sErr = 'Impossible apply perpendicular pocketing: ' .. sPocketing
return -2, sErr
end
local sName
local nMchFId
if bMakeContour then
-- inserisco la lavorazione di contornatura
sName = 'Prof_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return -1, sErr
end
else
-- altrimenti inserisco la lavorazione di svuotatura
sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
nMchFId = EgtAddMachining( sName, sPocketing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return -1, sErr
end
end
-- prendo l'id della prima lavorazione inserita
if not nFirstMachId then
nFirstMachId = nMchFId
end
if bMakeContour then
-- aggiungo geometria per contornatura
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
else
-- altrimenti aggiungo geometria per svuotatura
EgtSetMachiningGeometry( {{ nPathInt, -1}})
end
-- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale)
local bInvertMach
if not bMakeContour then
if vtOrtho:getZ() < BD.NZ_MINA and abs(vtOrtho:getZ()) >= 0.707 and not BD.DOWN_HEAD then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
-- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti
elseif not bDoubleSide and vtOrtho:getY() > GEO.EPS_SMALL and not ( -(vtOrtho:getZ()) < BD.NZ_MINA) then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
end
end
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameOrOppositeVectorApprox( vtOrtho, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtOrtho:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtOrtho:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- se tasca aperta, imposto opportuno attacco
if sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2' then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
-- inverto il percorso di lavorazione per lavorare sinistro
if not bMakeContour then
EgtSetMachiningParam( MCH_MP.INVERT, true)
end
-- imposto affondamento
if not bMakeContour then
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth)
end
-- se contornatura doppia anticipo la fine della lavorazione a metà trave
if bMakeContour and bDoubleSide then
EgtSetMachiningParam( MCH_MP.OFFSL, dDepth / 2)
end
-- se contornatura cerco la direzione di lavoro migliore e setto attacco e allungamenti
if bMakeContour then
local nFaceUse = BL.GetNearestParalOpposite( vtOrtho)
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- quantità di cui allargare la contornatura per andare in tangenza con lo spigolo, nel caso di altezza tasca minore di D/2 fresa
local dAddWorkWidth = EgtIf( dFacElev < dDiamTool / 2, -sqrt( dFacElev * dDiamTool - dFacElev * dFacElev), -dDiamTool / 2)
EgtSetMachiningParam( MCH_MP.LIELEV, 0)
EgtSetMachiningParam( MCH_MP.LOELEV, 0)
if bIsU then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, 30)
EgtSetMachiningParam( MCH_MP.LOPERP, 30)
elseif bIsL then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 30)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LITANG, 30)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, 0)
EgtSetMachiningParam( MCH_MP.LOPERP, 30)
end
end
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
if not bMakeContour then
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 1))
end
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) or EgtIsMachiningEmpty() then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return -1, sErr
elseif EgtIsMachiningEmpty() then
EgtRemoveOperation( nMchFId)
local sErr = 'Impossible to machine (empty toolpath)'
return -3, sErr
end
end
-- se posso applicare la svuotatura sul lato opposto
if bDoubleSide then
-- se ho la lavorazione da sotto ricalcolo in base a questa lavorazione
if bMakePocketDn then
-- sPocketing = sPocketingDn
-- dMaxDepth = dMaxDepthDn
-- dDiamTool = dDiamToolDn
-- se l'altezza utensile riesce a lavorare completamente da due parti
if dMaxDepthDn > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then
dMachDepth = BD.CUT_EXTRA_MIN
dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN
-- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione
else
dMachDepth = dMaxDepthDn - ( dDepth / 2) - dCollSic
dElev = dMaxDepthDn
bComplete = false
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
else
-- se anche lavorando dal lato opposto non riesco a svuotare completamente la fessura
-- setto i parametri affondamento ed emetto warning
if dMaxDepth < ( dDepth / 2) + BD.CUT_EXTRA + dCollSic then
dMachDepth = dMaxDepth - (dDepth / 2) - dCollSic
dElev = dMaxDepth
bComplete = false
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
end
if bMakeContour then
-- inserisco la lavorazione di contornatura
sName = 'ProfOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return -1, sErr
end
else
-- inserisco la lavorazione di svuotatura
sName = 'PockOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
nMchFId = EgtAddMachining( sName, EgtIf( bMakePocketDn, sPocketingDn, sPocketing))
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. EgtIf( bMakePocketDn, sPocketingDn, sPocketing)
EgtOutLog( sErr)
return -1, sErr
end
end
-- prendo l'id della prima lavorazione inserita
if not nFirstMachId then
nFirstMachId = nMchFId
end
if bMakeContour then
-- aggiungo geometria per contornatura
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
else
-- altrimenti aggiungo geometria per svuotatura
EgtSetMachiningGeometry( {{ nPathInt, -1}})
end
-- imposto direzione utensile opposta
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameVectorApprox( vtOrtho, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtOrtho:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtOrtho:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- se tasca aperta, imposto opportuno attacco
if sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2' then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
-- inverto il percorso di lavorazione per lavorare sinistro
EgtSetMachiningParam( MCH_MP.INVERT, true)
-- imposto affondamento
if not bMakeContour then
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth)
end
-- se contornatura doppia anticipo la fine della lavorazione a metà trave
if bMakeContour and bDoubleSide then
EgtSetMachiningParam( MCH_MP.OFFSL, dDepth / 2)
end
-- se contornatura cerco la direzione di lavoro migliore
if bMakeContour then
local nFaceUse = BL.GetNearestParalOpposite( vtOrtho)
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- quantità di cui allargare la contornatura per andare in tangenza con lo spigolo, nel caso di altezza tasca minore di D/2 fresa
local dAddWorkWidth = EgtIf( dFacElev < dDiamTool / 2, -sqrt( dFacElev * dDiamTool - dFacElev * dFacElev), -dDiamTool / 2)
EgtSetMachiningParam( MCH_MP.LIELEV, 0)
EgtSetMachiningParam( MCH_MP.LOELEV, 0)
if bIsU then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, 30)
EgtSetMachiningParam( MCH_MP.LOPERP, 30)
elseif bIsL then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dAddWorkWidth)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 30)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.TANGENT)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 30)
EgtSetMachiningParam( MCH_MP.LIPERP, 30)
EgtSetMachiningParam( MCH_MP.LOPERP, 0)
end
end
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
if not bMakeContour then
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 1))
end
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return -1, sErr
end
end
end
-- se non completo e U, cerco di lavorare anche la faccia di fondo (con il massimo affondamento possibile)
if not bComplete and bIs3Faces then
-- recupero la faccia da lavorare
local nFacInd, dFacElev = BL.GetFaceWithMostAdj( Proc, nPartId)
local vtN
local bPock3rd = false
if nFacInd then
vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
bPock3rd = ( vtN and ( vtN:getZ() >= BD.NZ_MINA or bMakePocketDn))
end
if bPock3rd then
-- recupero la distanza di sicurezza aggiuntiva
local dFacCollSic = BL.CalcCollisionSafety( vtN)
-- scelgo se lavorare da sotto
local bFacPocketDn = ( bMakePocketDn and vtN:getZ() < -0.174)
-- inserisco la lavorazione di svuotatura
local sName = EgtIf( bDoubleSide, 'Pock3rd_', 'Pock2nd_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, EgtIf( bFacPocketDn, sPocketingDn, sPocketing))
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return -1, sErr
end
-- prendo l'id della prima lavorazione inserita
if not nFirstMachId then
nFirstMachId = nMchFId
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameOrOppositeVectorApprox( vtN, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YM
else
nSCC = MCH_SCC.ADIR_YP
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- se tasca aperta, imposto opportuno attacco
if sMchFind == 'OpenPocket' or sMchFind == 'OpenPocket_H2' then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
-- inverto il percorso di lavorazione per lavorare sinistro
EgtSetMachiningParam( MCH_MP.INVERT, true)
-- imposto affondamento
local dDepth = 0
local dActMaxDepth = EgtIf( bFacPocketDn, dMaxDepthDn, dMaxDepth)
if dActMaxDepth < dFacElev + dFacCollSic then
dDepth = dActMaxDepth - ( dFacElev + dFacCollSic)
end
EgtSetMachiningParam( MCH_MP.DEPTH, dDepth)
-- dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return -1, sErr
end
end
end
end
return 1, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId
end
end
end
return 0, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId, bOrthoFaces
end
---------------------------------------------------------------------
local function ManageAntiSplintBySaw( Proc, b3Raw, b3Solid, bIsU, vtN, nFacInd, sWarn, bMillDown, bReduceDepth)
local bMadeASbyBld = false
local nNumFac = EgtIf( bIsU, 2, 1)
local nPrefSide = 1 -- di preferenza il motore è meglio tenerlo sinistra
-- se a U cerco di ottimizzare il lato di lavoro della lama
if bIsU then
if abs( vtN:getY()) > 0.996 then
nPrefSide = 0
elseif abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then
-- se X è negativa allora devo tenere il motore a destra
if vtN:getX() < 0.087 then
nPrefSide = 2
end
end
end
-- va eseguito sulle facce diverse dalla principale
local nPrevSCC = nil
for nFacet = 0, nNumFac do
if nFacet ~= nFacInd then
-- lavoro
local dSawThick = 0
local dMaxDepth = 200
local bAdj, dAng, dExtraOffs, sWarn2, nIdMach
bMadeASbyBld, sWarn2, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs = MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth, bMillDown)
if not bMadeASbyBld then return bMadeASbyBld, false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
-- se antischeggia veramente inserito perchè necessario
if nIdMach then
-- verifico se da invertire
local bInvertMach = false
if bIsU then
-- prendo il vettore normale alla faccia
local vtNFc = EgtSurfTmFacetNormVersor( Proc.Id, nFacet, GDB_ID.ROOT)
if abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then
-- se superficie principale parallela al piano XZ
if nPrefSide == 0 then
-- se facce praticamente verticali ||
if abs( vtNFc:getZ()) < 0.1 then
-- se FAST, mandrino a destra o sinistra come svuotatura
if not BD.C_SIMM and not BD.TURN then
local bNearTail = ( Proc.Box:getMax():getX() < b3Solid:getCenter():getX() + 50 and
Proc.Box:getMax():getX() - b3Solid:getMin():getX() < 1000)
local bVeryShortPart = ( BD.LEN_VERY_SHORT_PART and b3Solid:getDimX() < BD.LEN_VERY_SHORT_PART)
nPrefSide = EgtIf( BL.IsPartFinalPhase( EgtGetCurrPhase()) or ( bNearTail and not bVeryShortPart), 1, 2)
-- altrimenti sempre a destra
else
nPrefSide = 2
end
-- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto)
elseif vtNFc:getX() * vtNFc:getZ() > 0 then
nPrefSide = 2
-- altrimenti facce inclinate // quindi mandrino a sinistra (per essere ancora verso l'alto)
else
nPrefSide = 1
end
end
-- se faccia verso X+ e mandrino verso sinistra
if vtNFc:getX() > 0 and nPrefSide == 1 then
-- se angolo interno e circa -90
if abs( dAng + 90) < 5 then
bInvertMach = true
end
-- se faccia verso X- e mandrino verso destra
elseif vtNFc:getX() < 0 and nPrefSide == 2 then
-- se angolo interno e circa -90
if abs( dAng + 90) < 5 then
bInvertMach = true
end
end
end
-- eseguo inversione
if bInvertMach then
local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT)
local bInvert = EgtGetMachiningParam( MCH_MP.INVERT)
local nFaceUse = EgtGetMachiningParam( MCH_MP.FACEUSE)
local bOrtUp = ( nFaceUse >= MCH_MILL_FU.ORTUP_DOWN and nFaceUse <= MCH_MILL_FU.ORTUP_RIGHT)
if not bOrtUp then
-- assegno i parametri invertiti
EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert)
EgtSetMachiningParam( MCH_MP.INVERT, not bInvert)
-- setto l'offset pari allo spessore lama
EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick)
end
end
end
-- posizione del braccio : se primo taglio la recupero, altrimenti la imposto
if not nPrevSCC then
nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC)
elseif abs( vtN:getZ()) > 0.996 then
EgtSetMachiningParam( MCH_MP.SCC, nPrevSCC)
end
-- rieseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nIdMach, false)
return false, false, sErr
end
end
end
end
return bMadeASbyBld, true, sWarn
end
---------------------------------------------------------------------
local function MakePathsOnExtremPoints( nAddGrpId, nIdPath, pPaths, dTDiam)
local dLength = 2
if not nIdPath then return pPaths end
-- prendo i punti iniziali e finali del percorso e i versori direzione
local ptIni = EgtSP( nIdPath, GDB_RT.GLOB)
local ptEnd = EgtEP( nIdPath, GDB_RT.GLOB)
-- se distanza tra i punti è <= del diametro utensile esco
if dist( ptIni, ptEnd) <= dTDiam then return pPaths end
-- prendo i versori iniziali e finali
local vtIni = EgtSV( nIdPath, GDB_RT.GLOB)
local vtEnd = EgtEV( nIdPath, GDB_RT.GLOB)
local ptIniP = ptIni
local ptEndP = ptIniP + (vtIni * dLength)
local nAuxId = EgtLine( nAddGrpId, ptIniP, ptEndP, GDB_RT.GLOB)
table.insert( pPaths, { nAuxId, 1, ptIniP})
ptIniP = ptEnd
ptEndP = ptEnd - ( vtEnd * dLength)
nAuxId = EgtLine( nAddGrpId, ptIniP, ptEndP, GDB_RT.GLOB)
table.insert( pPaths, { nAuxId, 2, ptIniP})
return pPaths
end
---------------------------------------------------------------------
local function MakeAntiSplintByMill( Proc, nPartId, pPaths, nPathInt, vtN1,
bDoubleSide, bOppoSide, sMilling, nPhase, sMyWarn,
dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId)
local sMyWarn2
-- assegno lavorazioni ad ogni percorso
for i = 1, #pPaths do
local nIdPath = pPaths[i][1]
local nSide = pPaths[i][2]
-- modifico versore direzione
EgtModifyCurveExtrusion( nIdPath, vtN1, GDB_RT.GLOB)
local sName
if bOppoSide then
sName = 'AntiSplintOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
else
sName = 'AntiSplint_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
end
local nMchId = EgtAddMachining( sName, sMilling)
if nMchId then
-- aggiungo geometria
EgtSetMachiningGeometry( {{ nIdPath, -1}})
if ( bOppoSide and nSide == 1) or ( not bOppoSide and nSide == 2) then
-- imposto lato di lavoro destro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
else
-- imposto lato di lavoro sinistro
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
end
local nSCC
if bOppoSide then
-- imposto direzione utensile opposta
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
-- imposto posizione braccio porta testa
nSCC = MCH_SCC.ADIR_YM
if not BD.C_SIMM then
if AreSameVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
end
else
local bInvertMach = false
if not nPathInt then
-- imposto posizione braccio porta testa
nSCC = MCH_SCC.ADIR_YM
if vtN1:getY() > 100 * GEO.EPS_ZERO then
nSCC = MCH_SCC.ADIR_YP
end
else
-- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale)
if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
-- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti
elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
bInvertMach = true
end
-- imposto posizione braccio porta testa
nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN1:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN1:getY() < GEO.EPS_SMALL then
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
end
end
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- parametri attacco
EgtSetMachiningParam( MCH_MP.LEADINTYPE, 1)
-- allungo inizio
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 2)
EgtSetMachiningParam( MCH_MP.LITANG, 10)
EgtSetMachiningParam( MCH_MP.LIPERP, -5)
-- parametri uscita
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 0)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
local dMachDepth = 0
local dExtraElev = 0
if bDoubleSide then
dExtraElev = BL.GetFaceElevationFromPointDir( Proc.Id, nPartId, pPaths[i][3], EgtIf( bOppoSide, -vtN1, vtN1)) - dMaxElevMaster
end
local dMaxElev = dMaxElevMaster + dExtraElev
if ( dMaxElev + BD.CUT_EXTRA + dCollSic) > dMaxDepth then
dMachDepth = dMaxDepth - ( dMaxElev + dCollSic)
end
-- setto se devo invertire il percorso
local bInvert = CheckToInvert( nIdPath, true)
if bOppoSide then
EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth)
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
else
EgtSetMachiningParam( MCH_MP.DEPTH, (dMachDepth+dExtraDepth))
EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertMach, not bInvert, bInvert))
end
-- Note utente con dichiarazione nessuna generazione sfridi per Vmill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
-- aggiungo alle note massima elevazione
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( ( dMaxElev + dMachDepth), 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if ML.ApplyMachining( true, false) then
_, sMyWarn2 = EgtGetMachMgrWarning( 0)
if EgtIsMachiningEmpty() then
EgtSetOperationMode( nMchId, false)
else
-- se ho la lavorazione di svuotatura riloco la lavorazione antischeggia prima di questa
if nFirstMachId then
EgtRelocateGlob( nMchId, nFirstMachId, GDB_IN.BEFORE)
end
end
-- altrimenti lavorazione non applicata
else
_, sMyWarn2 = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchId, false)
end
-- altrimenti non è stata inserita lavorazione
else
sMyWarn2 = 'warning adding machining ' .. sName .. '-' .. sMilling
end
end
if sMyWarn2 and #sMyWarn2 > 0 then
sMyWarn = sMyWarn .. '\n' .. sMyWarn2
end
return sMyWarn
end
---------------------------------------------------------------------
local function ManageAntiSplintByMill( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, bMillDown, dDiam, bDoubleSide,
vtOrtho, nPathInt, nSurfInt, b3Solid, dDepth,
bOneShot, nFirstMachId)
local sMyWarn = ''
local pPaths = {}
local nAuxId
local sMilling
-- recupero la lavorazione tenendo conto dell'elevazione
local dCheckDepth
if bDoubleSide then
dCheckDepth = 0.5 * dDepth
else
if not nPathInt then
dCheckDepth = BL.GetFaceElevation( Proc, nFacInd, b3Solid)
else
dCheckDepth = dDepth
end
end
sMilling = ML.FindMilling( 'AntiSplintMillCut', dCheckDepth, nil, nil, nil, not( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide) or
ML.FindMilling( 'AntiSplintMillCut', 2/3 * dCheckDepth, nil, nil, nil, not( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide) or
ML.FindMilling( 'AntiSplintMillCut', nil, nil, nil, nil, not( bMillDown and not bDoubleSide), bMillDown and not bDoubleSide)
if sMilling then
local vtN1
local nFirstId, nNumId
local dMaxElevMaster
local dExtraDepth = 0
local dCollSic
local ptMidDist
-- recupero i dati dell'utensile
local dTDiam = 50
local dMaxDepth = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
end
-- se non ho la faccia aggiunta
if not nPathInt then
-- ottengo i percorsi da cui estrapolare il percorso di antischeggia
local tFacAdjMain = ChooseContour( Proc, nFacInd, false)
local tPaths = {}
-- se non trovato nessun angolo interno valido esco
if #tFacAdjMain == 0 then
return true, sMyWarn
end
-- prendo il primo versore
_, vtN1 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
dCollSic = BL.CalcCollisionSafety( vtN1) or 0
-- se direzione tende verso una delle alle 3 direzioni azzero l'altezza extra
if abs( vtN1:getX()) > 0.7 or abs( vtN1:getY()) > 0.7 or abs( vtN1:getZ()) > 0.7 then dCollSic = 0 end
-- se fresatura da sotto salto la lavorazione
if vtN1:getZ() < BD.DRILL_VZ_MIN and not bMillDown then
local sErr = 'Error : milling from bottom '
EgtOutLog( sErr)
return false, sErr
end
local ptIniPath
local nMaxLen = 0
dMaxElevMaster = BL.GetFaceElevation( Proc, nFacInd, b3Solid)
-- ciclo tutta la tabella
for i = 1, #tFacAdjMain do
-- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo
local ptP1, ptP2, dAng
ptP1 = tFacAdjMain[i][3]
ptP2 = tFacAdjMain[i][4]
dAng = tFacAdjMain[i][5]
if ( dAng < 0 and 180 + dAng >= 90 - 10 * GEO.EPS_SMALL) then
-- creo la linea da P1 a P2
nAuxId = EgtLine( nAddGrpId, ptP1, ptP2, GDB_RT.GLOB)
table.insert( tPaths, nAuxId)
-- prendo la lunghezza massima e il puto medio
if tFacAdjMain[i][2] > nMaxLen then
ptIniPath = ptP1
nMaxLen = tFacAdjMain[i][2]
ptMidDist = ( ptP1 + ptP2) / 2
end
end
end
-- cotruisco il/i percorso/i
nFirstId, nNumId = EgtCurveCompoByReorder( nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB)
local bOkPath = true
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
if EgtCurveIsClosed( nIdPath) then
bOkPath = false
end
end
-- se ho un percorso chiuso cancello tutto
if not bOkPath then
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
EgtErase(nIdPath)
end
else
-- creo percorsi antisplint dagli estremi dei percorsi di contorno trovati
for i = 1, nNumId do
local nIdPath = nFirstId + i - 1
pPaths = MakePathsOnExtremPoints( nAddGrpId, nIdPath, pPaths, dTDiam)
end
end
-- alrimenti ho la faccia aggiunta
else
dCollSic = BL.CalcCollisionSafety( vtOrtho)
nFirstId = EgtCopyGlob( nPathInt, nAddGrpId)
nNumId = 1
-- calcolo elevazione dalla faccia trasversale aggiunta
if bDoubleSide then
dMaxElevMaster = 0.5 * dDepth
else
dMaxElevMaster = dDepth
-- se la precedente svuotatura è stata fatta completamente in una sola volta
-- valuto di nuovo se devo fare due passate o una sola
if bOneShot then
-- se non è possibile svuotare completamente da una sola parte
if dMaxDepth <= ( dMaxElevMaster + BD.CUT_EXTRA + dCollSic) then
bDoubleSide = true
dMaxElevMaster = BL.GetFaceElevation( nSurfInt, 0, b3Solid)
else
dExtraDepth = dMaxElevMaster - BL.GetFaceElevation( nSurfInt, 0, b3Solid)
end
-- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie
else
dExtraDepth = dMaxElevMaster - BL.GetFaceElevation( nSurfInt, 0, b3Solid)
end
end
vtN1 = Vector3d(vtOrtho)
BL.SetOpenSide( nFirstId, b3Solid)
local bOpenPath = BL.ChangeOrOpenStart( nFirstId, 2)
-- se non ho un percorso chiuso estraggo i percorsi
if bOpenPath then
-- creo percorsi antisplint dagli estremi dei percorsi di contorno trovati
pPaths = MakePathsOnExtremPoints( nAddGrpId, nFirstId, pPaths, dTDiam)
end
EgtErase(nFirstId)
end
if #pPaths > 0 then
sMyWarn = MakeAntiSplintByMill( Proc, nPartId, pPaths, nPathInt, vtN1,
bDoubleSide, false, sMilling, nPhase, sMyWarn,
dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId)
if bDoubleSide then
if bMillDown then
local sMillingDn = ML.FindMilling( 'AntiSplintMillCut_H2', dCheckDepth) or
ML.FindMilling( 'AntiSplintMillCut_H2', 2/3 * dCheckDepth) or
ML.FindMilling( 'AntiSplintMillCut_H2')
sMilling = sMillingDn
-- controllo dati lavorazione
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam
dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth
end
end
-- se lavorazione valida
if sMilling then
sMyWarn = MakeAntiSplintByMill( Proc, nPartId, pPaths, nPathInt, vtN1,
bDoubleSide, true, sMilling, nPhase, sMyWarn,
dMaxElevMaster, dExtraDepth, dCollSic, dMaxDepth, nFirstMachId)
else
sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' clean corner milling/tool not found in library'
end
end
-- altrimenti non c'è il percorso
else
sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' impossible make clean corner path'
end
-- altrimenti non è stata trovata lavorazione
else
sMyWarn = 'warning in process ' .. tostring( Proc.Id) .. ' clean corner milling/tool not found in library'
end
if #sMyWarn > 0 then
EgtOutLog( sMyWarn)
end
return true, sMyWarn
end
---------------------------------------------------------------------
local function MakeTunnelByChainSaw( Proc, sSawing, nLundIdFace, vtOrtho, dWorkDepth, dMaxMat, nStep, dStep, sFaceUse, bOpposite)
for i = 1, nStep do
-- inserisco la lavorazione di sawing
local sName = ''
if bOpposite then
sName = 'Csaw_Opp_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
else
sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i)
end
local nMchFId = EgtAddMachining( sName, sSawing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nLundIdFace}})
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nLundIdFace, GDB_ID.ROOT)
-- imposto angolo 3° asse rot
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sSawing, 'perpendicular'))
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtN, vtOrtho, 1))
-- imposto offset radiale
local dOffs = ( i - 1) * dStep
EgtSetMachiningParam( MCH_MP.OFFSR, dOffs)
EgtSetMachiningParam( MCH_MP.FACEUSE, sFaceUse)
EgtSetMachiningParam( MCH_MP.DEPTH, dWorkDepth)
-- modifico la distanza di attacco per considerare anche tunnel inclinati
EgtSetMachiningParam( MCH_MP.STARTPOS, 50)
-- eseguo
if not ML.ApplyMachining( true, false) then
if EgtGetOutstrokeInfo() then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sSawing, 'parallel'))
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtN, vtOrtho, 2))
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
if EgtIsMachiningEmpty() then
_, sWarn = EgtGetMachMgrWarning( 0)
EgtSetOperationMode( nMchFId, false)
return false, sWarn
end
end
return true
end
---------------------------------------------------------------------
--#region SawPlusChain
-- 5 facce: la faccia di fondo è il fondo della tasca, la faccia da lavorare è grande, le facce laterali sono le due piccole
-- 4 facce con faccia di fondo piccola: la faccia da lavorare è grande (2 adj) e l'unica faccia laterale è piccola
-- 4 facce con faccia di fondo grande: la faccia da lavorare è piccola (3 adj) e le facce laterali sono le due piccole
-- 3 facce: la faccia di fondo è il fondo della tasca, la faccia da lavorare è grande, non ci sono facce laterali
-- TODO gestione messaggi in funzione apposita (almeno per append)
local SawPlusChain = {}
SawPlusChain.Saw = {}
SawPlusChain.Chainsaw = {}
SawPlusChain.Name = 'SawPlusChain'
SawPlusChain.ApplyOnlySawblade = false
function SawPlusChain.IsTopologyOk( Proc)
if Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' or
Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' or
Proc.TopologyLongName == 'Groove-Through-RightAngles-NotParallel-3' or
Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' or
Proc.TopologyLongName == 'Tunnel-Through-RightAngles-Parallel-4' then
return true
else
return false
end
end
function SawPlusChain.GetTunnelFaces( Proc)
local TunnelAddedFaces = {}
-- TODO scrivere il box della parte nella Proc o fare funzione per recuperarlo
local b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Proc.PartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not ( Proc.IsThrough and Proc.AllRightAngles and Proc.Fct < 5) then
error( 'GetTunnelFaces : Topology not implemented')
end
-- direzione del tunnel
local vtTunnelDirection = Proc.Face[1].VtN ^ Proc.Face[ Proc.Face[1].Adjacencies[1] + 1].VtN
-- centro del tunnel
local frTunnel = Frame3d( Proc.Face[1].PtCenter, vtTunnelDirection)
local b3Tunnel = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frTunnel)
local ptTunnelCenter = b3Tunnel:getCenter()
ptTunnelCenter:toGlob( frTunnel)
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( Proc.PartId)
if not nAddGrpId then
EgtOutLog( 'Error : missing AddGroup')
return TunnelAddedFaces
end
-- faccia centrale, si crea larga come la parte e poi si trimma
TunnelAddedFaces.MiddleFaceTm = {}
TunnelAddedFaces.MiddleFaceTm.Id = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, b3Part, GDB_ID.ROOT)
-- TODO se non si riesce a costruire la faccia bisogna dare errore o semplicemente non ritornarla??
for i = 1, Proc.Fct do
EgtCutSurfTmPlane( TunnelAddedFaces.MiddleFaceTm.Id, Proc.Face[i].PtCenter, -Proc.Face[i].VtN, false, GDB_ID.ROOT)
end
local _, dFaceWidth, dFaceHeight = BL.GetFaceHvRefDim( TunnelAddedFaces.MiddleFaceTm.Id, 0)
-- larghezza OCS faccia
TunnelAddedFaces.MiddleFaceTm.Width = dFaceWidth
-- altezza OCS faccia
TunnelAddedFaces.MiddleFaceTm.Height = dFaceHeight
if TunnelAddedFaces.MiddleFaceTm.Height > TunnelAddedFaces.MiddleFaceTm.Width then
TunnelAddedFaces.MiddleFaceTm.Height, TunnelAddedFaces.MiddleFaceTm.Width = TunnelAddedFaces.MiddleFaceTm.Width, TunnelAddedFaces.MiddleFaceTm.Height
end
TunnelAddedFaces.MiddleFaceTm.Type = 'Tunnel'
return TunnelAddedFaces
end
function SawPlusChain.GetBottomFace( Proc)
local BottomFace = {}
if Proc.Topology == 'Tunnel' then
return nil
end
-- la faccia di fondo ha sempre Fct - 1 adiacenze. Se si trovano più facce di fondo si sceglie quella con minor elevazione
local vBottomFace = Topology.GetFacesWithGivenAdjacencyNumber( Proc, Proc.vAdj, Proc.Fct - 1)
local nBottomFace
if #vBottomFace > 1 then
local dMinElevation = GEO.INFINITO
for i = 1, #vBottomFace do
for j = 1, Proc.Fct do
if vBottomFace[i] == Proc.Face[j].Id then
if Proc.Face[j].Elevation < dMinElevation then
dMinElevation = Proc.Face[j].Elevation
nBottomFace = Proc.Face[j].Id
end
end
end
end
else
nBottomFace = vBottomFace[1]
end
BottomFace.Id = nBottomFace
BottomFace.Type = 'Bottom'
BottomFace.Width = Proc.Face[nBottomFace + 1].Width
BottomFace.Height = Proc.Face[nBottomFace + 1].Height
BottomFace.Elevation = Proc.Face[nBottomFace + 1].Elevation
BottomFace.VtN = Proc.Face[nBottomFace + 1].VtN
if BottomFace.Height > BottomFace.Width then
BottomFace.Height, BottomFace.Width = BottomFace.Width, BottomFace.Height
end
return BottomFace
end
function SawPlusChain.GetLongFace( Proc)
local LongFace = {}
if not Proc.MainFaces.BottomFace or not Proc.MainFaces.BottomFace.Id then
Proc.MainFaces.BottomFace = SawPlusChain.GetBottomFace( Proc)
end
local FacesToAnalyze = {}
-- tutte le facce, ordinate per dimensione
if Proc.Topology == 'Tunnel' then
for i = 1, Proc.Fct do
FacesToAnalyze[i] = {}
FacesToAnalyze[i].Id = Proc.Face[i].Id
FacesToAnalyze[i].Area = Proc.Face[i].Area
FacesToAnalyze[i].LengthOnMainFace = Proc.Face[i].LengthOnMainFace
end
table.sort( FacesToAnalyze, function( a, b) return a.Area > b.Area end)
-- facce adiacenti a quella di fondo, ordinate per lunghezza sul lato di fondo
else
FacesToAnalyze = BL.GetAdjacentFaces( Proc, Proc.MainFaces.BottomFace.Id)
table.sort( FacesToAnalyze, function( a, b) return a.LengthOnMainFace > b.LengthOnMainFace end)
end
-- si sceglie la più grande (tunnel) o quella adiacente sul lato lungo
LongFace.Id = FacesToAnalyze[1].Id
for i = 1, Proc.Fct do
if LongFace.Id == Proc.Face[i].Id then
LongFace.Type = 'Long'
LongFace.Width = Proc.Face[i].Width
LongFace.Height = Proc.Face[i].Height
LongFace.Elevation = Proc.Face[i].Elevation
LongFace.VtN = Proc.Face[i].VtN
if LongFace.Height > LongFace.Width then
LongFace.Height, LongFace.Width = LongFace.Width, LongFace.Height
end
end
end
return LongFace
end
function SawPlusChain.GetSideFaces( Proc)
if not Proc.MainFaces.BottomFace or not Proc.MainFaces.BottomFace.Id then
Proc.MainFaces.BottomFace = SawPlusChain.GetBottomFace( Proc)
end
if not Proc.MainFaces.LongFace or not Proc.MainFaces.LongFace.Id then
Proc.MainFaces.LongFace = SawPlusChain.GetLongFace( Proc)
end
local FacesToAnalyze = {}
-- tutte le facce, ordinate per dimensione
if Proc.Topology == 'Tunnel' then
for i = 1, Proc.Fct do
FacesToAnalyze[i] = {}
FacesToAnalyze[i].Id = Proc.Face[i].Id
FacesToAnalyze[i].Area = Proc.Face[i].Area
FacesToAnalyze[i].LengthOnMainFace = Proc.Face[i].LengthOnMainFace
end
table.sort( FacesToAnalyze, function( a, b) return a.Area > b.Area end)
-- facce adiacenti a quella di fondo, ordinate per lunghezza sul lato di fondo
else
FacesToAnalyze = BL.GetAdjacentFaces( Proc, Proc.MainFaces.BottomFace.Id)
table.sort( FacesToAnalyze, function( a, b) return a.LengthOnMainFace > b.LengthOnMainFace end)
end
-- si determina il criterio di scelta delle facce laterali
local FacesAdjacentToLongFace = BL.GetAdjacentFaces( Proc, Proc.MainFaces.LongFace.Id)
local bIsLongFaceTheLargest = not ( Proc.Fct == 4 and #FacesAdjacentToLongFace == 3)
local SideFaces = {}
for i = 1, #FacesToAnalyze do
if ( not bIsLongFaceTheLargest and i < #FacesToAnalyze) or
( bIsLongFaceTheLargest and i > 2) then
table.insert( SideFaces, FacesToAnalyze[i])
SideFaces[#SideFaces].Id = FacesToAnalyze[i].Id
SideFaces[#SideFaces].Type = 'Side'
SideFaces[#SideFaces].Width = Proc.Face[FacesToAnalyze[i].Id + 1].Width
SideFaces[#SideFaces].Height = Proc.Face[FacesToAnalyze[i].Id + 1].Height
SideFaces[#SideFaces].Elevation = Proc.Face[FacesToAnalyze[i].Id + 1].Elevation
SideFaces[#SideFaces].VtN = Proc.Face[FacesToAnalyze[i].Id + 1].VtN
if SideFaces[#SideFaces].Height > SideFaces[#SideFaces].Width then
SideFaces[#SideFaces].Height, SideFaces[#SideFaces].Width = SideFaces[ #SideFaces].Width, SideFaces[ #SideFaces].Height
end
end
end
return SideFaces
end
function SawPlusChain.GetBottomFaceEdges( Proc, Face)
local Edges = {}
Edges.SideEdges = {}
Edges.LongEdges = {}
local nFaceType, vEdges = EgtSurfTmGetFacetOutlineInfo( Proc.Id, Face.Id, GDB_ID.ROOT)
if nFaceType < 1 then
for j = 1, #vEdges do
local nPreviousEdgeIndex = j - 1
if j == 1 then
nPreviousEdgeIndex = #vEdges
end
local nNextEdgeIndex = j + 1
if j == #vEdges then
nNextEdgeIndex = 1
end
local CurrentEdge = {}
CurrentEdge.AdjacentFaceId = vEdges[j].Adj
CurrentEdge.ToolDirection = Vector3d( vEdges[j].Norm)
CurrentEdge.Length = vEdges[j].Len
CurrentEdge.Elevation = vEdges[j].Elev
CurrentEdge.IsOpen = vEdges[j].Open
CurrentEdge.IsStartOpen = ( vEdges[nPreviousEdgeIndex].Open)
CurrentEdge.IsEndOpen = ( vEdges[nNextEdgeIndex].Open)
CurrentEdge.Id = j - 1
if CurrentEdge.AdjacentFaceId == Proc.MainFaces.LongFace.Id then
table.insert( Edges.LongEdges, CurrentEdge)
Edges.LongEdges[#Edges.LongEdges].Type = 'Long'
elseif vEdges[nNextEdgeIndex].Adj == Proc.MainFaces.LongFace.Id or vEdges[nPreviousEdgeIndex].Adj == Proc.MainFaces.LongFace.Id then
table.insert( Edges.SideEdges, CurrentEdge)
Edges.SideEdges[#Edges.SideEdges].Type = 'Side'
else
table.insert( Edges.LongEdges, CurrentEdge)
Edges.LongEdges[#Edges.LongEdges].Type = 'Long'
end
end
else
error( 'Face with closed hole')
end
return Edges
end
function SawPlusChain.GetLongFaceEdges( Proc, Face)
local Edges = {}
Edges.SideEdges = {}
Edges.OppositeEdges = {}
local nFaceType, vEdges = EgtSurfTmGetFacetOutlineInfo( Proc.Id, Face.Id, GDB_ID.ROOT)
if nFaceType < 1 then
for j = 1, #vEdges do
local nPreviousEdgeIndex = j - 1
if j == 1 then
nPreviousEdgeIndex = #vEdges
end
local nNextEdgeIndex = j + 1
if j == #vEdges then
nNextEdgeIndex = 1
end
local CurrentEdge = {}
CurrentEdge.AdjacentFaceId = vEdges[j].Adj
CurrentEdge.ToolDirection = Vector3d( vEdges[j].Norm)
CurrentEdge.Length = vEdges[j].Len
CurrentEdge.Elevation = vEdges[j].Elev
CurrentEdge.IsOpen = vEdges[j].Open
CurrentEdge.IsStartOpen = ( vEdges[nPreviousEdgeIndex].Open)
CurrentEdge.IsEndOpen = ( vEdges[nNextEdgeIndex].Open)
CurrentEdge.Id = j - 1
if Proc.Topology == 'Tunnel' then
if CurrentEdge.AdjacentFaceId > -1 then
table.insert( Edges.SideEdges, CurrentEdge)
else
table.insert( Edges.OppositeEdges, CurrentEdge)
end
else
if CurrentEdge.AdjacentFaceId == Proc.MainFaces.BottomFace.Id then
Edges.BottomEdge = CurrentEdge
Edges.BottomEdge.Type = 'Bottom'
elseif vEdges[nNextEdgeIndex].Adj == Proc.MainFaces.BottomFace.Id then
Edges.SideEdges.StartEdge = CurrentEdge
Edges.SideEdges.StartEdge.Type = 'Side'
elseif vEdges[nPreviousEdgeIndex].Adj == Proc.MainFaces.BottomFace.Id then
Edges.SideEdges.EndEdge = CurrentEdge
Edges.SideEdges.EndEdge.Type = 'Side'
else
table.insert( Edges.OppositeEdges, CurrentEdge)
Edges.OppositeEdges[#Edges.OppositeEdges].Type = 'Opposite'
end
end
end
else
error( 'Face with closed hole')
end
return Edges
end
function SawPlusChain.CalculateLeadInOut( Machining, EdgeToMachine)
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
-- si determina l'eventuale riduzione da applicare in caso di inizio o fine chiusi
local bIsMortising = ( Machining.Type == MCH_OY.MORTISING)
local dAddLengthToReduce = 0
if bIsMortising then
dAddLengthToReduce = Machining.Tool.Diameter / 2
else
dAddLengthToReduce = sqrt( Machining.Depth * Machining.Tool.Diameter - Machining.Depth * Machining.Depth)
end
if Machining.Invert then
Machining.IsStartClosed, Machining.IsEndClosed = Machining.IsEndClosed, Machining.IsStartClosed
end
local LeadIn = {}
local LeadOut = {}
LeadIn.StartAddLength = 0
LeadOut.EndAddLength = 0
if not bIsMortising then
LeadIn.Type = MCH_MILL_LI.LINEAR
LeadOut.Type = MCH_MILL_LI.LINEAR
LeadIn.TangentDistance = 0
LeadOut.TangentDistance = 0
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL then
LeadIn.PerpDistance = EdgeToMachine.Elevation + BD.CUT_SIC
LeadOut.PerpDistance = EdgeToMachine.Elevation + BD.CUT_SIC
else
LeadIn.PerpDistance = BD.CUT_SIC
LeadOut.PerpDistance = BD.CUT_SIC
end
LeadIn.Elevation = 0
LeadOut.Elevation = 0
LeadIn.CompLength = 0
LeadOut.CompLength = 0
if Machining.IsStartClosed and Machining.IsEndClosed then
LeadIn.StartAddLength = -dAddLengthToReduce
LeadOut.EndAddLength = -dAddLengthToReduce
elseif Machining.IsStartClosed then
LeadIn.StartAddLength = -dAddLengthToReduce
-- eventuale correzione per accorciamento maggiore di larghezza tasca
LeadOut.EndAddLength = max( -LeadIn.StartAddLength - EdgeToMachine.Length + 10 * BD.CUT_EXTRA, BD.CUT_EXTRA)
elseif Machining.IsEndClosed then
LeadOut.EndAddLength = -dAddLengthToReduce
-- eventuale correzione per accorciamento maggiore di larghezza tasca
LeadIn.StartAddLength = max( -LeadOut.EndAddLength - EdgeToMachine.Length + 10 * BD.CUT_EXTRA, BD.CUT_EXTRA)
else
LeadIn.StartAddLength = BD.CUT_EXTRA
LeadOut.EndAddLength = BD.CUT_EXTRA
end
else
if Machining.IsStartClosed then
LeadIn.StartAddLength = -dAddLengthToReduce
else
LeadIn.StartAddLength = BD.CUT_EXTRA
end
if Machining.IsEndClosed then
LeadOut.EndAddLength = -dAddLengthToReduce
else
LeadOut.EndAddLength = BD.CUT_EXTRA
end
end
return LeadIn, LeadOut
end
function SawPlusChain.ApplyMachining( Machining, b3Raw)
local sErr = ''
local nOperationId = EgtAddMachining( Machining.OperationName, Machining.Name)
if not nOperationId then
sErr = 'Error adding machining ' .. Machining.OperationName .. '-' .. Machining.Name
EgtOutLog( sErr)
return false, sErr
end
-- impostazione parametri lavorazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
EgtSetMachiningGeometry( Machining.Geometry)
EgtSetMachiningParam( MCH_MP.FACEUSE, Machining.Faceuse)
EgtSetMachiningParam( MCH_MP.SCC, Machining.SCC)
EgtSetMachiningParam( MCH_MP.INVERT, Machining.Invert)
EgtSetMachiningParam( MCH_MP.WORKSIDE, Machining.Workside)
EgtSetMachiningParam( MCH_MP.TOOLINVERT, Machining.ToolInvert)
EgtSetMachiningParam( MCH_MP.OFFSR, Machining.RadialOffset)
EgtSetMachiningParam( MCH_MP.OFFSL, Machining.LongitudinalOffset)
if Machining.Type ~= MCH_OY.MORTISING then
EgtSetMachiningParam( MCH_MP.LEADINTYPE, Machining.LeadIn.Type)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, Machining.LeadOut.Type)
EgtSetMachiningParam( MCH_MP.LITANG, Machining.LeadIn.TangentDistance)
EgtSetMachiningParam( MCH_MP.LOTANG, Machining.LeadOut.TangentDistance)
EgtSetMachiningParam( MCH_MP.LIPERP, Machining.LeadIn.PerpDistance)
EgtSetMachiningParam( MCH_MP.LOPERP, Machining.LeadOut.PerpDistance)
EgtSetMachiningParam( MCH_MP.LIELEV, Machining.LeadIn.Elevation)
EgtSetMachiningParam( MCH_MP.LOELEV, Machining.LeadOut.Elevation)
EgtSetMachiningParam( MCH_MP.LICOMPLEN, Machining.LeadIn.CompLength)
EgtSetMachiningParam( MCH_MP.LOCOMPLEN, Machining.LeadOut.CompLength)
end
EgtSetMachiningParam( MCH_MP.STARTADDLEN, Machining.LeadIn.StartAddLength)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, Machining.LeadOut.EndAddLength)
if Machining.Steps then
if Machining.Steps.StepType then
EgtSetMachiningParam( MCH_MP.STEPTYPE, Machining.Steps.StepType)
end
if Machining.Steps.StepLength then
EgtSetMachiningParam( MCH_MP.STEP, Machining.Steps.StepLength)
end
end
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( Machining.Name, Machining.BlockedAxis.Orientation, b3Raw, Machining.BlockedAxis.VtN, Machining.BlockedAxis.VtOut))
if Machining.Type == MCH_OY.MORTISING then
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( Machining.SuggestedAngles.VtN, Machining.SuggestedAngles.VtOrtho, Machining.SuggestedAngles.Index))
end
EgtSetMachiningParam( MCH_MP.OVERL, Machining.Overlap)
EgtSetMachiningParam( MCH_MP.STARTPOS, max( Machining.StartSafetyLength, EgtGetMachiningParam( MCH_MP.STARTPOS)))
if Machining.MaxElev then
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', Machining.MaxElev)
end
if Machining.nEdgeFaceUse then
sUserNotes = EgtSetValInNotes( sUserNotes, 'EdgesFaceUse', EgtNumToString( Machining.nEdgeFaceUse))
end
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
local bIsApplyOk = ML.ApplyMachining( true, false)
if not bIsApplyOk then
local nErr
nErr, sErr = EgtGetLastMachMgrError()
-- se mortasatura e l'errore è compatibile (Axes values not calculable) si prova con l'altra configurazione dell'asse bloccato
if Machining.Type == MCH_OY.MORTISING then
-- se errore "Axes values not calculable" si prova con l'altra configurazione dell'asse bloccato
if nErr == 2507 then
if Machining.BlockedAxis.Orientation == 'perpendicular' then
Machining.BlockedAxis.Orientation = 'parallel'
else
Machining.BlockedAxis.Orientation = 'perpendicular'
end
EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( Machining.Name, Machining.BlockedAxis.Orientation, b3Raw, Machining.BlockedAxis.VtN, Machining.BlockedAxis.VtOut))
if Machining.SuggestedAngles.Index == 1 then
Machining.SuggestedAngles.Index = 2
else
Machining.SuggestedAngles.Index = 1
end
EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( Machining.SuggestedAngles.VtN, Machining.SuggestedAngles.VtOrtho, Machining.SuggestedAngles.Index))
sErr = ''
bIsApplyOk = ML.ApplyMachining( true, false)
-- se errore "Outstroke" e permesso ToolInvert provo ad invertire il lato di lavorazione
elseif Machining.AllowToolInvert and nErr == 2508 then
EgtSetMachiningParam( MCH_MP.TOOLINVERT, not Machining.ToolInvert)
sErr = ''
bIsApplyOk = ML.ApplyMachining( true, false)
end
end
if not bIsApplyOk then
nErr, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nOperationId, false)
return false, sErr
end
end
return true, sErr
end
function SawPlusChain.Saw.GetSCC( vtMachiningDirection)
-- TODO implementare SCC come per FacesBySaw
local nSCC = MCH_SCC.NONE
if AreSameVectorApprox( vtMachiningDirection, Z_AX()) then
nSCC = MCH_SCC.ADIR_ZP
elseif AreOppositeVectorApprox( vtMachiningDirection, Z_AX()) then
nSCC = MCH_SCC.ADIR_ZM
elseif AreSameVectorApprox( vtMachiningDirection, Y_AX()) then
nSCC = MCH_SCC.ADIR_YP
elseif AreOppositeVectorApprox( vtMachiningDirection, Y_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif AreSameVectorApprox( vtMachiningDirection, X_AX()) then
nSCC = MCH_SCC.ADIR_XP
elseif AreOppositeVectorApprox( vtMachiningDirection, X_AX()) then
nSCC = MCH_SCC.ADIR_XM
end
return nSCC
end
function SawPlusChain.Saw.CalculateMachiningParameters( Proc, FaceToMachine, EdgeToMachine)
local Cutting = {}
Cutting.CanApply = true
Cutting.Message = ''
Cutting.ProcId = Proc.Id
local dPocketHeight = 0
if Proc.Topology == 'Tunnel' then
dPocketHeight = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Height
else
if FaceToMachine.Type == 'Long' then
dPocketHeight = Proc.MainFaces.BottomFace.Edges.SideEdges[1].Length
elseif FaceToMachine.Type == 'Side' then
dPocketHeight = Proc.MainFaces.BottomFace.Edges.LongEdges[1].Length
end
end
-- ricerca lavorazione
Cutting.Name = ML.FindCutting( 'HeadSide', true, false, abs( EdgeToMachine.Elevation))
if not Cutting.Name then
-- ricerca lavorazione senza considerare massima elevazione
Cutting.Name = ML.FindCutting( 'HeadSide', true, false, nil, 'Longest')
if not Cutting.Name then
Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - saw blade not found'
Cutting.CanApply = false
EgtOutLog( Cutting.Message)
return Cutting
end
end
Cutting.Type = MCH_OY.MILLING
Cutting.Tool = BL.GetToolFromMachining( Cutting.Name)
-- verifica dimensioni tasca e direzione compatibili
-- se tasca meno spessa della lama la strategia non è applicabile
if Cutting.Tool.Thickness > dPocketHeight + 10 * GEO.EPS_SMALL then
Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - pocket too narrow for saw blade thickness'
Cutting.CanApply = false
EgtOutLog( Cutting.Message)
end
if #( Proc.MainFaces.SideFaces) > 1 then
-- se tasca più stretta della lama la strategia non è applicabile
if Cutting.Tool.Diameter > EdgeToMachine.Length + 10 * GEO.EPS_SMALL then
Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - pocket too narrow for saw blade diameter'
Cutting.CanApply = false
EgtOutLog( Cutting.Message)
end
end
if EdgeToMachine.ToolDirection:getZ() < BD.NZ_MINA and BD.C_SIMM then
Cutting.CanApply = false
Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : skipped sawblade from bottom'
EgtOutLog( Cutting.Message)
end
-- parametri della lavorazione
-- inizio e fine aperti o chiusi
Cutting.IsStartClosed = not EdgeToMachine.IsStartOpen
Cutting.IsEndClosed = not EdgeToMachine.IsEndOpen
-- lato di lavoro e inversioni
if Cutting.Tool.IsCCW then
Cutting.Workside = MCH_MILL_WS.RIGHT
Cutting.Invert = true
else
Cutting.Workside = MCH_MILL_WS.LEFT
Cutting.Invert = false
end
if EdgeToMachine.Elevation < -10 * GEO.EPS_SMALL then
Cutting.Invert = not Cutting.Invert
end
-- TODO gestire lama da sotto e lama downUp
if FaceToMachine.VtN:getZ() < - 10 * GEO.EPS_SMALL then
Cutting.ToolInvert = true
Cutting.Invert = not Cutting.Invert
else
Cutting.ToolInvert = false
end
-- profondità e offset radiale
if Cutting.Tool.MaxDepth > abs( EdgeToMachine.Elevation) - 10 * GEO.EPS_SMALL then
-- TODO la depth dovrebbe essere quella del machining
Cutting.Depth = abs( EdgeToMachine.Elevation)
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL then
Cutting.RadialOffset = 0
else
Cutting.RadialOffset = EdgeToMachine.Elevation
end
else
Cutting.Depth = Cutting.Tool.MaxDepth - 1
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL then
Cutting.RadialOffset = EdgeToMachine.Elevation - Cutting.Depth
else
Cutting.RadialOffset = -Cutting.Depth
end
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL and SawPlusChain.ApplyOnlySawblade then
Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : sawblade elevation (' .. EgtNumToString( EdgeToMachine.Elevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Cutting.Depth, 1) .. ')'
EgtOutLog( Cutting.Message)
end
end
-- step verticale e offset longitudinale
Cutting.Steps = BL.GetMachiningSteps( dPocketHeight, Cutting.Tool.Thickness)
Cutting.Steps.StepType = MCH_MILL_ST.ONEWAY
Cutting.MaxElev = Cutting.Steps.StepLength * Cutting.Steps.Count - 10 * GEO.EPS_SMALL
if Cutting.ToolInvert and Cutting.Steps.Count > 1 then
Cutting.LongitudinalOffset = - dPocketHeight
else
Cutting.LongitudinalOffset = 0
end
-- distanza di sicurezza
Cutting.StartSafetyLength = 10
-- overlap
Cutting.Overlap = 0
-- faceuse
if EdgeToMachine.Elevation > - 10 * GEO.EPS_SMALL then
Cutting.Faceuse = BL.GetNearestOrthoOpposite( EdgeToMachine.ToolDirection)
else
Cutting.Faceuse = BL.GetNearestOrthoOpposite( -EdgeToMachine.ToolDirection)
end
Cutting.nEdgeFaceUse = EdgeToMachine.Id
-- SCC
Cutting.SCC = SawPlusChain.Saw.GetSCC( EdgeToMachine.ToolDirection)
-- asse bloccato
Cutting.BlockedAxis = {}
Cutting.BlockedAxis.Orientation = 'perpendicular'
Cutting.BlockedAxis.VtN = FaceToMachine.VtN
Cutting.BlockedAxis.VtOut = EgtIf( FaceToMachine.VtN:getX() > 0, X_AX(), -X_AX())
-- approccio e retrazione
Cutting.LeadIn, Cutting.LeadOut = SawPlusChain.CalculateLeadInOut( Cutting, EdgeToMachine)
-- eventuale step orizzontale
Cutting.HorizontalSteps = {}
if Cutting.Tool.SideStep then
Cutting.HorizontalSteps = BL.GetMachiningSteps( Cutting.Depth, Cutting.Tool.SideStep)
else
Cutting.HorizontalSteps.Count = 1
Cutting.HorizontalSteps.StepLength = 0
end
-- geometria
Cutting.Geometry = {{Proc.Id, FaceToMachine.Id}}
-- nome operazione
Cutting.OperationName = 'Cut_' .. ( EgtGetName( Cutting.ProcId) or tostring( Cutting.ProcId)) .. '_' .. tostring( FaceToMachine.Id + 1)
-- eventuale avviso di danneggiamento pezzo successivo
local dOffsideLength = max( Cutting.LeadIn.StartAddLength, Cutting.LeadOut.EndAddLength) + Cutting.Tool.Diameter / 2 + 10 * GEO.EPS_SMALL
if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and ( Proc.DistanceToNextPart < dOffsideLength) then
local sDamageNextPieceMessage = 'Feature '.. Proc.FeatureId .. ' : sawblade can damage next piece.'
if #Cutting.Message > 0 then
Cutting.Message = Cutting.Message .. '\n' .. sDamageNextPieceMessage
else
Cutting.Message = sDamageNextPieceMessage
end
EgtOutLog( sDamageNextPieceMessage)
end
return Cutting
end
function SawPlusChain.Saw.ApplyAllSteps( Cutting, b3Raw)
local bIsCuttingOk = false
local sCuttingOriginalMessage = Cutting.Message or ''
local sCuttingApplyMessage = ''
local dOriginalRadialOffset = Cutting.RadialOffset
local dOriginalLeadInPerpDistance = Cutting.LeadIn.PerpDistance
local dOriginalLeadOutPerpDistance = Cutting.LeadOut.PerpDistance
for i = Cutting.HorizontalSteps.Count, 1, -1 do
Cutting.RadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.StepLength * ( i - 1)
-- update distanza perpendicolare attacco per contemplare l'offset applicato
Cutting.LeadIn.PerpDistance = dOriginalLeadInPerpDistance - Cutting.RadialOffset
Cutting.LeadOut.PerpDistance = dOriginalLeadOutPerpDistance - Cutting.RadialOffset
-- applicazione lavorazione
bIsCuttingOk, sCuttingApplyMessage = SawPlusChain.ApplyMachining( Cutting, b3Raw)
-- update messaggi
if sCuttingApplyMessage and #sCuttingApplyMessage > 0 then
sCuttingApplyMessage = sCuttingOriginalMessage .. '\n' .. sCuttingApplyMessage .. 'Apply : ' .. sCuttingApplyMessage .. '\n'
else
sCuttingApplyMessage = sCuttingOriginalMessage
end
end
return bIsCuttingOk, sCuttingApplyMessage
end
function SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc, FaceToMachine, EdgeToMachine)
local Mortising = {}
Mortising.CanApply = true
Mortising.Message = ''
Mortising.ProcId = Proc.Id
Mortising.AllowToolInvert = false
local bNeedToMachineOtherSide = false
local dTestCornerRadius = 43
-- OneSide | OneSideAndExtend | BothSides | BothSidesAndExtend
local sMortisingType
local dPocketHeight = 0
if Proc.Topology == 'Tunnel' then
dPocketHeight = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Height
else
if FaceToMachine.Type == 'Long' then
dPocketHeight = Proc.MainFaces.BottomFace.Edges.SideEdges[1].Length
elseif FaceToMachine.Type == 'Side' then
dPocketHeight = Proc.MainFaces.BottomFace.Edges.LongEdges[1].Length
end
end
-- ricerca lavorazione
if Proc.Topology == 'Tunnel' then
Mortising.Name = ML.FindSawing( 'Sawing', abs( EdgeToMachine.Elevation) + dTestCornerRadius + BD.CUT_EXTRA_MIN)
sMortisingType = 'OneSideAndExtend'
if not Mortising.Name then
Mortising.Name = ML.FindSawing( 'Sawing', abs( EdgeToMachine.Elevation) / 2 + dTestCornerRadius + BD.CUT_EXTRA_MIN)
sMortisingType = 'BothSidesAndExtend'
end
elseif EdgeToMachine.Type == 'Side' and #( Proc.MainFaces.SideFaces) == 0 then
Mortising.Name = ML.FindSawing( 'Sawing', abs( EdgeToMachine.Elevation) / 2 + dTestCornerRadius + BD.CUT_EXTRA_MIN)
sMortisingType = 'BothSidesAndExtend'
else
Mortising.Name = ML.FindSawing( 'Sawing', abs( EdgeToMachine.Elevation))
sMortisingType = 'OneSide'
end
if not Mortising.Name then
Mortising.Name = ML.FindSawing( 'Sawing', nil, nil, 'Longest')
if sMortisingType == 'BothSidesAndExtend' then
sMortisingType = 'BothSides'
elseif sMortisingType == 'OneSideAndExtend' then
sMortisingType = 'OneSide'
end
end
if not Mortising.Name then
Mortising.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - chainsaw not found'
Mortising.CanApply = false
EgtOutLog( Mortising.Message)
end
Mortising.Type = MCH_OY.MORTISING
Mortising.Tool = BL.GetToolFromMachining( Mortising.Name)
-- in caso di tunnel da un lato permetto eventuale inversione lato di lavoro in caso di errori di applicazione (es: Outstroke)
if Proc.Topology == 'Tunnel' and sMortisingType == 'OneSide' or sMortisingType == 'OneSideAndExtend' then
Mortising.AllowToolInvert = true
end
-- verifica dimensioni tasca compatibili
-- se tasca meno spessa della sega a catena la strategia non è applicabile
if Mortising.Tool.Thickness > dPocketHeight + 10 * GEO.EPS_SMALL then
Mortising.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - pocket too narrow for chainsaw thickness'
Mortising.CanApply = false
EgtOutLog( Mortising.Message)
end
if #( Proc.MainFaces.SideFaces) > 1 then
-- se tasca più stretta della sega a catena la strategia non è applicabile
if Mortising.Tool.Width > EdgeToMachine.Length + 10 * GEO.EPS_SMALL then
Mortising.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - pocket too narrow for chainsaw width'
Mortising.CanApply = false
EgtOutLog( Mortising.Message)
end
end
if EdgeToMachine.ToolDirection:getZ() < - 10 * GEO.EPS_ANG_SMALL then
Mortising.CanApply = false
Mortising.Message = 'Feature '.. Proc.FeatureId .. ' : skipped chainsaw from bottom'
EgtOutLog( Mortising.Message)
end
-- parametri della lavorazione
-- inizio e fine aperti o chiusi
Mortising.IsStartClosed = not EdgeToMachine.IsStartOpen
Mortising.IsEndClosed = not EdgeToMachine.IsEndOpen
-- lato di lavoro e inversioni
Mortising.Invert = false
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL then
Mortising.Workside = MCH_MILL_WS.RIGHT
Mortising.ToolInvert = false
else
Mortising.Workside = MCH_MILL_WS.LEFT
Mortising.ToolInvert = true
end
-- profondità e offset longitudinale
if sMortisingType == 'OneSide' then
Mortising.Depth = abs( EdgeToMachine.Elevation)
elseif sMortisingType == 'OneSideAndExtend' then
Mortising.Depth = abs( EdgeToMachine.Elevation) + Mortising.Tool.CornerRadius + BD.CUT_EXTRA_MIN
elseif sMortisingType == 'BothSides' then
Mortising.Depth = abs( EdgeToMachine.Elevation) / 2
bNeedToMachineOtherSide = true
elseif sMortisingType == 'BothSidesAndExtend' then
Mortising.Depth = abs( EdgeToMachine.Elevation) / 2 + Mortising.Tool.CornerRadius + BD.CUT_EXTRA_MIN
bNeedToMachineOtherSide = true
end
if Mortising.Tool.MaxMat > Mortising.Depth - 10 * GEO.EPS_SMALL then
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL then
Mortising.LongitudinalOffset = 0
else
Mortising.LongitudinalOffset = abs( EdgeToMachine.Elevation) - Mortising.Depth
end
else
Mortising.Depth = Mortising.Tool.MaxMat - 1
if EdgeToMachine.Elevation > -10 * GEO.EPS_SMALL then
Mortising.LongitudinalOffset = EdgeToMachine.Elevation - Mortising.Depth
else
Mortising.LongitudinalOffset = 0
end
Mortising.Message = 'Feature '.. Proc.FeatureId .. ' : chainsaw elevation (' .. EgtNumToString( EdgeToMachine.Elevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Mortising.Depth, 1) .. ')'
EgtOutLog( Mortising.Message)
end
-- offset radiale
Mortising.RadialOffset = 0
-- distanza di sicurezza
Mortising.StartSafetyLength = EdgeToMachine.Elevation
-- overlap
Mortising.Overlap = 0
-- faceuse
if EdgeToMachine.Elevation > - 10 * GEO.EPS_SMALL then
Mortising.Faceuse = BL.GetNearestParalOpposite( EdgeToMachine.ToolDirection)
else
Mortising.Faceuse = BL.GetNearestParalOpposite( -EdgeToMachine.ToolDirection)
end
-- SCC
Mortising.SCC = MCH_SCC.NONE
-- asse bloccato e angoli suggeriti
Mortising.BlockedAxis = {}
Mortising.BlockedAxis.Orientation = 'perpendicular'
Mortising.BlockedAxis.VtN = FaceToMachine.VtN
Mortising.SuggestedAngles = {}
Mortising.SuggestedAngles.Index = 1
Mortising.SuggestedAngles.VtN = FaceToMachine.VtN
Mortising.SuggestedAngles.VtOrtho = EdgeToMachine.ToolDirection
-- approccio e retrazione
Mortising.LeadIn, Mortising.LeadOut = SawPlusChain.CalculateLeadInOut( Mortising, EdgeToMachine)
-- eventuale step verticale
Mortising.VerticalSteps = BL.GetMachiningSteps( dPocketHeight, Mortising.Tool.Thickness)
-- geometria
Mortising.Geometry = {{Proc.Id, FaceToMachine.Id}}
-- nome operazione
Mortising.OperationName = 'Chainsaw_' .. ( EgtGetName( Mortising.ProcId) or tostring( Mortising.ProcId)) .. '_' .. tostring( FaceToMachine.Id + 1)
-- eventuale avviso di danneggiamento pezzo successivo
local dOffsideLength = max( Mortising.LeadIn.StartAddLength, Mortising.LeadOut.EndAddLength) + Mortising.Tool.Width / 2 + 10 * GEO.EPS_SMALL
if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and ( Proc.DistanceToNextPart < dOffsideLength) then
local sDamageNextPieceMessage = 'Feature '.. Proc.FeatureId .. ' : chainsaw can damage next piece.'
if #Mortising.Message > 0 then
Mortising.Message = Mortising.Message .. '\n' .. sDamageNextPieceMessage
else
Mortising.Message = sDamageNextPieceMessage
end
EgtOutLog( sDamageNextPieceMessage)
end
return Mortising, bNeedToMachineOtherSide
end
function SawPlusChain.Chainsaw.ApplyAllSteps( Mortising, b3Raw)
local bIsMortisingOk = false
local sMortisingApplyMessage = ''
local dOriginalRadialOffsetMortising = Mortising.RadialOffset
for i = Mortising.VerticalSteps.Count, 1, -1 do
Mortising.RadialOffset = dOriginalRadialOffsetMortising + Mortising.VerticalSteps.StepLength * ( i - 1)
-- applicazione lavorazione
bIsMortisingOk, sMortisingApplyMessage = SawPlusChain.ApplyMachining( Mortising, b3Raw)
-- update messaggi
if sMortisingApplyMessage and #sMortisingApplyMessage > 0 then
Mortising.Message = Mortising.Message .. '\n' .. 'Apply : ' .. sMortisingApplyMessage
end
end
return bIsMortisingOk, sMortisingApplyMessage
end
function SawPlusChain.Make( bOnlySaw, Proc, nRawId)
SawPlusChain.ApplyOnlySawblade = bOnlySaw
local b3Raw = EgtGetRawPartBBox( nRawId)
-- TODO per implementare la strategia con lapjoint lunghe bisogna prima riconoscere le topologie che arrivano
if Proc.IsSplittedLapJoint then
local sErr = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not implemented for long lapjoint'
EgtOutLog( sErr)
return false, sErr
end
if not SawPlusChain.IsTopologyOk( Proc) then
local sErr = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not implemented'
EgtOutLog( sErr)
return false, sErr
end
-- se tasca su faccia sotto la strategia non è applicabile (la sega a catena in generale non può lavorare da sotto)
-- TODO se OnlySaw questo test è da rimuovere ma bisogna considerare anche la lama da sotto
if Proc.AffectedFaces.Bottom and ( Proc.Fct > 3 or not Proc.AffectedFaces.Top) then
local sErr = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. SawPlusChain.Name .. ' not applicable - pocket on bottom face'
EgtOutLog( sErr)
return false, sErr
end
-- facce principali
Proc.MainFaces = {}
Proc.MainFaces.BottomFace = SawPlusChain.GetBottomFace( Proc)
Proc.MainFaces.LongFace = SawPlusChain.GetLongFace( Proc)
Proc.MainFaces.SideFaces = SawPlusChain.GetSideFaces( Proc)
if Proc.Topology == 'Tunnel' then
Proc.MainFaces.TunnelAddedFaces = SawPlusChain.GetTunnelFaces( Proc)
else
Proc.MainFaces.BottomFace.Edges = SawPlusChain.GetBottomFaceEdges( Proc, Proc.MainFaces.BottomFace)
end
Proc.MainFaces.LongFace.Edges = SawPlusChain.GetLongFaceEdges( Proc, Proc.MainFaces.LongFace)
-- lama
-- lavorazione di lama - fondo della tasca o fino a massimo materiale se tunnel
local Cutting = {}
if Proc.Topology == 'Tunnel' then
Cutting = SawPlusChain.Saw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.OppositeEdges[1])
else
Cutting = SawPlusChain.Saw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.BottomEdge)
end
local bIsCuttingOk = false
if Cutting.CanApply then
bIsCuttingOk, Cutting.Message = SawPlusChain.Saw.ApplyAllSteps( Cutting, b3Raw)
if not bIsCuttingOk then
return bIsCuttingOk, Cutting.Message
end
end
local dBottomDepthToMachine = Cutting.RadialOffset
-- lato opposto del tunnel
if Proc.Topology == 'Tunnel' then
Cutting = SawPlusChain.Saw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.OppositeEdges[2])
bIsCuttingOk = false
if Cutting.CanApply then
bIsCuttingOk, Cutting.Message = SawPlusChain.Saw.ApplyAllSteps( Cutting, b3Raw)
if not bIsCuttingOk then
return bIsCuttingOk, Cutting.Message
end
end
elseif Proc.IsParallel then
-- se la lama non è arrivata sul fondo e c'è almeno un lato aperto va lavorato
if Cutting.CanApply and Cutting.RadialOffset > 10 * GEO.EPS_SMALL then
-- eventuale lavorazione di lama - lato della tasca da cui inizia la lavorazione
if Proc.MainFaces.LongFace.Edges.BottomEdge.IsStartOpen then
Cutting = SawPlusChain.Saw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.SideEdges.StartEdge)
bIsCuttingOk = false
if Cutting.CanApply then
bIsCuttingOk, Cutting.Message = SawPlusChain.Saw.ApplyAllSteps( Cutting, b3Raw)
if not bIsCuttingOk then
return bIsCuttingOk, Cutting.Message
end
end
end
-- eventuale lavorazione di lama - lato della tasca in cui finisce la lavorazione
if Proc.MainFaces.LongFace.Edges.BottomEdge.IsEndOpen then
Cutting = SawPlusChain.Saw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.SideEdges.EndEdge)
bIsCuttingOk = false
if Cutting.CanApply then
bIsCuttingOk, Cutting.Message = SawPlusChain.Saw.ApplyAllSteps( Cutting, b3Raw)
if not bIsCuttingOk then
return bIsCuttingOk, Cutting.Message
end
end
end
-- la lama è arrivata sul fondo e tasca passante, non servono ulteriori lavorazioni
elseif #( Proc.MainFaces.SideFaces) == 0 then
SawPlusChain.ApplyOnlySawblade = true
end
end
if SawPlusChain.ApplyOnlySawblade then
return bIsCuttingOk, Cutting.Message
end
-- sega a catena
-- parametri lavorazione con sega a catena - fondo della tasca o tunnel
local Mortising = {}
local bNeedToMachineOtherSide = false
if Proc.Topology == 'Tunnel' then
Mortising, bNeedToMachineOtherSide = SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.OppositeEdges[1])
else
Mortising = SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.BottomEdge)
-- si lavora solo quanto non lavorato dalla lama
Mortising.MaxElev = dBottomDepthToMachine + BD.CUT_EXTRA
end
local bIsMortisingOk = false
if Mortising.CanApply then
bIsMortisingOk, Mortising.Message = SawPlusChain.Chainsaw.ApplyAllSteps( Mortising, b3Raw)
end
-- lato opposto del tunnel
if Proc.Topology == 'Tunnel' and bNeedToMachineOtherSide then
Mortising = SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.OppositeEdges[2])
bIsMortisingOk = false
if Mortising.CanApply then
bIsMortisingOk, Mortising.Message = SawPlusChain.Chainsaw.ApplyAllSteps( Mortising, b3Raw)
if not bIsMortisingOk then
return bIsMortisingOk, Mortising.Message
end
end
elseif Proc.IsParallel then
-- se la sega a catena non è arrivata sul fondo e c'è almeno un lato aperto va lavorato
if Mortising.LongitudinalOffset > 10 * GEO.EPS_SMALL then
-- eventuale lavorazione di sega a catena - lato della tasca da cui inizia la lavorazione
if Proc.MainFaces.LongFace.Edges.BottomEdge.IsStartOpen then
Mortising = SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.SideEdges.StartEdge)
bIsMortisingOk = false
if Mortising.CanApply then
bIsMortisingOk, Mortising.Message = SawPlusChain.Chainsaw.ApplyAllSteps( Mortising, b3Raw)
if not bIsMortisingOk then
return bIsMortisingOk, Mortising.Message
end
end
end
-- eventuale lavorazione di sega a catena - lato della tasca in cui finisce la lavorazione
if Proc.MainFaces.LongFace.Edges.BottomEdge.IsEndOpen then
Mortising = SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc, Proc.MainFaces.LongFace, Proc.MainFaces.LongFace.Edges.SideEdges.EndEdge)
bIsMortisingOk = false
if Mortising.CanApply then
bIsMortisingOk, Mortising.Message = SawPlusChain.Chainsaw.ApplyAllSteps( Mortising, b3Raw)
if not bIsMortisingOk then
return bIsMortisingOk, Mortising.Message
end
end
end
end
end
local sFinalMessage = ''
if #Cutting.Message > 0 or #Mortising.Message > 0 then
sFinalMessage = Cutting.Message .. '\n' .. Mortising.Message
end
return bIsMortisingOk, sFinalMessage
end
--#endregion SawPlusChain
---------------------------------------------------------------------
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 = EgtTestConeSurface( 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 = EgtTestCylSurface( frOriTool, dDiam2/2, dTall2, nNewProc, 0, GDB_RT.GLOB)
if bColl2 then return true end
local ptCentrGrid3 = ptCentr + ( vtExtr * ( dTall2 + 0.01))
frOriTool = Frame3d( ptCentrGrid3, vtExtr)
local bColl3 = EgtTestCylSurface( frOriTool, dDiam3/2, dTall3, 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)
-- verifico che i tre punti siano definiti
if not ptP1 or not ptP2 or not ptP3 then
return nil
end
-- creo il contorno
local nLoopId = EgtCurveCompoFromPoints( nAddGrpId, { ptP1, ptP2, ptP3, ptP1}, GDB_RT.GLOB)
if not nLoopId then
return nil
end
-- creo la superfice triangolare (quindi piana)
local nFaceId = EgtSurfTmByFlatContour( nAddGrpId, nLoopId, 0.01)
EgtErase( nLoopId)
if not nFaceId then
return nil
end
-- se normale negativa inverto
local vtN1 = EgtSurfTmFacetNormVersor( nFaceId, 0, GDB_ID.ROOT)
if vtN1:getZ() < -0.01 then
EgtInvertSurf( nFaceId)
end
return nFaceId
end
---------------------------------------------------------------------
local function AddMillCornerMachining( nPartId, nNewProc, nFacInd, tFacAdj, nAddGrpId,
dToolDiam, sMilling, dOffsAng,
dDiam1, dDiam2, dTall1,
dTall2, dDiam3, dTall3, bMakeLocSurf, vFace, vtN)
-- 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.Id)
-- creo copia del percorso principale e gli aggiungo la nuova faccia
nNewProcLoc = EgtCopyGlob( nNewProc.Id, 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.Id
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
else
local sErr = 'Error : Impossible insert clean corner from bottom'
return false, sErr
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() < BD.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()
-- calcolo angolo tilt di 45°
vtExtr = vtExtrExit + vtN
vtExtr:normalize()
local vtCheck = Vector3d(vtExtr)
-- se ho un offset angolare ruoto il percorso
if abs(dOffsAng) > 100 * GEO.EPS_SMALL then
vtCheck:rotate( vtN, dOffsAng)
end
-- controllo se c'è collisione con le facce della superfice
if CalcInterference( nNewProc.Id, vtCheck, tFacAdj[nIdEndPoint], 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], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
-- 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], ptApPoint, 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, 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], vtN, -dOffsAng, GDB_RT.GLOB)
end
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB)
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], vtN, -dOffsAng, GDB_RT.GLOB)
end
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
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 offset angolare valido e/o negativo creo il baffo precedente
if dOffsAng > -( 100 * GEO.EPS_SMALL) then
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint], ptApPoint, 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, 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], vtN, -dOffsAng, GDB_RT.GLOB)
end
-- prendo il nuovo punto finale
ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB)
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], vtN, -dOffsAng, GDB_RT.GLOB)
end
end
table.insert( pAuxId, nAuxId)
-- creo linea di ritorno
nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[nIdEndPoint], GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- ultima linea di distacco (5mm in direzione utensile)
local pEnd = tFacAdj[nIdEndPoint] + ( 5 * vtExtr)
nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint], pEnd, GDB_RT.GLOB)
table.insert( pAuxId, nAuxId)
end
-- trasformo in percorso
if #pAuxId > 0 then
AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true)
EgtSetInfo( AuxId, 'TASKID', nNewProc.TaskId)
EgtSetInfo( AuxId, 'CUTID', nNewProc.CutId)
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], vtN, dOffsAng, GDB_RT.GLOB)
end
-- inserisco la lavorazione
local sName = 'Clean_' .. ( EgtGetName( nNewProc.Id) or tostring( nNewProc.Id))
local nMchId = EgtAddMachining( sName, sMilling)
if not nMchId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
EgtSetInfo( nMchId, 'Part', nPartId)
-- 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) or ''
-- 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( vFace, Proc, dToolDiam, nAddGrpId, nMasterNewProc, vtN)
local sMilling, dMaxDepth
-- se ripresa angolo con fresa cono 60° con ripresa
-- recupero la lavorazione di fresatura
sMilling, dMaxDepth = ML.FindMilling( 'CleanCorner60')
if not sMilling then
local sErr = 'Error : CleanCorner 60 not found in library'
EgtOutLog( sErr)
return false, sErr
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 = { CutId = Proc.CutId, TaskId = Proc.TaskId}
if nMasterNewProc then
nNewProc.Id = nMasterNewProc
else
nNewProc.Id = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
end
local nFacCnt = EgtSurfTmFacetCount( nNewProc.Id)
local nFacInd, dDimMin, dDimMax, dDepth, nSurfInt
local bMakeLocSurf = true
-- 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
if abs( vtN:getZ()) > abs( vtN:getY()) then
ptLoc3 = Point3d( vFace[i].Cen:getX(), vFace[i].Cen:getY(), ptLoc1:getZ())
else
ptLoc3 = Point3d( vFace[i].Cen:getX(), ptLoc1:getY(), vFace[i].Cen:getZ())
end
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
if abs( vtN:getZ()) > abs( vtN:getY()) then
ptLoc2 = Point3d( vFace[j].Cen:getX(), vFace[j].Cen:getY(), ptLoc1:getZ())
else
ptLoc2 = Point3d( vFace[j].Cen:getX(), ptLoc1:getY(), vFace[j].Cen:getZ())
end
else
ptLoc2 = vFace[k].PPrev
end
-- ricavo i punti e l'angolo interno
local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( nNewProc.Id, 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 > -( 90 + 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 (dAng + 90) > 2 then
local dAngOffs = (dAng + 90) / 2
-- primo taglio
local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nAddGrpId,
dToolDiam, sMilling, -dAngOffs,
dMillDiam, dMillTotDiam, abs( dThickTool),
dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace, vtN)
if not bOk then return bOk, sErr end
-- secondo taglio
bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nAddGrpId,
dToolDiam, sMilling, dAngOffs,
dMillDiam, dMillTotDiam, abs( dThickTool),
dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace, vtN)
if not bOk then return bOk, sErr end
-- altrimenti ho un solo percorso
else
local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nAddGrpId,
dToolDiam, sMilling, 0,
dMillDiam, dMillTotDiam, abs( dThickTool),
dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace, vtN)
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.Id then
EgtErase( nNewProc.Id)
end
return true
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 GetFacesData( nNewProc, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, nPartId, vtNBottom)
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 = i - 1
local nPrecFac
nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2)
-- recupero centro e normale della faccia
local ptCen, vtN = EgtSurfTmFacetCenter( nNewProc, nFac, GDB_ID.ROOT)
-- recupero le dimensioni della faccia
local _, dLen, dWidth = BL.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)) * vtNBottom > 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
-- se rivolto verso Z
if abs( vtNBottom:getZ()) > abs( vtNBottom:getY()) then
if ptLocP1:getZ() < ptLocP2:getZ() then
vFace[i].PPrev = ptLocP1
else
vFace[i].PPrev = ptLocP2
end
else
if vtNBottom:getY() > 0 then
vFace[i].PPrev = EgtIf( ptLocP1:getY() < ptLocP2:getY(), ptLocP1, ptLocP2)
else
vFace[i].PPrev = EgtIf( ptLocP1:getY() > ptLocP2:getY(), ptLocP1, ptLocP2)
end
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 = BD.CUT_EXTRA
if vFace[i].Width + BD.CUT_EXTRA > dToolMaxDepth then
dDepth = dToolMaxDepth - vFace[i].Width
end
-- lunghezza baffo
local dElev = vFace[i].Width + dDepth
local dWhisk = ( 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
nType = nType + 1
end
if vFace[EgtIf( i < nNumFacet, i + 1, 1)].AngPrev < -0.1 then
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 ReorderFaces( nIdSurf, nNumFacet, vtNBottom)
-- 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)) * vtNBottom > 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)) * vtNBottom > 0 then
EgtSurfTmSwapFacets( nIdSurf, i, j - 1)
break
end
end
end
end
---------------------------------------------------------------------
local function RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFaceToDel, vtN)
-- 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, vtN)
return nNewProc, nNumFacet
end
---------------------------------------------------------------------
local function MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, bSinglePart, bPrevBhSideMill, bAllWithEndCap)
if not BD.MAXDIAM_POCK_CORNER then
BD.MAXDIAM_POCK_CORNER = 30
end
local nMGrpId = EgtGetCurrMachGroup()
local sWarn
-- recupero l'ingombro del grezzo di appartenenza
local b3Raw = EgtGetRawPartBBox( nRawId)
-- recupero l'ingombro della trave
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- strategia lama + eventuale sega a catena
if ( EgtGetInfo( Proc.Id, Q_SAW_PLUS_CHAIN, 'i') or 0) > 0 then
local bOk
local sErr
local bOnlySaw = EgtGetInfo( Proc.Id, Q_SAW_PLUS_CHAIN, 'i') == 1
bOk, sErr = SawPlusChain.Make ( bOnlySaw, Proc, nRawId)
return bOk, sErr
end
local bClosedOrthoFaces
local nFacInd, dFacElev, nFacInd2, dFacElev2
local nBottomFace
local sMchFindBackUp
-- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa
nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc, nPartId)
if not nFacInd or nFacInd < 0 then
if nFacInd == -1 then
bClosedOrthoFaces = nFacInd2
else
local sErr = 'Error : MakeMoreFaces could not find reference face'
EgtOutLog( sErr)
return false, sErr
end
end
-- se scanalatura chiusa lavoro la faccia di fondo
if Proc.Topology == 'Pocket' and ( Proc.IsParallel or Proc.AllRightAngles) and not bClosedOrthoFaces then
nFacInd = Topology.GetFacesWithGivenAdjacencyNumber( Proc, nil, 4)[1]
nFacInd2 = nil
dFacElev = Proc.Face[ nFacInd + 1].Elevation
end
-- se proviene da divisione in parti lungo X ed è un tunnel non è fattibile
if not bSinglePart and bClosedOrthoFaces then
local sErr = 'Error : long splitted tunnel not feasible'
EgtOutLog( sErr)
return false, sErr
end
-- verifico se sono presenti i parametri Q per la profondità smusso e
-- per eseguire in esclusiva solo lo smusso
local nChamfer, dDepthCham, sErrCham, bForceUseBlade = EvaluateQParam( Proc)
-- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer
-- genero errore e non faccio nulla
if nChamfer < 0 then
return false, sErrCham
end
-- eventuale forzatura sega a catena
local bForceChainsaw = ( EgtGetInfo( Proc.Id, Q_FORCE_CHAINSAW, 'i') or 0) > 0
-- TUNNEL: svuotatura o sega a catena
if bClosedOrthoFaces then
local bTryWithBlades = true
local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace
-- forzata sega a catena
if bForceChainsaw then
-- ottengo le dimensioni del tunnel
dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace = BL.GetTunnelDimension( Proc, nPartId)
-- lavoro fessura con svuotature (singola o doppia contrapposta)
else
local sMyMchFind = 'Pocket'
local nOk, sErr
nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho,
nLundIdFace, sErr = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, false, b3Solid, bClosedOrthoFaces)
if nOk < 0 then
return false, sErr
elseif nOk > 0 then
sWarn = sErr
bTryWithBlades = false
end
end
-- Se la svuotatura precedente non è stata fatta e chamfer non è mutuamente esclusivo provo con la sega-catena
if bTryWithBlades and nChamfer < 2 then
-- verifico se posso farlo con la sega-catena
local bMakeChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick, _, dSawWidth = VerifyChainSaw( Proc, dDimMin, dDimMax, dDepth)
if bMakeChainSaw then
-- se forzata sega a catena devo verificare se inserire lo smusso
if bForceChainsaw and nChamfer > 0 then
local nOk, sErr = MakeChamfer( Proc, false, nAddGrpId, vtOrtho, b3Solid, nLundIdFace, dDepthCham)
if nOk < 0 then return -1, sErr end
end
-- Ricalcolo l'affondamento tenendo conto di eventuale inclinazione
local dSlDepth
local frSlDh = Frame3d( Proc.Box:getCenter(), vtOrtho)
for i = 1, Proc.Fct do
local b3Fac = EgtSurfTmGetFacetBBoxRef( Proc.Id, i - 1, GDB_BB.STANDARD, frSlDh)
if b3Fac and ( not dSlDepth or b3Fac:getDimZ() < dSlDepth) then
dSlDepth = b3Fac:getDimZ()
end
end
if dSlDepth then dDepth = dSlDepth end
-- Verifico se necessarie più passate
local nStep = ceil( ( dDimMin - 100 * GEO.EPS_SMALL) / dSawThick)
local dStep = 0
if nStep > 1 then
dStep = ( dDimMin - dSawThick) / ( nStep - 1)
end
local bSplit = false
local sFaceUse, sFaceUseOtherSide
-- imposto il lato di lavorazione, da sopra oppure di fronte
-- se è di fronte, non è una Fast e il tagliente non arriva splitto la lavorazione
-- Questa feature non è applicata su facce di testa e quindi non controllo l'entrata in X
if abs(vtOrtho:getZ()) >= 0.707 then
sFaceUse = MCH_MILL_FU.PARAL_DOWN
else
sFaceUse = MCH_MILL_FU.PARAL_BACK
-- per escludere la Fast controllo C_SIMM
if BD.C_SIMM and dMaxMat < dDepth then
bSplit = true
sFaceUseOtherSide = MCH_MILL_FU.PARAL_FRONT
dDepth = dDepth / 2 + BD.CUT_EXTRA
end
end
-- se necessario riduco la profondità di lavoro per considerare l'ingombro della testa
local dChainSawTHLength = EgtIf( EgtTdbGetCurrToolThLength() > 10 * GEO.EPS_SMALL, EgtTdbGetCurrToolThLength(), 88)
local dChainSawExtraLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) - dChainSawTHLength - dMaxMat
local dMaxMatReduction = 0
local dToolEntryAngle, _, _, dTanToolEntryAngle = GetToolEntryAngle( Proc, vtOrtho)
if dToolEntryAngle > 10 * GEO.EPS_ANG_SMALL and dTanToolEntryAngle then
dMaxMatReduction = max( ( ( 2 * BD.C_SIMM_ENC - dSawWidth) / ( 2 * dTanToolEntryAngle) - dChainSawExtraLength) - 5, 0)
end
local dWorkDepth = dMaxMat - dMaxMatReduction
-- cerco di estendere il taglio considerando la parte arrotondata della lama
if dMaxMat - dMaxMatReduction > dDepth + dSawCornerRad + 1 then
dWorkDepth = dDepth + dSawCornerRad + 1
-- se massimo affondamento utensile inferiore alla profondità da lavorare, setto la profondità di lavoro e emetto warning
elseif dMaxMat - dMaxMatReduction < dDepth then
sWarn = 'Warning : elevation bigger than max tool depth'
EgtOutLog( sWarn)
end
-- lavoro da un lato
local bOk, sErr = MakeTunnelByChainSaw( Proc, sSawing, nLundIdFace, vtOrtho, dWorkDepth, dMaxMat, nStep, dStep, sFaceUse, false)
if not bOk then return false, sErr end
-- se è da lavorare anche dall'altro lato
if bSplit then
bOk, sErr = MakeTunnelByChainSaw( Proc, sSawing, nLundIdFace, vtOrtho, dWorkDepth, dMaxMat, nStep, dStep, sFaceUseOtherSide, true)
if not bOk then return false, sErr end
end
end
end
-- NO TUNNEL: tutti gli altri casi
else
-- dati della faccia
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
-- larghezza della faccia
local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
if Proc.Box:getDimX() > Proc.Box:getDimY() then
if dH > dV then dH, dV = dV, dH end
else
if dH < dV then dH, dV = dV, dH end
end
-- se due o più facce (recupero la larghezza della faccia perpendicolarmente alle altre)
if Proc.Fct >= 2 then
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( nFacInd == 0, 1, 0), GDB_ID.ROOT)
local vtX = vtN2 ^ vtN
if not vtX:isSmall() then
local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2)
local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef)
if b3Ref then
dH = b3Ref:getDimX()
dV = b3Ref:getDimY()
end
end
end
-- verifico se U
local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc))
-- verifico se due facce o L con una o due facce di terminazione
local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2)
-- se parametro Q03=2 forzo la fresatura di lato; con Q03=3 forzo solo se la faccia di lavoro non è rivolta verso l'alto +/-10°; per rabbet che guardano in giù sempre fresatura di lato
local bIsRabbetAlongXTowardsBottom = ( Proc.TopologyLongName == 'Rabbet-Through-RightAngles-Parallel-2' and ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) and Proc.AffectedFaces.Bottom and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right)
local bForceSideMill = ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) and ( bIsRabbetAlongXTowardsBottom or ( ( EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') == 2 or ( EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') == 3 and vtN:getZ() < 0.985)) and ( ( Proc.Fct == 4 and ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back)) or Proc.Fct == 3 or Proc.Fct == 2)))
-- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia
local bMakeBySideMill, bHead, bHeadDir, sMilling, dMaxMat, dToolDiam = VerifyBHSideMill( Proc, bIsU, bIsL, bSinglePart, bPrevBhSideMill, b3Raw)
if bPrevBhSideMill == nil then
bPrevBhSideMill = bMakeBySideMill
end
-- SIDEMILL (tipo BLOCKHAUS)
if bMakeBySideMill then
-- se smusso non è esclusivo
if nChamfer < 2 then
-- verifico che la faccia non sia diretta come X, altrimenti cerco di cambiarla
if abs( vtN:getX()) > 0.866 and nFacInd2 then
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT)
if vtN2 and abs( vtN2:getX()) < 0.866 then
nFacInd, nFacInd2 = nFacInd2, nFacInd
dFacElev, dFacElev2 = dFacElev2, dFacElev
vtN, vtN2 = vtN2, vtN
end
end
-- informazioni utensile
local Tool = BL.GetToolFromMachining( sMilling)
-- se lavorazione da sotto e lunga, va divisa in due metà
local bDouble = not Tool.IsOnAggregate and ( vtN:getZ() < -0.5 and dH > ( BD.MAX_LEN_BH_FROM_BOTTOM or 200) and not BD.TURN)
-- inserisco la lavorazione di fresatura
local sName = 'BHMill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
sName = EgtGetName( nMchFId)
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}})
-- imposto uso del lato faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bHeadDir, MCH_MILL_FU.PARAL_LEFT, MCH_MILL_FU.PARAL_RIGHT))
-- calcolo step effettivo ed elevazione
local dVcalc = dV - dMaxMat
if abs( dVcalc) < 0.1 then dVcalc = 0 end
local dStep = min( EgtMdbGetCurrMachiningParam( MCH_MP.STEP), dMaxMat)
local nStep = ceil( dVcalc / dStep)
if nStep > 0 then
dStep = dVcalc / nStep + 0.1
else
dStep = 0
end
-- lo step finale non deve mai superare lo spessore utensile
dStep = min( dStep, dMaxMat)
EgtSetMachiningParam( MCH_MP.STEP, dStep)
-- imposto elevazione e dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dVcalc + dStep, 2))
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- attacchi e uscite
if vtN:getZ() > -0.5 or BD.TURN then
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, dFacElev + BD.CUT_SIC)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI)
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( nFacInd == 0, 1, 0), GDB_ID.ROOT)
if vtN2 then
local AddLen = sqrt( dV^2 * ( ( 1 / abs( vtN2:getX())^2) - 1)) + BD.CUT_SIC
EgtSetMachiningParam( MCH_MP.STARTADDLEN, AddLen)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, AddLen)
end
else
EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0)
EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + BD.CUT_SIC)
EgtSetMachiningParam( MCH_MP.LIPERP, 0)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.PERP_TG)
EgtSetMachiningParam( MCH_MP.LOTANG, -( dToolDiam / 2 + b3Raw:getDimY() + BD.CUT_SIC))
EgtSetMachiningParam( MCH_MP.LOPERP, EgtIf( vtN:getZ() > -0.5, dFacElev + BD.COLL_SIC, BD.COLL_SIC))
if bDouble then
EgtSetMachiningParam( MCH_MP.ENDADDLEN, - dH / 2)
EgtSetMachiningParam( MCH_MP.LOTANG, -( dToolDiam / 2 + dH / 2 + BD.CUT_SIC))
end
end
-- tipo passate multiple
local nStepType = MCH_MILL_ST.ONEWAY
EgtSetMachiningParam( MCH_MP.STEPTYPE, nStepType)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.TURN then
nSCC = EgtIf( ( vtN:getY() > 0.5 or ( bHeadDir and vtN:getZ() > 0.5 ) or ( not bHeadDir and vtN:getZ() < -0.5)), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
else
if vtN:getY() > 0.707 then
nSCC = MCH_SCC.ADIR_YP
elseif vtN:getY() < -0.707 then
nSCC = MCH_SCC.ADIR_YM
elseif vtN:getZ() > 0.707 then
nSCC = MCH_SCC.ADIR_ZP
elseif vtN:getZ() < -0.707 then
nSCC = MCH_SCC.ADIR_ZM
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- impostazioni per fresa a disco su aggregato
if Tool.IsOnAggregate then
if AreSameVectorApprox( vtN, -Z_AX()) then
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_RIGHT)
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
if bHeadDir then
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT)
EgtSetMachiningParam( MCH_MP.TOOLINVERT, true)
else
EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT)
EgtSetMachiningParam( MCH_MP.TOOLINVERT, false)
end
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_ZP)
end
end
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- se divisa in due metà
if bDouble then
local nMchFNId = EgtCopyMachining( sName .. '_2', sName)
if not nMchFNId then
local sErr = 'Error copying machining ' .. sName
EgtOutLog( sErr)
return false, sErr
end
-- inverto direzione e lato di lavoro e direzione ausiliaria
local bInvert = EgtGetMachiningParam( MCH_MP.INVERT)
EgtSetMachiningParam( MCH_MP.INVERT, not bInvert)
local nWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE)
EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( nWorkSide == MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT))
EgtSetMachiningParam( MCH_MP.SCC, EgtIf( nSCC == MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP))
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFNId, false)
return false, sErr
end
end
end
-- TASCA GENERICA: si cerca il modo migliore di lavorare in base alla forma
else
local bSpecial3faces = false
-- verifico se lavorando la faccia principale rimane esclusa molta sezione trasversale complessiva della feature (da box)
local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
local bBoxF = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfFac)
if dH * dV < 0.9 * ( bBoxF:getDimX() * bBoxF:getDimY()) and nFacInd2 and dFacElev2 < 1.5 * dFacElev and not ( Proc.Topology == 'Groove' and Proc.Fct == 2) then
bSpecial3faces = true
end
local bPocketFloatingAggregate = false
-- se abilitata lavorazione con aggregato flottante
local sMillingFloatingAggregate
if Proc.Topology == 'Groove' and Proc.Fct == 4 and EgtGetInfo( Proc.Id, Q_FLOATING_AGGREGATE, 'i') == 1 then
-- verifico se è possibile lavorare con utensile su aggregato flottante
sMillingFloatingAggregate = ML.FindMilling( 'FloatingAggregate', dFacElev, nil, min( dH , dV))
if sMillingFloatingAggregate then
if EgtMdbSetCurrMachining( sMillingFloatingAggregate) then
local sTuuidPk = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then
local dToolDiameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
-- la larghezza della tasca non può superare il doppio del diametro, la lavorazione deve essere fatta con una passata di contornatura
if min( dH , dV) < dToolDiameter * 1.9 then
bPocketFloatingAggregate = true
end
end
end
end
end
-- FRESATURA SPECIALE CON AGGREGATO FLOTTANTE
if bPocketFloatingAggregate then
-- inserisco la lavorazione di svuotatura
local sName = 'Float_Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMillingFloatingAggregate)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMillingFloatingAggregate
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
local Geometry = {}
for Index = 1, Proc.Fct do
if nFacInd ~= Index-1 then
table.insert( Geometry, { Proc.Id, Index-1})
end
end
EgtSetMachiningGeometry( Geometry)
-- imposto uso faccia
local nFaceUse = BL.GetNearestParalOpposite( vtN)
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- piccolo offset radiale per essere sicuri di lavorare anche con tasca larga come diametro fresa
EgtSetMachiningParam( MCH_MP.OFFSR, -0.01)
-- imposto posizione braccio porta testa
local nSCC = MCH_SCC.NONE
if not BD.C_SIMM then
if AreSameVectorApprox( vtN, Z_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif abs( vtN:getX()) < 0.1 then
nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
elseif vtN:getY() < GEO.EPS_SMALL then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
end
EgtSetMachiningParam( MCH_MP.SCC, nSCC)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- CASO SPECIALE 3 FACCE (se rimane esclusa molta sezione trasversale complessiva della feature, solo per feature 20)
elseif bSpecial3faces and Proc.Prc == 20 then
-- se smusso non è esclusivo
if nChamfer < 2 then
-- entrambe le facce non devono essere orientate verso il basso
local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT)
-- se orientata verso il basso, verifico l'alternativa
if vtN:getZ() < BD.NZ_MINA and vtN2:getZ() < BD.NZ_MINA then
local sErr = 'Error : special LapJoint from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd2, GDB_ID.ROOT)
-- eventuali tagli preliminari
do
local bOk, sErr = MakePreCuts( Proc, nPhase, nRawId, nPartId, dOvmHead, b3Raw, nChamfer)
if not bOk then return false, sErr end
end
-- Recupero la lavorazione di fresa
local sMilling = ML.FindMilling( 'LongSmallCut')
if not sMilling then
local sErr = 'Error : LongSmallCut not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- Recupero la lavorazione di svuotatura
local sMchFind = 'Pocket'
-- se forzato uso truciolatore
if EgtGetInfo( Proc.Id, Q_USE_ROUGH_TOOL, 'i') == 1 then
sMchFind = 'OpenPocket'
end
local dDiam = min( dH, dV)
local dDiam2 = min( dH2, dV2)
local dCollSic = 2 * BD.COLL_SIC
local dCollSic2 = 2 * BD.COLL_SIC
if abs( vtN:getX()) > 0.7 or abs( vtN:getY()) > 0.7 or abs( vtN:getZ()) > 0.7 then dCollSic = 0 end
if abs( vtN2:getX()) > 0.7 or abs( vtN2:getY()) > 0.7 or abs( vtN2:getZ()) > 0.7 then dCollSic2 = 0 end
local sPocketing = ML.FindPocketing( sMchFind, dDiam2, dFacElev2 + dCollSic2)
-- se non trova una svuotatura adatta provo ad assegnarla all'altra faccia
if not sPocketing then
dDiam, dDiam2 = dDiam2, dDiam
dCollSic, dCollSic2 = dCollSic2, dCollSic
nFacInd, nFacInd2 = nFacInd2, nFacInd
dH, dH2 = dH2, dH
dV, dV2 = dV2, dV
dFacElev, dFacElev2 = dFacElev2, dFacElev
rfFac, rfFac2 = rfFac2, rfFac
vtN, vtN2 = vtN2, vtN
sPocketing = ML.FindPocketing( sMchFind, dDiam2, dFacElev2 + dCollSic2)
if not sPocketing then
dDiam, dDiam2 = dDiam2, dDiam
dCollSic, dCollSic2 = dCollSic2, dCollSic
nFacInd, nFacInd2 = nFacInd2, nFacInd
dH, dH2 = dH2, dH
dV, dV2 = dV2, dV
dFacElev, dFacElev2 = dFacElev2, dFacElev
rfFac, rfFac2 = rfFac2, rfFac
vtN, vtN2 = vtN2, vtN
sPocketing = ML.FindPocketing( sMchFind, dDiam2, nil, nil, nil, nil, nil, nil, 'Longest')
if not sPocketing then
local sErr = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
end
-- provo con contornatura
local dDiamTool = 20
if bIsL then
local bOk, sErr
bOk, sWarn, dDiamTool = MakeByMill( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dFacElev, dCollSic, true, sMilling, nFacInd2, dFacElev2)
if not bOk then return bOk, sWarn end
else
local sErr = 'Error : Impossible mill special LapJoint'
EgtOutLog( sErr)
return false, sErr
end
-- inserisco la lavorazione di svuotatura
local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sPocketing)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacInd2}})
-- imposto uso faccia
EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT)
-- imposto posizione braccio porta testa
if vtN:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- se tasca aperta, imposto opportuno attacco
if sMchFind == 'OpenPocket' then
EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN)
end
-- imposto elevazione
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dFacElev2, 1))
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
-- provo ad allargare leggermente la tasca
EgtSetMachiningParam( MCH_MP.OFFSR, -0.1)
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
end
-- se abilitato dal parametro Q inserisco foro sullo spigolo
if EgtGetInfo( Proc.Id, Q_BORE_ON_CORNER, 'i') == 1 then
local bOk
bOk, sWarn = MakeDrillOnCorner( Proc, nPhase, nRawId, nPartId, b3Raw, 0, nAddGrpId, dDiamTool, true)
if not bOk then return false, sWarn end
-- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura
elseif EgtGetInfo( Proc.Id, Q_BORE_ON_CORNER, 'i') == 2 then
local bOk
bOk, sWarn = MakeSharpCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, 0, nAddGrpId, dDiamTool)
if not bOk then return false, sWarn end
end
end
-- SVUOTATURA O FRESATURA: si valuta se si può fare svuotatura o se provare altro
else
local bUseOtherFace
local bLapJointAngTrasm = false
-- se è presente il rinvio angolare ed è una tasca perfettamente verticale, da sotto
if BD.ANG_TRASM and Proc.Fct >= 4 and AreOppositeVectorApprox( vtN, Z_AX()) then
bLapJointAngTrasm = true
-- se orientata verso il basso e non c'è testa da sotto, verifico l'alternativa
elseif vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD and nFacInd2 and not Proc.OkFromBottom then
ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT)
nFacInd, nFacInd2 = nFacInd2, nFacInd
dFacElev, dFacElev2 = dFacElev2, dFacElev
bUseOtherFace = true
end
-- verifico non sia orientata verso il basso o ci sia una testa dal basso o la lavorazione sia dal lato.
local bFaceDown = ( vtN:getZ() < BD.NZ_MINA)
if bFaceDown and not BD.DOWN_HEAD and not BD.TURN and not bForceSideMill and not bLapJointAngTrasm and not Proc.OkFromBottom then
local sErr = 'Error : LapJoint from bottom impossible'
EgtOutLog( sErr)
return false, sErr
end
rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
-- se forma a L e la componente in X è maggiore di 60° e non in testa allora verifico se posso utilizzare la faccia secondaria
if bIsL and abs( vtN:getX()) > 0.866 and
( Proc.Box:getMax():getX() < b3Solid:getMax():getX() - 10 or vtN:getX() < 0) and
( not Proc.Tail or vtN:getX() > 0) then
-- se non ho scambiato la faccia
if not bUseOtherFace then
if nFacInd2 then
nFacInd, nFacInd2 = nFacInd2, nFacInd
dFacElev, dFacElev2 = dFacElev2, dFacElev
ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
-- altrimenti cerco la faccia secondaria per adiacenza alla principale
else
-- Cerco una faccia adiacente alla principale sul lato lungo
local nFacAdj, sErr = GetFaceAdj( Proc, nFacInd, dH, dV)
if nFacAdj < 0 then
EgtOutLog( sErr)
return false, sErr
end
nFacInd = nFacAdj
dFacElev = BL.GetFaceElevation( Proc, nFacInd, b3Solid)
ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT)
rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
end
-- altrimenti se ho già cambiato faccia do errore per impossibilità di lavorazione
else
local sErr = 'Error : impossible to machine by side angle too big that cause collision'
EgtOutLog( sErr)
return false, sErr
end
end
-- eventuali tagli preliminari
do
local bOk, sErr = MakePreCuts( Proc, nPhase, nRawId, nPartId, dOvmHead, b3Raw, nChamfer)
if not bOk then return false, sErr end
end
-- imposto altezza aggiuntiva di elevazione
local dCollSic = BL.CalcCollisionSafety( vtN)
-- abilitazione lavorazione da sotto
local bMillUp = ( BD.DOWN_HEAD and vtN:getZ() > -0.259)
local bMillDown = ( BD.DOWN_HEAD and vtN:getZ() < 0.342)
-- settaggio voluto da Alessandro/Fabio (per fare angoli con fresa piccola)
local sMchFind = 'Pocket'
local dDiam = min( dH, dV)
local bTailOnSide = ( Proc.Box:getMin():getX() - b3Solid:getMin():getX() < 0.1 and not Proc.Tail and not bAllWithEndCap)
if ( Proc.Fct == 1) or (( Proc.Fct == 2 or Proc.Fct == 3) and bIsL) or ((( Proc.Fct == 3 and bIsU) or ( Proc.Fct == 4 and not bTailOnSide)) and bSinglePart) then
sMchFind = 'OpenPocket'
if bIsU then
dDiam = GetUShapeWidth( Proc, nFacInd) or dDiam
elseif Proc.Fct == 4 then
-- se non angoli fittizi, per rifinire gli angoli premio utensile diam 25 o da BD
if not bAllWithEndCap then
dDiam = min( EgtIf( bIsL, 2, 1) * dDiam + 10 * GEO.EPS_SMALL, BD.MAXDIAM_POCK_CORNER)
end
elseif Proc.Fct == 3 and bIsL then
-- per rifinire gli angoli premio utensile diam 25 o da BD
dDiam = min( 2 * dDiam + 10 * GEO.EPS_SMALL, BD.MAXDIAM_POCK_CORNER)
else
dDiam = 3 * dDiam
end
end
sMchFindBackUp = sMchFind
local nUseRoughTool = EgtIf( bSinglePart, 0, 1)
local nUseRT
-- 04/08/2020 Se settato parametro uso truciolatore (parametro Q), non si devono prendere altre frese, si da errore (Fabio)
-- Questa opzione si scontra facilmente con altre interpretazioni dello stasso parametro Q (per tornare indietro bNewCheck = false)
local bNewCheck = true
-- se processo 20 e non sto usando il truciolatore
if bNewCheck and Proc.Prc == 20 and nUseRoughTool == 0 then
-- verifico se forzato uso truciolatore
nUseRT = EgtGetInfo( Proc.Id, Q_USE_ROUGH_TOOL, 'i')
if nUseRT and nUseRT ~= 0 then
sMchFind = 'OpenPocket'
nUseRoughTool = 1
end
end
-- se è una tasca aperta e forzo lavorazione laterale, cerco il truciolatore (di norma il truciolatore è solo OpenPocket)
if bNewCheck and Proc.Prc == 30 and nUseRoughTool == 0 and Proc.Fct < 5 and not bClosedOrthoFaces then
-- verifico se forzato uso truciolatore
nUseRT = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i')
if nUseRT and nUseRT ~= 0 then
sMchFind = 'OpenPocket'
nUseRoughTool = 1
end
end
-- se processo 20 e non sto usando il truciolatore
if Proc.Prc == 20 and nUseRoughTool == 0 then
if nUseRT and nUseRT ~= 0 then
sMchFind = 'OpenPocket'
nUseRoughTool = 1
end
end
-- se presente curva da lavorare con lato aperto
if Proc.LoopIdFacInd and ( EgtGetInfo( Proc.LoopIdFacInd, 'OPEN', 'i') or -1) > -1 then
sMchFind = 'OpenPocket'
nUseRoughTool = 0
end
-- se abilitato rinvio da sotto
if bLapJointAngTrasm then
if not EgtEndsWith( sMchFind, '_AT') then
sMchFind = sMchFind .. '_AT'
end
if not EgtEndsWith( sMchFindBackUp, '_AT') then
sMchFindBackUp = sMchFindBackUp .. '_AT'
end
end
-- se da sotto, imposto massima lunghezza secondo la direzione
local dMaxTotLen
if bMillDown and BD.GetBottomToolMaxTotLen then
dMaxTotLen = BD.GetBottomToolMaxTotLen( vtN)
end
local dUserMaxElev = EgtGetInfo( Proc.Id, Q_MAX_ELEVATION, 'd')
local dCustomMaxElev
-- se esistono tagli troncanti in testa o in coda, si calcola il MaxElev da applicare
if not dUserMaxElev then
local nTailCutId = EgtGetInfo( nPartId, 'TAILCUTFEATUREID', 'i')
local nHeadCutId = EgtGetInfo( nPartId, 'HEADCUTFEATUREID', 'i')
if nHeadCutId or nTailCutId then
local nSurfPartId = EgtCopyGlob( EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, 'Box'), nAddGrpId)
if nHeadCutId then
local ptCCutSurf, vtNCutSurf = EgtSurfTmFacetCenter( nHeadCutId, 0, GDB_ID.ROOT)
EgtCutSurfTmPlane( nSurfPartId, ptCCutSurf, vtNCutSurf, false, GDB_RT.GLOB)
local nSurfPartIdOld = nSurfPartId
nSurfPartId = EgtSurfTmBySewing( nAddGrpId, { nSurfPartId, nHeadCutId}, false)
EgtErase( nSurfPartIdOld)
end
-- in coda si usa il troncante solo se la feature è settata da lavorare dopo separazione (Tail), altrimenti si rischia che venga fatta prima del taglio
if nTailCutId and Proc.Tail then
local ptCCutSurf, vtNCutSurf = EgtSurfTmFacetCenter( nTailCutId, 0, GDB_ID.ROOT)
EgtCutSurfTmPlane( nSurfPartId, ptCCutSurf, vtNCutSurf, false, GDB_RT.GLOB)
local nSurfPartIdOld = nSurfPartId
nSurfPartId = EgtSurfTmBySewing( nAddGrpId, { nSurfPartId, nTailCutId}, false)
EgtErase( nSurfPartIdOld)
end
dCustomMaxElev = EgtSurfTmFacetElevationInClosedSurfTm( Proc.Id, nFacInd, nSurfPartId, true)
if dCustomMaxElev then
dCustomMaxElev = dCustomMaxElev + dCollSic
end
EgtErase( nSurfPartId)
end
end
-- ricerca lavorazione di svuotatura
local sPocketing
local _, sMyPocketing, dMyTMaxDepth, dMyTDiam = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind, bMillUp, bMillDown)
if not sMyPocketing and bMillUp then
_, sMyPocketing, dMyTMaxDepth, dMyTDiam = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind)
bMillDown = false
end
-- se è presente un'elevazione custom dCustomMaxElev si lavora sempre la faccia standard
if sMyPocketing then
if dUserMaxElev then
dCustomMaxElev = dUserMaxElev
elseif dCustomMaxElev and ( dMyTMaxDepth < dCustomMaxElev + dCollSic - 10 * GEO.EPS_SMALL) then
dCustomMaxElev = nil
end
if ( dMyTMaxDepth > dFacElev + dCollSic - 10 * GEO.EPS_SMALL or ( dMyTMaxDepth > 0.8 * dFacElev + dCollSic and not bIsU) or
( bIsL and nUseRoughTool == 0) or
( bIsL and Proc.Prc == 20) or
( bIsL and not bSinglePart) or
( Proc.Prc == 25 and not bIsU and not bIsL)) or
( dCustomMaxElev and dCustomMaxElev > 10 * GEO.EPS_SMALL) then
sPocketing = sMyPocketing
end
end
if bMillDown then
sMchFind = sMchFind ..'_H2'
end
-- Verifico se lavorazione "Lamello":
local bSpecialMillOnSide, sMillingOnSide, dThickMillOnSide, dToolDiamOnSide, dMaxDepthOnSide = VerifySideMillAsSaw( Proc, nAddGrpId, vtN, dDiam, dFacElev)
if bSpecialMillOnSide then
sPocketing = nil
end
-- se feature 16 e forzata lama e forma ad U, annulla la svuotatura
if Proc.Prc == 16 and bForceUseBlade and Proc.Fct == 3 and bIsU then
sPocketing = nil
end
-- se richiesta fresatura di lato
if bForceSideMill then
sPocketing = nil
end
-- se forzata sega a catena
if bForceChainsaw then
sPocketing = nil
end
-- leggo parametro Q
local nQAntisplintResult = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0
-- se lavorazione fresa come lama disabilito eventuale antischeggia
if bSpecialMillOnSide then nQAntisplintResult = 0 end
-- NO SVUOTATURA (si deve provare altro)
if not sPocketing then
-- se forma a L provo con contornatura
if bIsL and not bSpecialMillOnSide and not bForceSideMill then
-- se smusso non è esclusivo
if nChamfer < 2 then
return MakeByMill( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dFacElev, dCollSic)
end
-- altrimenti, in base alla forma, provo con svuotature di fianco o con la sega a catena o lama
else
local bTryWithBlades = true
local nOk, bOk, sStat, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces, nSurfInt
if bSpecialMillOnSide then
-- eseguo
bOk, sWarn = MakeByMillAsSaw( Proc, nPhase, nRawId, nPartId, nFacInd,
rfFac, dH, dV, dFacElev,
nBottomFace, nAddGrpId, b3Solid, dMaxDepthOnSide, sMillingOnSide,
dToolDiamOnSide, dThickMillOnSide, bAllWithEndCap)
if bOk then
return true, sWarn
end
end
-- se feature 16 o 17 e se forzata lama provo prima con questa e poi con la fresa
if ( Proc.Prc == 16 or Proc.Prc == 17) and bForceUseBlade then
-- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame
if bTryWithBlades and nChamfer < 2 then
-- anche su macchine con testa da sotto, la sega a catena è solo da sopra
if vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and nFacInd2 then
ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT)
nFacInd, nFacInd2 = nFacInd2, nFacInd
dFacElev, dFacElev2 = dFacElev2, dFacElev
bUseOtherFace = true
rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
end
-- se forma a U (recupero la larghezza della faccia perpendicolarmente alle altre)
if Proc.Fct == 3 and bIsU then
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( nFacInd == 0, 1, 0), GDB_ID.ROOT)
local vtX = vtN2 ^ vtN
if not vtX:isSmall() then
local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2)
local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef)
if b3Ref then
dH = b3Ref:getDimX()
dV = b3Ref:getDimY()
end
end
end
-- eseguo
bOk, sWarn, sStat = MakeByChainOrSaw( Proc, nPhase, nRawId, nPartId, nFacInd,
rfFac, dH, dV, dFacElev, bForceUseBlade,
dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace,
bOrthoFaces, nBottomFace, nChamfer, nAddGrpId, b3Solid,
dDepthCham, nSurfInt)
if not bOk then
-- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e
-- se non è possibile allora provo in seguito con lama o segacatena
-- o passare subito dalla lavorazione con lama/sega catena
if Proc.Fct == 3 and bIsU then
-- lavoro con svuotature (singola o doppia contrapposta)
local sMyMchFind = 'Pocket'
nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, _, _, _, _, _, _, _,
bOrthoFaces = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, true, b3Solid, nil, bMillDown)
-- se lavorazione non idonee ( asse della feature troppo inclinato e impossibile lavorare completamente da due parti)
if nOk == -2 then
if not sMchFind then
sMchFind = sMchFindBackUp
end
sPocketing = ML.FindPocketing( sMchFind, dDiam, nil, nil, not bMillDown, bMillDown)
if not sPocketing then
local sErr = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr)
return false, sErr
end
elseif nOk < 0 then
return false, sErr
elseif nOk == 0 then
if sStat == 'MNF' then
sPocketing = ML.FindPocketing( sMchFind, dDiam, nil, nil, not bMillDown, bMillDown)
if not sPocketing then
local sErr = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr)
return false, sErr
end
else
return bOk, sWarn
end
else
bOk = true
return bOk, sErr
end
else
sPocketing = ML.FindPocketing( sMchFind, dDiam, nil, nil, not bMillDown, bMillDown)
if not sPocketing then
local sErr = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr)
return false, sErr
end
end
else
return bOk, sWarn
end
else
-- se devo inserire il chamfer
if ( ( Proc.Fct == 3 and bIsU) or (Proc.Fct == 2 and bIsL)) and nChamfer > 0 then
-- ottengo le dimensioni dello pseudotunnel
local _, _, _, vtOrtho, _, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return false, sErr end
end
bOk = true
return bOk, sWarn
end
else
-- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo
-- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa
-- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z
-- 2021.07.16 Per poter eseguire antischeggia di lama su feature che non sono passanti da faccia a faccia
-- ma che sono su un angolo (coinvolgono 2 facce contigue) è stato modificato il confronto in:
-- esegue antischeggia di lama se forma U o L con feature passante in Y o Z, oppure se feature a furma U e con 3 facce oppore a forma a L e con 2 facce
-- non fa mai antischeggia di lama se la faccia è rivolta verso il basso, a meno che ci sia una testa sotto
local bMadeASbyBld = false
local bPassThrou = ( Proc.Box:getDimY() > b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > b3Raw:getDimZ() - 1)
local bPassEdge = ((( bIsU and Proc.Fct == 3) or ( bIsL and Proc.Fct == 2)) and bSinglePart and Proc.Box:getDimX() < 0.9 * b3Raw:getDimX())
local nFacIndOri = BL.GetFaceWithMostAdj( Proc, nPartId)
local vtNOri = EgtSurfTmFacetNormVersor( Proc.Id, nFacIndOri, GDB_ID.ROOT)
if nChamfer < 2 and nQAntisplintResult == 1 and (( bIsU or bIsL) and ( bPassThrou or bPassEdge)) and ( vtNOri:getZ() > -0.087 or BD.DOWN_HEAD or BD.TURN) then
local bOk
local bSawDown = ( bMillDown and not bMillUp)
bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, b3Solid, bIsU, vtNOri, nFacIndOri, sWarn, bSawDown, true)
if not bOk then return false, sWarn end
end
-- in base al flag interno e al numero di facce e se ha forma ad U
-- oppure se richiesta lavorazione di lato:
-- provo prima la svuotatura sul fianco e
-- se non è possibile allora provo in seguito con lama o segacatena
-- o passare subito dalla lavorazione con lama/sega catena
if ( bTrySidePocketAtFirst and Proc.Fct == 3 and bIsU) or bForceSideMill then
-- lavoro con svuotature (singola o doppia contrapposta)
local sMyMchFind = EgtIf( bForceSideMill, 'OpenPocket', 'Pocket')
local dDiamTool = 100
local nPathInt, nSurfInt, bOneShot, nFirstMachId
local bIs3Faces = true
local bOrthoFacesMaster = nil
local bSetOpenBorders = nil
-- trovo la faccia con normale più inclinata verso Y
local nFacApproxY, ptCFacApproxY, vtNFacApproxY = BL.FindFaceBestOrientedAsAxis( Proc, Y_AX())
-- se Q03 = 2 e
-- 3 facce a L, oppure
-- 3 facce non a L ma con una faccia favorevole a Y, oppure
-- 4 facce
-- lancio la MakePocket ( lavorazione solo da un lato, fondo della tasca la faccia più favorevole a Y)
if bForceSideMill and (( Proc.Fct == 3 and bIsL) or ( ( Proc.Fct == 3 or Proc.Fct == 2) and abs( vtNFacApproxY:getY()) >= 0.707 ) or ( Proc.Fct == 4 and Proc.Topology == 'Groove')) then
nFacInd, vtN, ptC = nFacApproxY, vtNFacApproxY, ptCFacApproxY
local tvtNx = {}
tvtNx[2] = vtN
local ptPs = ptC
dFacElev = BL.GetFaceElevation( Proc, nFacInd, b3Solid)
dCollSic = BL.CalcCollisionSafety( tvtNx[2])
local dMachDepth = dFacElev + dCollSic
local frFacRec, dFacDim1, dFacDim2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
-- limito il diametro utensile massimo a 201 per queste lavorazioni
dToolTargetDiam = min( BD.MAXDIAM_POCK_CORNER, 201)
-- se è 4 facce devo capire quale è il lato libero e settare dH e dV di conseguenza
if Proc.Fct == 4 then
local vAdj = {}
local vtN2
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 vAdj[i] == Proc.Fct - 1 and i ~= nFacInd + 1 then
dV = BL.GetFaceElevation( Proc, i - 1, b3Solid)
vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT)
end
end
local vtRes = vtN2 ^ vtN
if AreSameOrOppositeVectorApprox( frFacRec:getVersX(), vtRes) then
dH = dFacDim1
else
dH = dFacDim2
end
-- se la tasca ha dimensioni adeguate cerco di usare una fresa con raggio fino a metà altezza
dToolMaxDiam = EgtIf( dH >= dToolTargetDiam and dV > 0.5 * dToolTargetDiam, dToolTargetDiam, min( dH, dV, dToolTargetDiam))
-- per le L a 3 facce, avendo due lati aperti per l'attacco, si considera un diametro utensile pari al doppio della dimensione minima; il "- 1" è un accorgimento per impedire bug derivanti da dimensione della tasca uguale a D\2 utensile
elseif Proc.Fct == 3 and bIsL then
dToolMaxDiam = min ( ( min( dFacDim1, dFacDim2) * 2) - 1, dToolTargetDiam)
-- in tutti gli altri casi l'utensile dovrà essere grande al massimo come il lato più piccolo
else
dToolMaxDiam = dToolTargetDiam
end
local _, sPocketing = VerifyPocket( Proc, dToolMaxDiam, dFacElev, nil, sMyMchFind)
bOk, sWarn2, sTuuidPk, dDiamTool, dDepth = MakePocket( Proc, nPartId, b3Solid, ptPs, tvtNx, nFacInd, sMyMchFind, nUseRoughTool, sPocketing, dMachDepth, nil, nil, bAllWithEndCap, nil, nPhase, nRawId, dCustomMaxElev)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
bTryWithBlades = false
-- se ho antischeggia con fresa le inserisco
-- if nChamfer < 2 and nQAntisplintResult == 2 and ( bIsU or bIsL) then
if nChamfer < 2 and nQAntisplintResult == 2 then
local bOk, sWarn2 = ManageAntiSplintByMill( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, bMillDown, dDiamTool, nil,
nil, nil, nil, b3Solid, dDepth,
bOneShot, nFirstMachId)
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
-- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0
if nContourSmallTool > 0 then
local bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiamTool, nContourSmallTool, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid,
dDepth, bOneShotm)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
-- in tutti gli altri casi, a meno che non sia forzata sega a catena, lancio la MakeByPockets
-- lavorazione singola o doppia contrapposta, fondo della tasca una faccia fittizia perpendicolare al lato lungo
elseif not bForceChainsaw then
-- se 2 facce setto i parametri corretti per la MakeByPockets
if bForceSideMill and Proc.Fct == 2 then
bIs3Faces = false
bOrthoFacesMaster = true
bSetOpenBorders = true
end
nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bMillDown, nFirstMachId,
bOrthoFaces = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, bIs3Faces, b3Solid, bOrthoFacesMaster, bMillDown, bSetOpenBorders, bIsU, bIsL)
if nOk == -3 then
bTryWithBlades = true
elseif nOk == -2 then
if not sMchFind then
sMchFind = sMchFindBackUp
end
sPocketing = ML.FindPocketing( sMchFind, dDiam, nil, nil, not bMillDown, bMillDown)
if not sPocketing then
local sErr2 = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr2)
return false, sErr2
end
bTryWithBlades = false
sWarn = sErr
elseif nOk < 0 then
return false, sErr
elseif nOk > 0 then
bTryWithBlades = false
sWarn = sErr
-- se ho antischeggia con fresa le inserisco
-- if nChamfer < 2 and nQAntisplintResult == 2 and ( bIsU or bIsL) then
local nFacIndOri, dFacElevOri = BL.GetFaceWithMostAdj( Proc, nPartId)
if nChamfer < 2 and nQAntisplintResult == 2 then
local bOk, sWarn2 = ManageAntiSplintByMill( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacIndOri, nAddGrpId, bMillDown, dDiamTool, nil,
nil, nil, nil, b3Solid, dFacElevOri,
bOneShot, nFirstMachId)
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
-- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0
if nContourSmallTool > 0 then
local bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiamTool, nContourSmallTool, bMillDown,
bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid,
dDepth, bOneShotm)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
end
bOk = true
end
end
-- 03/09/2020 da conferma di Fabio Squaratti: Per ora solo sulla feature 016:
-- se ha fallito la fresatura (qua sopra) allora di defalut ( anche se il flag Q della lama è disattivato) prima provo la lama
if Proc.Prc == 16 then
bForceUseBlade = true
end
-- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame
if bTryWithBlades and nChamfer < 2 then
-- anche su macchine con testa da sotto, la sega a catena è solo da sopra
if vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and nFacInd2 then
ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT)
nFacInd, nFacInd2 = nFacInd2, nFacInd
dFacElev, dFacElev2 = dFacElev2, dFacElev
bUseOtherFace = true
rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT)
end
-- eseguo
bOk, sWarn, sStat = MakeByChainOrSaw( Proc, nPhase, nRawId, nPartId, nFacInd,
rfFac, dH, dV, dFacElev, bForceUseBlade,
dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace,
bOrthoFaces, nBottomFace, nChamfer, nAddGrpId, b3Solid,
dDepthCham, nSurfInt)
if not bOk and sStat == 'MNF' then
_, sPocketing = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, nil, sMchFind)
if sPocketing then
sWarn = ''
else
local sErr2 = 'Error : '..sMchFind..' not found in library'
EgtOutLog( sErr2)
return false, sErr2
end
else
-- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0
if nContourSmallTool > 0 then
local bOk, sWarn2
bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, 100, nContourSmallTool, bMillDown)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
return bOk, sWarn
end
-- altrimenti verifico se ho già svuotato dal fianco, se si esco
else
-- se non ho annullato la/le svuotatura/e dal fianco
if nOk ~= -2 then
return bOk, sWarn
end
end
end
end
-- SVUOTATURA OK
else
-- se devo inserire il chamfer
if ( ( Proc.Fct == 3 and bIsU) or (Proc.Fct == 2 and bIsL)) and nChamfer > 0 then
-- ottengo le dimensioni dello pseudotunnel
local _, _, _, vtOrtho, _, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return false, sErr end
end
end
-- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo
-- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa
-- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z
-- 2021.07.16 Per poter eseguire antischeggia di lama su feature che non sono passanti da faccia a faccia
-- ma che sono su un angolo (coinvolgono 2 facce contigue) è stato modificato il confronto in:
-- esegue antischeggia di lama se forma U o L con feature passante in Y o Z, oppure se feature a furma U e con 3 facce oppore a forma a L e con 2 facce
-- non fa mai antischeggia di lama se la faccia è rivolta verso il basso, a meno che ci sia una testa sotto
local bMadeASbyBld = false
local bPassThrou = ( Proc.Box:getDimY() > b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > b3Raw:getDimZ() - 1)
local bPassEdge = ((( bIsU and Proc.Fct == 3) or ( bIsL and Proc.Fct == 2)) and bSinglePart and Proc.Box:getDimX() < 0.9 * b3Raw:getDimX())
local nFacIndOri = BL.GetFaceWithMostAdj( Proc, nPartId)
local vtNOri = EgtSurfTmFacetNormVersor( Proc.Id, nFacIndOri, GDB_ID.ROOT)
if nChamfer < 2 and nQAntisplintResult == 1 and (( bIsU or bIsL) and ( bPassThrou or bPassEdge)) and ( vtNOri:getZ() > -0.087 or BD.DOWN_HEAD or BD.TURN) then
local bOk
local bSawDown = ( bMillDown and not bMillUp)
bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, b3Solid, bIsU, vtNOri, nFacIndOri, sWarn, bSawDown)
if not bOk then return false, sWarn end
end
if nChamfer < 2 and nQAntisplintResult == 2 then
local bOk, sWarn2 = ManageAntiSplintByMill( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, bMillDown, dDiamTool, nil,
nil, nil, nil, b3Solid)
if not bOk then return false, sWarn2 end
end
-- dopo aver applicato gli antischeggia ricerco la svuotatura perchè l'ottimizzazione teste deve sapere quale è la lavorazione precedente
_, sPocketing, dMyTMaxDepth, dMyTDiam = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind, bMillUp, bMillDown)
if not sPocketing and bMillUp then
_, sPocketing, dMyTMaxDepth, dMyTDiam = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind)
bMillDown = false
end
-- se smusso non esclusivo
if nChamfer < 2 then
-- eseguo la svuotatura della faccia principale, mi restituisce id utensile, il diametro utensile per il foro opzionale
local tvtNx = {}
tvtNx[2] = vtN
-- recupero alcuni parametri dell'utensile per decidere la distanza di sicurezza da utilizzare
local dMaxToolCutDepth = 0
local dMaxToolMaterial = 0
local dToolThLength = 999
local dToolTotalLength = 0
local dToolThDiameter = 999
local dToolDiameter = 0
if EgtMdbSetCurrMachining( sPocketing) then
local sTuuidPk = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then
dMaxToolCutDepth = EgtTdbGetCurrToolMaxDepth() or dMaxToolCutDepth
dMaxToolMaterial = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxToolMaterial
dToolDiameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiameter
dToolThLength = EgtTdbGetCurrToolThLength() or dToolThLength
dToolThDiameter = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or dToolThDiameter
dToolTotalLength = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dToolTotalLength
end
end
local dMachiningDepth = 0
-- se il gambo è più largo dell'utensile verifico se la lunghezza del gambo è maggiore della distanza di sicurezza calcolata
local dShankLength = dToolTotalLength - dToolThLength - dMaxToolCutDepth
if ( dMaxToolCutDepth < dMaxToolMaterial - 10 * GEO.EPS_SMALL) and ( dShankLength > dCollSic + 10 * GEO.EPS_SMALL) then
dMachiningDepth = dFacElev + BD.COLL_SIC
else
dMachiningDepth = dFacElev + dCollSic
end
local bOk, sWarn2
local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase)
-- se avevo escluso l'attacco da fuori per non rovinare il pezzo successivo, riverifico con il diametro fresa effettivo
if ( Proc.Fct == 4 and bTailOnSide) and ( dDistToNextPiece > dToolDiameter + 10 * GEO.EPS_SMALL) then
sMchFind = EgtIf( bMillDown, 'OpenPocket_H2', 'OpenPocket')
end
bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, nPartId, b3Solid, ptC, tvtNx, nFacInd, sMchFind, nUseRoughTool, sPocketing, dMachiningDepth, nil, nil, bAllWithEndCap, bLapJointAngTrasm, nPhase, nRawId, dCustomMaxElev)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
-- se ho più di 3 facce e non di forma ad u oppure ho 3 facce e di forma ad u oppure groove a 2 facce
-- e non sono stati inseriti antischeggia di lama
-- controllo se c'è una faccia non ortogonale alla principale e la lavoro con una contornatura o svuotatura
if ( ( Proc.Fct >= 3 and not bIsU) or ( Proc.Fct == 3 and bIsU) or ( Proc.Fct == 2)) and not bMadeASbyBld then
-- Recupero le facce adiacenti alla principale
local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1]
if not vAdj or #vAdj == 0 then
local sErr = 'Error : main face without adjacencies'
EgtOutLog( sErr)
return false, sErr
end
-- Cerco una faccia adiacente alla principale con angolo > 90
local nFacAdj
local tDimAndRef = {}
tvtNx = {}
tvtNx[1] = vtN
tDimAndRef[1] = {dH, dV, rfFac}
for i = 1, #vAdj do
if vAdj[i] >= 0 then
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT)
if bAdj and dAng < 0 and 180 + dAng > 90.1 then
local rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, vAdj[i], GDB_ID.ROOT)
_, tvtNx[2] = EgtSurfTmFacetCenter( Proc.Id, vAdj[i], GDB_ID.ROOT)
tDimAndRef[2] = {dH2, dV2, rfFac2}
local ptPs = ( ptP1 + ptP2) / 2
local bOk, sWarn2
bOk, sWarn2 = MachineByMill( Proc, nPhase, nRawId, nPartId, b3Solid, tvtNx, nFacInd, vAdj[i], ptPs, tDimAndRef,
b3Raw, EgtIf( ( Proc.Fct == 3 and bIsU) or Proc.Fct == 2, 0, 2), nUseRoughTool, dAng, sPocketing, sTuuidPk, dFacElev)
if not bOk then return bOk, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
end
end
end
local nBoreOnCorner = EgtGetInfo( Proc.Id, Q_BORE_ON_CORNER, 'i') or 0
local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0
local nCleanCorner = EgtGetInfo( Proc.Id, Q_CLEAN_CORNER, 'i') or 0
-- se abilitato dal parametro Q inserisco foro sullo spigolo
if nBoreOnCorner == 1 then
local bOk, sWarn2
bOk, sWarn2 = MakeDrillOnCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiamTool)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
-- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura
elseif nBoreOnCorner == 2 then
local bOk, sWarn2
bOk, sWarn2 = MakeSharpCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiamTool)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
-- altrimenti se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola
elseif nContourSmallTool > 0 then
local bOk, sWarn2
bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw,
nFacInd, nAddGrpId, dDiamTool, nContourSmallTool, bMillDown)
if not bOk then return false, sWarn2 end
if sWarn2 then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2)
end
end
-- se richiesta pulizia spigoli con fresa a V
if nCleanCorner > 0 then
local dThElev = dToolThDiameter / 2 * sqrt( vtN:getX() * vtN:getX() + vtN:getY() * vtN:getY())
local nNewProc = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacInd, vtN)
local vFace, dDepth = GetFacesData( nNewProc, dToolDiameter, dMaxToolMaterial, ( dToolDiameter/2), nAddGrpId, Proc.PartId, vtN)
local bCleanCornerOk, sCleanCornerWarn = AddMillCorner( vFace, Proc, dToolDiameter, nAddGrpId, nNewProc, vtN)
if not bCleanCornerOk then return false, sCleanCornerWarn end
if sCleanCornerWarn then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sCleanCornerWarn, sCleanCornerWarn)
end
end
end
end
end
-- eventuale segnalazione ingombro di testa o coda
UpdateEncumbrance( Proc, nRawId, b3Raw, b3Solid)
end
return true, sWarn, bPrevBhSideMill
end
---------------------------------------------------------------------
local function MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead)
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- recupero l'ingombro del grezzo di appartenenza
local b3Raw = EgtGetRawPartBBox( nRawId)
-- ottengo la distanza tra la fine del pezzo e il pezzo successivo
local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase)
-- verifico se applicare gestione speciale delle giunzioni (U diretta come asse X)
local bAddEndCapLeftSide, bAddEndCapRightSide = false, false
local dAddLen = 0
local bIsOpenU = ( Proc.Fct == 3 and not TestElleShape3( Proc))
if bIsOpenU then
local ptC0, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT)
local ptC1, vtN1 = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT)
local ptC2, vtN2 = EgtSurfTmFacetCenter( Proc.Id, 2, GDB_ID.ROOT)
if abs( vtN0:getX()) < 0.0175 and abs( vtN1:getX()) < 0.0175 and abs( vtN2:getX()) < 0.0175 then
local dWidth = 0
if vtN0 * vtN1 < -0.9998 then
bAddEndCapLeftSide = true
dWidth = ( ptC1 - ptC0) * vtN0
elseif vtN0 * vtN2 < -0.9998 then
bAddEndCapLeftSide = true
dWidth = ( ptC2 - ptC0) * vtN0
elseif vtN1 * vtN2 < -0.9998 then
bAddEndCapLeftSide = true
dWidth = ( ptC2 - ptC1) * vtN1
end
dAddLen = min( dWidth, 100) / 2
end
end
-- verifico se applicare gestione speciale per tunnel
local nSurfBottomId
if Proc.Topology == 'Tunnel' or ( Proc.Topology == 'Groove' and Proc.IsThrough and Proc.Fct == 3) then
bAddEndCapLeftSide = true
bAddEndCapRightSide = true
-- recupero centro e normale delle facce
local vtN = {}
for i = 1, Proc.Fct do
vtN[i] = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT)
end
-- calcolo l'orientamento del tunnel
local vtOrtho
local bAdj = EgtSurfTmFacetsContact( Proc.Id, 0, 1)
if bAdj then
vtOrtho = vtN[1] ^ vtN[2]
else
if Proc.Fct >= 3 then
vtOrtho = vtN[1] ^ vtN[3]
else
local sErr = 'Error : disconnected tunnel'
EgtOutLog( sErr)
return false, sErr
end
end
vtOrtho = EgtIf( abs( vtOrtho:getY()) > abs( vtOrtho:getZ()), -Y_AX(), -Z_AX())
local ptMaxBox = Proc.Box:getMax()
-- per creare le superfici di cap nei tunnel serve aggiungere una faccia di fondo
-- recupero il box della trave e lo ingrandisco di poco per essere sicuro di avere intersezione con il piano di fondo
local b3SolidExtended = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
b3SolidExtended:expand( 100 * GEO.EPS_SMALL)
-- superficie di fondo
nSurfBottomId = EgtSurfTmPlaneInBBox( nAddGrpId, ptMaxBox, vtOrtho, b3SolidExtended, GDB_ID.ROOT)
-- calcolo di quanto allargare le superfici
if dAddLen == 0 then
local dWidth = EgtIf( Proc.AffectedFaces.Front, Proc.Box:getDimZ(), Proc.Box:getDimY())
dAddLen = min( dWidth, 100) / 2
end
end
-- la divido in parti lungo X
local vAddId = {}
local bAllWithEndCap = bAddEndCapLeftSide or bAddEndCapRightSide
local nPart = max( ceil( Proc.Box:getDimX() / BD.LONGCUT_MAXLEN + 10 * GEO.EPS_SMALL), 2)
local dPartLen = Proc.Box:getDimX() / nPart
local Xmin = Proc.Box:getMin():getX()
-- trimesh per la creazione degli EndCap
local AddIdCopy = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
-- aggiunta di eventuale fondo alla trimesh per creare correttamente le superfici EndCap
if nSurfBottomId then EgtSurfTmAdd( AddIdCopy, nSurfBottomId) end
for i = 1, nPart do
local nCapIdLeftSide, nCapIdRightSide
-- eseguo divisione
local AddId = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL
if i > 1 or bAddEndCapLeftSide then
-- definizione del piano sinsitro
local dAdd = EgtIf( i > 1, dAddLen, 0)
local ptOn = Point3d( Xmin - dAdd + ( i - 1) * dPartLen, 0, 0)
local vtN = -X_AX()
-- se richiesto, creazione tappo sinistro
if bAddEndCapLeftSide then
local nFirstId, nPnt, nCrv, nSrf = EgtPlaneSurfTmInters( ptOn, vtN, AddIdCopy, nAddGrpId, GDB_RT.GLOB)
if nPnt == 0 and nCrv == 1 and nSrf == 0 then
EgtCloseCurveCompo( nFirstId)
nCapIdLeftSide = EgtSurfTmByFlatContour( nAddGrpId, nFirstId)
if not nCapIdLeftSide then bAllWithEndCap = false end
end
if nFirstId then
for nId = nFirstId, nFirstId + nPnt + nCrv + nSrf - 1 do
EgtErase( nId)
end
end
end
if i > 1 then
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, vtN, true, GDB_RT.GLOB)
end
-- se esiste, aggiunta del tappo sinistro
if nCapIdLeftSide then
AddId = EgtSurfTmBySewing( nAddGrpId, { AddId, nCapIdLeftSide})
-- se prima spezzatura, allungamento per non lasciare archi
if i == 1 then
local b3Box = EgtGetBBoxGlob( AddId, GDB_BB.STANDARD)
local dCoeffX = 1 + min( dAddLen, dDistToNextPiece) / b3Box:getDimX()
EgtScale( AddId, Frame3d( b3Box:getMax()), dCoeffX, 1, 1, GDB_RT.GLOB)
end
end
end
if i < nPart then
-- definizione del piano destro
local dAdd = EgtIf( i < nPart, dAddLen, 0)
local ptOn = Point3d( Xmin + dAdd + i * dPartLen, 0, 0)
local vtN = X_AX()
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, vtN, true, GDB_RT.GLOB)
-- se richiesto, creazione tappo destro
if bAddEndCapRightSide then
local nFirstId, nPnt, nCrv, nSrf = EgtPlaneSurfTmInters( ptOn, vtN, AddIdCopy, nAddGrpId, GDB_RT.GLOB)
if nPnt == 0 and nCrv == 1 and nSrf == 0 then
EgtCloseCurveCompo( nFirstId)
nCapIdRightSide = EgtSurfTmByFlatContour( nAddGrpId, nFirstId)
if not nCapIdRightSide then bAllWithEndCap = false end
end
if nFirstId then
for nId = nFirstId, nFirstId + nPnt + nCrv + nSrf - 1 do
EgtErase( nId)
end
end
end
end
-- se esiste, aggiunta del tappo destro
if nCapIdRightSide then
AddId = EgtSurfTmBySewing( nAddGrpId, { AddId, nCapIdRightSide})
end
EgtSetName( AddId, 'AddPart_' .. tostring( Proc.Id) .. '_' .. tostring( i))
-- eseguo inserimento in modo da ordinare da X+ a X-
table.insert( vAddId, 1, AddId)
end
EgtErase( AddIdCopy)
-- applico le lavorazioni sulle diverse parti
local sWarn
local bPrevBhSideMill
for i = 1, #vAddId do
local b3Box = EgtGetBBoxGlob( vAddId[i], GDB_BB.STANDARD)
local nFct = EgtSurfTmFacetCount( vAddId[i])
local AddProc = { Id = vAddId[i], Grp = Proc.Grp, Prc = Proc.Prc, Box = b3Box, TotBox = Proc.Box, Fct = nFct, Flg = Proc.Flg, PartId = Proc.PartId, TaskId = Proc.TaskId, FeatureId = Proc.FeatureId, IsSplittedLapJoint = true, AffectedFaces = Proc.AffectedFaces, OkFromBottom = Proc.OkFromBottom}
Topology.Classify( AddProc, b3Raw)
-- con specifiche topologie si lavora la curva e si forza il lato aperto dove finisce la lavorazione precedente
if i > 1 and
( ( Proc.Topology == 'Groove' and Proc.IsThrough and Proc.Fct == 3 and Proc.AffectedFaces.Left and Proc.AffectedFaces.Right)
or ( Proc.Topology == 'Groove' and Proc.Fct == 4 and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right))
or Proc.Topology == 'Pocket') then
local nFacInd = BL.GetFaceWithMostAdj( AddProc, nPartId)
if type( nFacInd) == "number" and nFacInd >= 0 then
local nLoopId, nLoopCnt = EgtExtractSurfTmFacetLoops( vAddId[i], nFacInd, nAddGrpId)
if nLoopId and nLoopCnt == 1 then
local nEdgeId = BL.GetEdgeToMachineFromVector( vAddId[i], nFacInd, -X_AX())
EgtSetInfo( nLoopId, 'OPEN', nEdgeId)
AddProc.LoopIdFacInd = nLoopId
end
end
end
-- lasciare il false nel sesto parametro (perchè internamente viene verificato se diverso da nil)
local bOk, sMyWarn
bOk, sMyWarn, bPrevBhSideMill = MakeMoreFaces( AddProc, nPhase, nRawId, nPartId, dOvmHead, bAllWithEndCap, bPrevBhSideMill, bAllWithEndCap)
if not sWarn or #sWarn == 0 then sWarn = sMyWarn end
if not bOk then return bOk, sWarn end
end
return true, sWarn
end
---------------------------------------------------------------------
local function TestTwoFacesDownHead( Proc)
-- test valido solo per due facce
if Proc.Fct ~= 2 then return false end
local bDownHeadBlade = false
local bDownHeadMill = false
-- verifico se da lavorare con testa da sotto
if BD.DOWN_HEAD then
local vtNm = ( Proc.Face[1].VtN + Proc.Face[2].VtN)
vtNm:normalize()
bDownHeadMill = ( vtNm:getZ() < -0.5)
-- recupero il massimo materiale della lama sopra
local sCutting = ML.FindCutting( 'HeadSide', true, false)
if not sCutting then
local sErr = 'Error : cutting not found in library'
EgtOutLog( sErr)
return false, sErr
end
local dTopBladeMaxDepth = 0
if EgtMdbSetCurrMachining( sCutting) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dTopBladeMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTopBladeMaxDepth
end
end
-- recupero le caratteristiche della feature e delle facce
local vtRes = Proc.Face[1].VtN ^ Proc.Face[2].VtN
Proc.IsTopDownRabbet = Proc.AffectedFaces.Top and abs( vtRes:getZ()) > 10 * GEO.EPS_SMALL
for i = 1, Proc.Fct do
Proc.Face[i].IsTooDownwardForTopBlade = Proc.Face[i].VtN:getZ() < ( BD.CUT_VZ_MIN or -0.484) - 10 * GEO.EPS_SMALL
Proc.Face[i].IsTooWideForTopBlade = Proc.Face[i].WidthTrimmed > dTopBladeMaxDepth
end
-- serve la lama sotto se c'è almeno una faccia troppo inclinata verso il basso e non è un rabbet stretto lavorabile dal lato
if not ( Proc.Face[1].IsTooDownwardForTopBlade or Proc.Face[2].IsTooDownwardForTopBlade) then
bDownHeadBlade = false
else
for i = 1, Proc.Fct do
if Proc.Face[i].IsTooDownwardForTopBlade and ( not Proc.IsTopDownRabbet or Proc.Face[i].IsTooWideForTopBlade) then
bDownHeadBlade = true
break
end
end
end
end
return bDownHeadBlade, bDownHeadMill
end
---------------------------------------------------------------------
local function MakeStaircaseStep( Proc, nRawId, b3Raw, nPartId)
local sWarn
-- box della trave
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- angolo tra le facce
local _, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
-- l'angolo tra le facce deve essere compreso tra 80 e 95 deg
if ( dAng > -85 + 10 * GEO.EPS_ANG_SMALL) or ( dAng < -100 - 10 * GEO.EPS_ANG_SMALL) then return false end
-- normali delle facce
local vtNRiser = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
local vtNTread = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
-- la faccia 0 è l'alzata (faccia più verticale), la 1 la pedata; se così non è le scambio
local nFacetRiser, nFacetTread = 0, 1
if abs( vtNRiser:getZ()) > abs( vtNTread:getZ()) then
EgtSurfTmSwapFacets( Proc.Id, 0, 1)
Proc.Face = BL.GetFacetsInfo( Proc, b3Raw)
vtNRiser, vtNTread = vtNTread, vtNRiser
end
-- riferimenti e dimensioni delle facce
local rfFacRiser, dHRiser, dVRiser = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacetRiser, GDB_ID.ROOT)
local rfFacTread, dHTread, dVTread = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacetTread, GDB_ID.ROOT)
-- recupero la fresatura
-- verifico se fresatura da sopra
local bIsMillingUpward = ( vtNTread:getZ() >= BD.NZ_MINA)
-- fresatura
local sMilling = ML.FindMilling( 'BirdsMouth', nil, nil, nil, nil, bIsMillingUpward, not bIsMillingUpward)
if not sMilling then
local sErr = 'Error : BirdsMouth not found in library'
EgtOutLog( sErr)
return false, sErr
end
-- dati utensile
local dMillDiam = 50
local dMillMaxMat = 0
local dMillRotationSpeed = 0
if EgtMdbSetCurrMachining( sMilling) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam
dMillMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMillMaxMat
dMillRotationSpeed = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) or dMillRotationSpeed
end
end
-- recupero la lavorazione con lama
-- verifico se uso lama da sotto
local bCutDown = ( BD.DOWN_HEAD and rfFacTread:getVersZ():getZ() < - 0.5)
-- lavorazione con lama
local sCutting = ML.FindCutting( 'HeadSide', not bCutDown, bCutDown)
-- dati utensile
local dSawMaxDepth = 0
local dSawDiam = 400
local dSawRotationSpeed = 0
local dSawThick = 5
if sCutting then
if EgtMdbSetCurrMachining( sCutting) then
local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID)
if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then
dSawMaxDepth = EgtTdbGetCurrToolMaxDepth() or dSawMaxDepth
dSawRotationSpeed = EgtTdbGetCurrToolParam( MCH_MP.SPEED) or dSawRotationSpeed
dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick
end
end
end
-- calcolo riduzione profondità lama in caso di angolo inferiore a 90deg
local dCutExtraSaw = 0
if dAng < -91 and dAng > -179 then
dCutExtraSaw = - dSawThick / tan( 180 + dAng)
end
-- eventuali smussi
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- verifiche per smusso
local nChamfer, dDepthCham, sErrCham = EvaluateQParam( Proc)
-- lavorazione smussi
if nChamfer > 0 then
local _, _, _, vtOrtho, _, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return false, sErr end
if sErr then
if not sWarn then sWarn = '' end
sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sErr, sErr)
end
end
-- fresatura della pedata per fare spazio alla lama
local dMillingDepth = dVTread - dSawMaxDepth + 10
-- divido in passate orizzontali
local nMillHorizontalSteps = ceil( ( dMillingDepth - 100 * GEO.EPS_SMALL) / ( dMillDiam * 0.6))
local dMillHorizontalStep = 0
if nMillHorizontalSteps > 1 then
dMillHorizontalStep = ( dMillingDepth - dMillDiam * 0.6) / ( nMillHorizontalSteps - 1)
end
for i = nMillHorizontalSteps, 1, -1 do
-- inserisco la lavorazione
local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id))
local nMchFId = EgtAddMachining( sName, sMilling)
if not nMchFId then
local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling
EgtOutLog( sErr)
return false, sErr
end
-- aggiungo geometria
EgtSetMachiningGeometry( {{ Proc.Id, nFacetTread}})
-- imposto uso faccia
local nFaceUse = BL.GetNearestOrthoOpposite( vtNTread)
EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse)
-- imposto lato di lavoro e eventuale inversione
local bInvert = dMillRotationSpeed < 0
local nWorkSide = MCH_MILL_WS.LEFT
if bInvert then
nWorkSide = MCH_MILL_WS.RIGHT
end
EgtSetMachiningParam( MCH_MP.WORKSIDE, nWorkSide)
EgtSetMachiningParam( MCH_MP.INVERT, bInvert)
-- imposto posizione braccio porta testa
if vtNTread:getY() < GEO.EPS_SMALL then
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM)
else
EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP)
end
-- imposto attacchi e allungamenti
if nFacetTread then
EgtSetMachiningParam( MCH_MP.STARTADDLEN, dMillDiam/2 + 10)
EgtSetMachiningParam( MCH_MP.ENDADDLEN, dMillDiam/2 + 10)
EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR)
EgtSetMachiningParam( MCH_MP.LITANG, 0)
EgtSetMachiningParam( MCH_MP.LOTANG, 0)
EgtSetMachiningParam( MCH_MP.LIPERP, 0)
EgtSetMachiningParam( MCH_MP.LOPERP, 0)
end
-- imposto eventuale offset
EgtSetMachiningParam( MCH_MP.OFFSR, dVTread - dMillingDepth + ( i - 1) * dMillHorizontalStep)
-- se step verticale non presente, lo setto
local dMillVerticalStep = EgtGetMachiningParam( MCH_MP.STEP, 'd')
if not dMillVerticalStep or dMillVerticalStep <= 10 * GEO.EPS_SMALL then
dMillVerticalStep = 0.25 * dMillDiam
end
EgtSetMachiningParam( MCH_MP.STEP, dMillVerticalStep)
-- dichiaro non si generano sfridi per VMill
local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or ''
sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
-- eseguo
if not ML.ApplyMachining( true, false) then
local _, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nMchFId, false)
return false, sErr
end
-- eventuale segnalazione ingombro di testa o coda
UpdateEncumbrance( Proc, nRawId, b3Raw, b3Solid)
end
-- taglio di lama della pedata
-- calcolo faceuse
local nFaceUseTread = EgtIf( vtNRiser * Z_AX() > -GEO.EPS_SMALL, MCH_MILL_FU.ORTHO_DOWN, MCH_MILL_FU.ORTHO_TOP)
-- lavorazioni della faccia
for i = 2, 1, -1 do
local dCutRadialOffsetTread = - dSawMaxDepth / 2 * ( i - 1)
-- componente limite del vettore Z per lama downUp; impostata a -2 per non farla mai rientrare in quel caso
local dVzLimDwnUp = -2
local bOkSawTread, sErr = Fbs.MakeOne( Proc.Id, nFacetTread, sCutting, dSawDiam, nFaceUseTread, dVzLimDwnUp, dCutRadialOffsetTread + dCutExtraSaw, 0, 0, 0, 0, nil, b3Raw)
if not bOkSawTread then return false, sErr end
end
-- taglio di lama dell'alzata
-- calcolo faceuse
local nFaceUseRiser = EgtIf( vtNRiser * Z_AX() > -GEO.EPS_SMALL, MCH_MILL_FU.ORTHO_DOWN, MCH_MILL_FU.ORTHO_TOP)
-- lavorazioni della faccia
for i = 2, 1, -1 do
local dCutRadialOffsetRiser = - dVRiser / 2 * ( i - 1)
-- componente limite del vettore Z per lama downUp; impostata a -2 per non farla mai rientrare in quel caso
local dVzLimDwnUp = -2
local bOkSawRiser, sErr = Fbs.MakeOne( Proc.Id, nFacetRiser, sCutting, dSawDiam, nFaceUseRiser, dVzLimDwnUp, dCutRadialOffsetRiser + dCutExtraSaw, 0, 0, 0, 0, nil, b3Raw)
if not bOkSawRiser then return false, sErr end
end
return true, sWarn
end
---------------------------------------------------------------------
-- Applicazione della lavorazione
---------------------------------------------------------------------
function ProcessLapJoint.Make( Proc, nPhase, nRawId, nPartId, dOvmHead)
-- inizializzazione costanti
if not BD.C_SIMM_ENC then BD.C_SIMM_ENC = EgtIf( BD.C_SIMM, 180, 90) end
-- setto a nil la variabile smussi
bMadeChamfer = nil
-- limiti di fresatura semplice
local MAX_MILL_LIN = 80
-- recupero l'ingombro del grezzo di appartenenza
local b3Raw = EgtGetRawPartBBox( nRawId)
-- recupero l'ingombro della trave
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
local sErr = 'Error : part box not found'
EgtOutLog( sErr)
return false, sErr
end
-- in base al tipo di feature attribuisco il significato dei parametri Q
AssignQIdent( Proc)
-- se non forzate frese, uso la lama
local bUseBlade = EgtIf( Proc.Prc == 90 or Proc.bForceMill, false, EgtGetInfo( Proc.Id, Q_USE_ROUGH_TOOL, 'i') ~= 1 and EgtGetInfo( Proc.Id, Q_USE_MILL, 'i') ~= 1)
local nForceUseBladeOnNotContinueFace
-- se ho attivo la lama e ho la feature 30, verifico i parametri Q propri della feature
if bUseBlade then
if Proc.Prc == 30 or Proc.Prc == 20 then
local nBladeAntisplint = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0
local nUseRoughToolOnSide = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0
if nUseRoughToolOnSide == 4 and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) then
nUseRoughToolOnSide = 0
end
nForceUseBladeOnNotContinueFace = EgtGetInfo( Proc.Id, Q_BLADE_ON_ALONG_FACE, 'i') or 0
-- se antischeggia di fresa o abilitato sgrossatore di fianco
if nBladeAntisplint == 2 or nUseRoughToolOnSide > 0 then
bUseBlade = false
end
-- se ho attivo la lama e ho la feature 32, verifico i parametri Q propri della feature
elseif Proc.Prc == 32 then
local nBladeAntisplint = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0
local nUseRoughToolOnSide = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0
-- se antischeggia di fresa o abilitato sgrossatore di fianco
if nBladeAntisplint == 2 or nUseRoughToolOnSide == 1 then
bUseBlade = false
end
-- se ho attivo la lama e ho la feature 34, verifico i parametri Q propri della feature
elseif Proc.Prc == 34 then
local nBladeAntisplint = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0
-- se antischeggia di fresa o abilitato sgrossatore di fianco
if nBladeAntisplint == 2 then
bUseBlade = false
end
end
end
-- se lunghezza richiede spezzatura
if ( Proc.Box:getDimX() > BD.LONGCUT_MAXLEN) or
( Proc.Box:getDimX() > 0.7 * b3Solid:getDimX() and ( Proc.DistanceToNextPart > 1000 or Proc.Box:getDimX() > BD.LONGCUT_ENDLEN)) or
( ( nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0) and ( Proc.Box:getDimX() > ( BD.LEN_SHORT_PART or 1000))) then
-- una faccia
if Proc.Fct == 1 then
if bUseBlade then
if nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return LongCut.Make( Proc, nPhase, nRawId, nPartId)
end
else
return LongCut.Make( Proc, nPhase, nRawId, nPartId)
end
-- due facce
elseif Proc.Fct == 2 then
-- verifico se da lavorare con testa da sotto
local bDownHeadBlade = TestTwoFacesDownHead( Proc)
-- dati delle facce
local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD)
local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD)
local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
-- determino se due facce lunghe oppure una lunga e l'altra terminale
if abs( b3Fac1:getDimX() - b3Fac2:getDimX()) < 50 and abs( b3Fac1:getCenter():getX() - b3Fac2:getCenter():getX()) < 50 and
abs( vtN1:getX()) < GEO.EPS_SMALL and abs( vtN2:getX()) < GEO.EPS_SMALL then
-- leggo i parametri Q per utilizzare la fresa di fianco e/o lama
local nUseSideTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0
local bUseBlade = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') == 1
-- forzatura lavorazione discorde in base a parametro Q su feature
local nQ14Param = EgtGetInfo( Proc.Id, Q_CONVENTIONAL_MILLING, 'd') or 0
local bOk, sMyWarn, _, AddedIds = Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool, nQ14Param)
-- se non sono riuscito a farlo di lama, riprovo con la fresa
if not bOk and bUseBlade then
bUseBlade = false
return Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool)
else
return bOk, sMyWarn, nil, AddedIds
end
-- prima faccia terminale
elseif b3Fac1:getDimX() < 1 and abs( vtN2:getX()) < GEO.EPS_SMALL then
-- la faccia 0 deve essere quella lunga
EgtSurfTmSwapFacets( Proc.Id, 0, 1)
Proc.Face = BL.GetFacetsInfo( Proc, b3Raw)
if bUseBlade then
if nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide' .. EgtIf( bDownHeadBlade, '_H2', ''), true, bDownHeadBlade)
end
else
return LongCut.Make( Proc, nPhase, nRawId, nPartId)
end
-- seconda faccia terminale
elseif b3Fac2:getDimX() < 1 and abs( vtN1:getX()) < GEO.EPS_SMALL then
if bUseBlade then
if nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide' .. EgtIf( bDownHeadBlade, '_H2', ''), true, bDownHeadBlade)
end
else
return LongCut.Make( Proc, nPhase, nRawId, nPartId)
end
-- altrimenti
else
if bUseBlade and ( abs( vtN1:getX()) > 0.5 or abs( vtN2:getX()) > 0.5) then
return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide' .. EgtIf( bDownHeadBlade, '_H2', ''), true, bDownHeadBlade)
else
return MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead)
end
end
-- tre facce
elseif Proc.Fct == 3 then
-- determino se due facce lunghe oppure una lunga e l'altra terminale
local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD)
local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD)
local b3Fac3 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 2, GDB_BB.STANDARD)
local bApplyBladeOnLongNotContinueFace
if b3Fac1:getDimX() < 1 and b3Fac3:getDimX() < 1 then
-- la faccia 0 deve essere quella lunga
EgtSurfTmSwapFacets( Proc.Id, 0, 1)
Proc.Face = BL.GetFacetsInfo( Proc, b3Raw)
bApplyBladeOnLongNotContinueFace = true
elseif b3Fac1:getDimX() < 1 and b3Fac2:getDimX() < 1 then
-- la faccia 0 deve essere quella lunga
EgtSurfTmSwapFacets( Proc.Id, 0, 2)
Proc.Face = BL.GetFacetsInfo( Proc, b3Raw)
bApplyBladeOnLongNotContinueFace = true
elseif b3Fac2:getDimX() < 1 and b3Fac3:getDimX() < 1 then
bApplyBladeOnLongNotContinueFace = true
end
if bApplyBladeOnLongNotContinueFace and bUseBlade and nForceUseBladeOnNotContinueFace and nForceUseBladeOnNotContinueFace > 0 then
return LongCut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nForceUseBladeOnNotContinueFace)
else
return MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead)
end
-- più facce
else
return MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead)
end
-- altrimenti lavorazione unica
else
-- una faccia
if Proc.Fct == 1 then
-- se piccola, con fresa
if not bUseBlade and ( Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN)) then
return MakeOneFaceByMill( Proc, nPhase, nRawId, nPartId)
-- se è una spianatura a una faccia richiamo la LongCut
elseif Proc.Prc == 90 then
return LongCut.Make( Proc, nPhase, nRawId, nPartId)
-- se arriva da una cut si applica una svuotatura
elseif Proc.Prc == 10 then
local dDiam = min( Proc.Face[1].Height, Proc.Face[1].Width) * 3
local bMillUp = ( BD.DOWN_HEAD and Proc.Face[1].VtN:getZ() > -0.259)
local bMillDown = ( BD.DOWN_HEAD and Proc.Face[1].VtN:getZ() < 0.342)
local sMchFindMaster = 'OpenPocket'
local _, sPocketing = VerifyPocket( Proc, dDiam, nil, nil, sMchFindMaster, bMillUp, bMillDown)
return Fbp.Make( Proc, Proc.Id, 0, sPocketing, nPartId, b3Solid)
-- altrimenti, con lama
else
return Cut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead)
end
-- due facce
elseif Proc.Fct == 2 then
-- se V passante e attiva Q per lavorazione speciale scala
if EgtGetInfo( Proc.Id, Q_STAIRCASE, 'i') == 1 and Proc.Topology == 'Groove' and Proc.IsThrough == true then
return MakeStaircaseStep( Proc, nRawId, b3Raw, nPartId)
end
-- se praticamente è lunga come la trave e sono due facce lunghe
local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD)
local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD)
if Proc.Box:getDimX() > 0.8 * b3Solid:getDimX() and
abs( b3Fac1:getDimX() - b3Fac2:getDimX()) < 50 and abs( b3Fac1:getCenter():getX() - b3Fac2:getCenter():getX()) < 50 then
local nUseSideTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0
local bOk, sMyWarn = Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool)
-- se non sono riuscito a farlo di lama, riprovo con la fresa
if not bOk and bUseBlade then
bUseBlade = false
return Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool)
else
return bOk, sMyWarn
end
-- altrimenti
else
-- verifico se da lavorare con testa da sotto
local bDownHeadblade, bDownHeadMill = TestTwoFacesDownHead( Proc)
-- determino l'angolo tra le facce
local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
-- se con BH
if VerifyBHSideMill( Proc, nil, nil, nil, nil, b3Raw) then
return MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, true)
-- se ortogonali e non forzata lama, con fresa
elseif not bUseBlade then
-- verifico se devo fare prima gli smussi
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- verifiche per smusso
local nChamfer, dDepthCham, sErrCham = EvaluateQParam( Proc)
-- se smusso da fare
if nChamfer > 0 then
local _, _, _, vtOrtho, _, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return false, sErr end
end
-- se piccole
if Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN) and bAdj and abs( dAng + 90) < 1 then
return MakeTwoFacesByMill( Proc, nPhase, nRawId, nPartId, bDownHeadMill)
else
return MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, true)
end
-- altrimenti, con lama
else
-- verifico se devo fare prima gli smussi
-- recupero gruppo per geometria addizionale
local nAddGrpId = BL.GetAddGroup( nPartId)
if not nAddGrpId then
local sErr = 'Error : missing AddGroup'
EgtOutLog( sErr)
return false, sErr
end
-- verifiche per smusso
local nChamfer, dDepthCham, sErrCham = EvaluateQParam( Proc)
-- se smusso da fare
if nChamfer > 0 then
local _, _, _, vtOrtho, _, nSurfInt = BL.GetTunnelDimension( Proc, nPartId)
local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham)
if nOk < 0 then return false, sErr end
end
-- se smusso non esclusivo
if nChamfer < 2 then
return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide' .. EgtIf( bDownHeadblade, '_H2', ''), true, bDownHeadblade or BD.TURN)
end
return true
end
end
-- tre o più facce
else
return MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, true)
end
end
end
---------------------------------------------------------------------
return ProcessLapJoint