-- 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 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') -- 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 -- variabile smussi local bMadeChamfer -- Settaggi interni local bTrySidePocketAtFirst = true --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessLapJoint.Identify( Proc) return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 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 --------------------------------------------------------------------- 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' 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 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17 then Q_DEPTH_CHAMFER = 'Q01' -- d Q_ONLY_CHAMFER = 'Q02' -- 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 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 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 33 then Q_ANTISPLINT_TYPE = 'Q06' -- 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 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 elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 90 then Q_ANTISPLINT_TYPE = 'Q03' -- i Q_SIDE_ROUGH_TOOL = 'Q04' -- 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) -- 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 nUseSideTool == 0 and not BD.BH_MACHINE 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 for i = 1, Proc.Fct do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) if abs( vtN:getX()) > 0.001 and abs( vtN:getX()) < 0.999962 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) 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 then if bUseBHSideMill and ( Proc.Box:getMax():getX() - b3Solid:getMin():getX()) < 400 then return true else 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 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) 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 local vtNBottomFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) if AreOppositeVectorApprox( vtNBottomFace, 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 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) 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 = ( ( 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 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.LEFT) if not bUp then EgtSetMachiningParam( MCH_MP.INVERT, true) 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 EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- 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 EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- 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 EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- 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 sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) 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 = 'VMRS=0;' sUserNotes = 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 = 'VMRS=0;' sUserNotes = 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 = 'VMRS=0;' sUserNotes = 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 = 'VMRS=0;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 local sUserNotes = 'VMRS=0;' -- aggiungo alle note massima elevazione (coincide con affondamento) sUserNotes = 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 local bOk, sErr, nMchId = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, dVzLimDwnUp, 0, BD.CUT_SIC, dOffs, dStartDist, dEndDist, nil, b3Raw) if not bOk then return bOk, sErr end -- setto l'elevazione local sNotes = 'MaxElev=' .. EgtNumToString( 0, 1) .. ';' -- applico elevazione EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 -- se la lunghezza utensile non riesce ad arrivare sul fondo assegno la possibilità di lavorare di fianco (se possibile) if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then -- continuo di testa se fessura con tre facce o non è tunnel bGoFromHead = (( bIs3Faces and dMaxElev) or not bOrthoFaces) 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 sNotes = 'MaxElev=' .. EgtNumToString( dElev, 2) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 else -- verifico se posso farlo con la sega-catena 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 vtRef = Vector3d( vtOrtho) if vtRef:getY() > 0.5 or vtRef:getZ() < -0.1 then vtRef = -vtRef end 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) -- se possibile aumento l'affondamento pari al raggio corner + 1 if dMaxMat2 > ( dDepth + dSawCornerRad2 + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dDepth + dSawCornerRad2 + 1)) -- se massimo affondamento supera altezza fessura, uso massimo affondamento elseif dMaxMat2 > (dDepth + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dMaxMat2 - 1)) -- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning elseif dMaxMat2 < dDepth then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat2) sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- considero estremi inizio/fine chiusi -- imposto massima elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 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) -- 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 EgtSetMachiningGeometry( {{ Proc.Id, (nFaceRef)}}) -- 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' 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.SUBTYPE, MCH_POCK_SUB.ZIGZAG) 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 imposta dall'utente local dMaxElev = EgtGetInfo( Proc.Id, Q_MAX_ELEVATION, 'd') if dMaxElev and dMaxElev < 1 then dMaxElev = nil end -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente dElev = dMaxElev 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 sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' if bOpenOutRaw then sNotes = sNotes .. 'OpenOutRaw=1;' end sNotes = sNotes .. ( EgtGetMachiningParam( MCH_MP.USERNOTES) or '') EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) 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 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 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 -- 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 -- 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 uso faccia local nFaceUse = BL.GetNearestOrthoOpposite(tvtN[1]) -- 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 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 local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) 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 local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, (nBaseFace))[1] for j = 1, #vAdj2 do if vAdj2[j] == (nSideFace) then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == (nSideFace) 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] == (nSideFace) do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) end end end local sMilling if nUseRoughTool > 0 then sMilling = ML.FindMilling( 'Long2Cut', nil, sTuuidPk) if not sMilling then sMilling = ML.FindMilling( 'Long2Cut') end else sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk) if not sMilling then sMilling = ML.FindMilling( 'LongSmallCut') end end if not sMilling then local sErr = 'Error : Long2Cut & LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr 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 -- 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) EgtSetMachiningParam( MCH_MP.INVERT, ( nWrkSide ~= MCH_MILL_WS.RIGHT)) -- 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) EgtSetMachiningParam( MCH_MP.LOPERP, dElev) 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.LIPERP, dElev) EgtSetMachiningParam( MCH_MP.LOPERP, dElev) end end -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end return true 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 sNotes = '' if not bMakeContour then sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' end sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 sNotes = '' if not bMakeContour then sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' end sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 sNotes = 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 = 'VMRS=0;' -- aggiungo alle note massima elevazione sUserNotes = 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-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) 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) 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.GetToolFromMachining( sMachiningName) local Tool = {} if EgtMdbSetCurrMachining( sMachiningName) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then Tool.Name = EgtTdbGetCurrToolParam( MCH_TP.NAME) Tool.IsCCW = ( EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) < 0) Tool.Type = EgtTdbGetCurrToolParam( MCH_TP.TYPE) Tool.Diameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0 -- lama if Tool.Type == MCH_TY.SAW_STD or Tool.Type == MCH_TY.SAW_FLAT then Tool.Thickness = EgtTdbGetCurrToolParam(MCH_TP.THICK) or 0 Tool.MaxDepth = EgtTdbGetCurrToolMaxDepth() or 0 Tool.SideStep = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDESTEP', 'd') -- sega a catena elseif Tool.Type == MCH_TY.MORTISE_STD then Tool.Length = EgtTdbGetCurrToolParam( MCH_TP.LEN) or 0 Tool.MaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or 0 Tool.Width = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0 Tool.Thickness = EgtTdbGetCurrToolParam( MCH_TP.THICK) or 0 Tool.CornerRadius = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) or 0 -- altri utensili al momento non previsti else error( 'Wrong tool type') end end end return Tool 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) 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 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) 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) end Cutting.Type = MCH_OY.MILLING Cutting.Tool = SawPlusChain.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 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 -- 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 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 = sCuttingApplyMessage .. 'Apply : ' .. sCuttingApplyMessage .. '\n' 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 = SawPlusChain.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 else -- se la lama non è arrivata sul fondo e c'è almeno un lato aperto va lavorato if 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 else -- 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 MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, bSinglePart, bPrevBhSideMill, bAllWithEndCap) if not BD.MAXDIAM_POCK_CORNER then BD.MAXDIAM_POCK_CORNER = 30 end 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 -- se è un tunnel provo a vedere se è possibile lavorarlo con la svuotatura o con la sega 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 = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, false, b3Solid, bClosedOrthoFaces) if nOk < 0 then return false, sErr elseif nOk > 0 then 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 -- altrimenti non è una fessura 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 = 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) if bPrevBhSideMill == nil then bPrevBhSideMill = bMakeBySideMill end 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 -- se lavorazione da sotto e lunga, va divisa in due metà local bDouble = ( 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 sNotes = 'MaxElev=' .. EgtNumToString( dVcalc + dStep, 2) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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) 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) -- 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 -- altrimenti lavoro con svuotatura 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 -- se riconosciuta gestione 3 facce (limitatamente per ora alla feature 20) if 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 local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr 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 sNotes = 'MaxElev=' .. EgtNumToString( dFacElev2, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- 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 -- altrimenti lavorazione di svuotatura o contornatura 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 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 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 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') -- ricerca lavorazione 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 l'utente ha definito un'elevazione custom dUserMaxElev si lavora sempre la faccia standard if sMyPocketing and ( dMyTMaxDepth > dFacElev + dCollSic - 10 * GEO.EPS_SMALL or ( dMyTMaxDepth > 0.8 * dFacElev + dCollSic and not bIsU) or ( bIsL and nUseRoughTool == 0) or ( Proc.Prc == 25 and not bIsU and not bIsL)) or ( dUserMaxElev and dUserMaxElev > 10 * GEO.EPS_SMALL) then sPocketing = sMyPocketing 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 -- se non trovata una svuotatura adatta 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 -- 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) 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 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 -- 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) 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 -- 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 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 local dWidth = EgtIf( Proc.AffectedFaces.Front, Proc.Box:getDimZ(), Proc.Box:getDimY()) dAddLen = min( dWidth, 100) / 2 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} Topology.Classify( AddProc, b3Raw) -- 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 = 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 EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- 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, 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 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.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 local bOk, sMyWarn, _, AddedIds = 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, 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) -- 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) then return MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, true) -- se ortogonali e non forzata lama, con fresa elseif not bUseBlade then -- 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