-- ProcessLapJoint.lua by Egaltech s.r.l. 2022/07/05 -- 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/07/19 Profondamente semplificata la funzione SetOpenSide. Modificata la MakeMoreFaces per cercare sempre OpenPocket in determinate condizioni. -- 2022/08/11 Aggiunta lavorazione tunnel splittata con sega a catena per tutte le macchine ad esclusione della Fast. -- 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') 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 -- 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 == 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' 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_BORE_ON_CORNER = 'Q06' -- 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 == 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_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 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) local bUseChainSaw = false local sMchFind = 'Sawing' local sSawing = ML.FindSawing(sMchFind) local dMaxMat = 0 local dSawCornerRad = 0 local dSawThick = 0 local dMaxDepth = 200 -- 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 end --------------------------------------------------------------------- local function VerifyPocket( Proc, dDiam, dDepth, dMaxTotLen, sMchFindMaster, 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, not bPocketDown, bPocketDown) or ML.FindPocketing( sMchFind, dDiam, 0.8 * dDepth, dMaxTotLen, not bPocketDown, bPocketDown) or ML.FindPocketing( sMchFind, dDiam, 0.6 * dDepth, dMaxTotLen, not bPocketDown, bPocketDown) or ML.FindPocketing( sMchFind, dDiam, 0.4 * dDepth, dMaxTotLen, not bPocketDown, bPocketDown) 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 GetTunnelDimension( Proc, nPartId) -- sono necessarie almeno due facce if Proc.Fct < 2 then return 0, 0, 0 end -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- recupero centro e normale delle facce local ptC = {} local vtN = {} for i = 1, Proc.Fct do ptC[i], vtN[i] = EgtSurfTmFacetCenter( 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 return 0, 0, 0 end end -- ottengo il boundingBox e prendo le dimensioni lungo la direzione (Z locale) che rappresenta la profondità della fessura local frFc = Frame3d( ptC[1], vtOrtho) ; local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) local dDepth = b3BoxLoc:getDimZ() -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then EgtOutLog( 'Error : missing AddGroup') return 0, 0, 0 end -- centro del bounding box locale local ptCen = b3BoxLoc:getCenter() ptCen:toGlob( frFc) -- creo superficie intermedia local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptCen, vtOrtho, b3Solid, GDB_ID.ROOT) if not nSurfInt then return 0, 0, 0 end -- ritaglio la superficie con le facce della fessura for i = 1, Proc.Fct do EgtCutSurfTmPlane( nSurfInt, ptC[i], -vtN[i], false, GDB_ID.ROOT) end local frSurfInt, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) -- cerco la faccia con larghezza pari a dimensione massima della fessura local nLongIdFace = 0 for i = 1, Proc.Fct do if abs( vtN[i] * frSurfInt:getVersX()) < 0.5 then nLongIdFace = i - 1 break end end return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt 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 CalcCollisionSafety( vtDir) local dCollSic = 10 * BD.COLL_SIC if abs( vtDir:getX()) > 0.999 or abs( vtDir:getY()) > 0.999 or abs( vtDir:getZ()) > 0.999 then dCollSic = 0 elseif abs( vtDir:getX()) > 0.996 or abs( vtDir:getY()) > 0.996 or abs( vtDir:getZ()) > 0.996 then dCollSic = 1 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.89 or abs( vtDir:getY()) > 0.89 or abs( vtDir:getZ()) > 0.89 then dCollSic = 2.5 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.86 or abs( vtDir:getY()) > 0.86 or abs( vtDir:getZ()) > 0.86 then dCollSic = 4 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.707 or abs( vtDir:getY()) > 0.707 or abs( vtDir:getZ()) > 0.707 then dCollSic = 5.5 * BD.COLL_SIC end return dCollSic 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()) if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + dMinHIng then if Proc.Head then local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX() BL.UpdateHCING( nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX() BL.UpdateTCING( nRawId, dOffs) elseif Proc.Fct > 1 and 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() -- sempre concavo aumento la distanza (rimane una punta...) dDist = dDist + 10 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 local nFacInd, dElev = BL.GetFaceWithMostAdj( Proc.Id, 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 -- 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 return false end -- se lunga come trave, oppure non è trave corta e la sua lunghezza supera il massimo o il 70% 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.7 * 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 -- deve avere la normale principale diretta verso la coda (oppure tunnel) local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc.Id, 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 local bForceSideMill = ( 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.Id, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 else return false end end -- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then return false end -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura for i = 1, Proc.Fct do local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL -- elimino una faccia nDeletedFace = i - 1 if EgtSurfTmRemoveFacet( nNewProc, nDeletedFace) then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( nNewProc, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 EgtErase( nNewProc) break else EgtErase( nNewProc) return false end end -- altrimenti esco else EgtErase( nNewProc) break end end -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo if bClosedOrthoFaces then nFacInd = nDeletedFace -- rendo nulla la faccia opzionale perchè si tratta di una fessura nFacInd2 = nil dElev = BL.GetFaceElevation( Proc.Id, nFacInd) bClosedOrthoFaces = false -- non lo setto come tunnel end end -- se facce formano un tunnel e sono ortogonali if bClosedOrthoFaces then -- ottengo le dimensioni del tunnel local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = 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 nFac2Ind = EgtIf( nFacInd ~= 0, 0, 1) local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFac2Ind, GDB_ID.ROOT) if abs( rfFac:getVersY() * vtN2) < 0.5 then dH, dV = dV, dH rfFac:rotate( rfFac:getOrigin(), rfFac:getVersZ(), 90) end -- se può essere fatto con utensile tipo lama local bUseBHSideMill, _, _, _, _, dTDiam = VerifyBHSideMill( Proc) if bUseBHSideMill then local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) 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 -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) -- 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 bForceSideMill = ( ( EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'd') == 2 or EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'd') == 3) and ( Proc.Fct == 3 or Proc.Fct == 4)) if bForceSideMill then bDown = false elseif nFacInd2 and dElev2 < 2 * dElev then local ptC2, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) elseif not nFacInd2 and bIsL and nFaceAdj >= 0 then local ptC2, vtN2 = EgtSurfTmFacetCenter( 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 il numero di facce > 2 o il box della feature supera una certa distanza dalle teste allora controllo la z 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 ptC2, vtN2 = EgtSurfTmFacetCenter( 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} 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 --------------------------------------------------------------------- local function SetOpenSide( nPathInt, vtOrtho, b3Solid, nAddGrpId, nStartPoint) -- fondo tra loro le curve compatibili EgtMergeCurvesInCurveCompo( nPathInt) local nStartIdEnt, nNumEnt = EgtCurveDomain( nPathInt) local pLastPIni, pLastPEnd -- faccio una copia della curva e la esplodo if nStartIdEnt then -- ciclo i lati della curva e controllo per ognuno se giace in uno dei piani limite del pezzo: se sì allora il lato è aperto for i = 1, nNumEnt do local pPini = EgtUP( nPathInt, (i-1), GDB_RT.GLOB) local pPend = EgtUP( nPathInt, EgtIf( i == nNumEnt, 0, i), GDB_RT.GLOB) if ( abs( pPini:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- scrivo nelle proprietà della curva quali sono i lati aperti local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then -- se ci sono già altri lati aperti EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else -- se è l'unico EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- inizio - 20220719 codice vecchio mantenuto per backup -- -- Se normale lungo la Z considero il box in X e Y -- if abs(vtOrtho:getZ()) > 0.999 then -- -- se corrisponde a X -- if ( abs( pPini:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- -- altrimenti se corrisponde a Y -- elseif ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- end -- -- altrimenti se normale lungo la Y considero il box in X e Z -- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.999 then -- -- se corrisponde a X -- if ( abs( pPini:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- -- altrimenti se corrisponde a Z -- elseif ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- end -- -- caso che non dovrebbe mai capitare ma gestito per completezza -- -- altrimenti se normale lungo la X considero il box in Y e Z -- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.999 then -- -- se corrisponde a Y -- if ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- -- altrimenti se corrisponde a Z -- elseif ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- end -- -- se asse Z orizzontale verifico se si avvicina piú a Y -- elseif abs(vtOrtho:getZ()) < 0.001 then -- if abs(vtOrtho:getY()) > 0.75 then -- -- se corrisponde a Z -- if ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- end -- end -- -- se asse Y a 0 (fresa ne davanti ne dietro) verifico se si avvicina piú a Z+ -- elseif abs(vtOrtho:getY()) < 0.001 then -- if abs(vtOrtho:getZ()) > 0.75 then -- -- se corrisponde a Y -- if ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or -- ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) then -- -- setto l'entità open -- local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' -- if #sActInfo > 0 then -- EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) -- else -- EgtSetInfo( nPathInt, 'OPEN', (i-1)) -- end -- -- prendo i punti per eventuale modifica del punto di inizio percorso -- pLastPIni = pPini -- pLastPEnd = pPend -- end -- end -- fine - 20220719 codice vecchio mantenuto per backup end end -- se devo cambiare il punto di partenza if nStartPoint then if pLastPIni and pLastPEnd then -- calcolo il punto medio con gli ultimi punti utilizzati local ptPs = ( pLastPIni + pLastPEnd) / 2 EgtChangeClosedCurveStartPoint( nPathInt, ptPs, GDB_RT.GLOB) -- se devo eliminare la parte open, nei casi in cui la funzione caller non faccia in automatico il check if nStartPoint == 2 then EgtRemoveCurveCompoCurve( nPathInt, true) EgtRemoveCurveCompoCurve( nPathInt, false) return true end end end end return false 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) dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam dTMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTMaxDepth 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) dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam dTMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTMaxDepth 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) dTDiamDn = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiamDn dTMaxDepthDn = EgtTdbGetCurrToolMaxDepth() or dTMaxDepthDn 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 = CalcCollisionSafety( vtN1) -- elevazione massima della faccia dMaxElev = BL.GetFaceElevation( Proc.Id, nFacInd, nPartId) -- 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 = CalcCollisionSafety( vtOrtho) -- calcolo elevazione dalla faccia trasversale aggiunta local dSurfIntElev = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) 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.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) else dExtraDepth = dMaxElev - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end -- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie else dExtraDepth = dMaxElev - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end end -- normale alla faccia aggiunta vtN1 = Vector3d( vtOrtho) -- imposto i lati aperti e con il parametro 2 li cancello per evitare di lavorarli SetOpenSide( nFirstId, vtOrtho, b3Solid, nAddGrpId, 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) dMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth 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) -- 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 if bIs3Faces then -- nAuxId1, _ = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) -- EgtModifyCurveExtrusion( nAuxId1, vtOrtho, GDB_RT.GLOB) -- SetOpenSide( nAuxId1, vtOrtho, b3Solid, nAddGrpId, 1) -- nNumIdAux = 2 -- 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 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 vtExtr, _, _ = EgtCurveArea( AuxId) end if vtExtr then if not bIs3Faces then local fFrCurve = EgtGetGlobFrame( AuxId) vtExtr:toGlob( fFrCurve) end -- 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, bForceUseBlade, nBottomFace, nAddGrpId, b3Solid, dSawMaxDepth, sMillingOnSide, dSawDiam, dSawThick) local bOrthoFaces local sWarn -- ingombro del grezzo local b3Raw = EgtGetRawPartBBox( nRawId) -- ottengo la distanza tra la fine del pezzo e il pezzo successivo local dDistToNextPiece = EgtGetInfo( nRawId, 'BDST', 'd') or 5. -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd1, dFacElev1, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, nPartId, true) if not nFacInd1 or nFacInd1 < 0 then if nFacInd1 == -1 then bOrthoFaces = nFacInd2 else local sErr = 'Error : MakeByMillAsSaw could not find reference face' EgtOutLog( sErr) return false, sErr end end if bOrthoFaces then -- ottengo le dimensioni del tunnel local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc, nPartId) 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 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 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 -- Se possibile, lavoro con la lama if bForceUseBlade then -- 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 for i = 1, nStep do local dOffs = ( i - 1) * dStep --if vtN:getZ() < BD.NZ_MINA then dOffs = dOffs + dSawThick end local bOk, sErr, nMchId = Fbs.MakeOne( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 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 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 = EgtGetInfo( nRawId, 'BDST', 'd') or 5.4 -- 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.Id, 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 = 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 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') 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 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.GetChainSawBlockedAxis( 1)) 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 limitazioneo dell'affondamento if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' 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.GetChainSawBlockedAxis( 2)) 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) 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.GetChainSawBlockedAxis( 1)) 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.GetChainSawBlockedAxis( 2)) 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) 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 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 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 bMadeASbyBld, sWarn, nIdMach = Fbs.MakeOne( Proc.Id, nFacet, sCutting, dSawDiam, vtN, nil, ( -0.5 + dExtraOffs), BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if bMadeASbyBld then sWarn = nil if 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, ptPs, tvtN, nFaceRef, sMchFind, nUseRoughTool, sMasterPocket, dPrevFaceElev, tDimAndRef, dAng, bOpenOutRaw) -- 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 if 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 nSCC = EgtIf( BL.IsPartFinalPhase( EgtGetCurrPhase()), 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 -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local sWarn if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxDepth - dElev) 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 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 return true, sWarn, sTuuidPk, dDiamTool 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, ptPs, tvtN, nSideFace, sMchFind, nUseRoughTool, sPocketing, dPrevFaceElev, tDimAndRef, dAng) 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( nMchFId, 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) else sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk) 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) -- setto inversione del percorso EgtSetMachiningParam( MCH_MP.INVERT, true) -- 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) if dElev > 0 then EgtSetMachiningParam( MCH_MP.LIPERP, dElev) end end if bOpenEnd then EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.ENDADDLEN, -dTDiam / 2) if dElev > 0 then 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) local nFirstMachId local bOrthoFaces local sWarn local sMchFind = 'Pocket' local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt local bBadMach = false 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.Id, 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 = 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.Id, nPartId, false) local dWidth = GetUShapeWidth( Proc, nFacInd or -1) 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, true) -- se è negativo inverto il versore e la faccia if vtOrtho:getZ() < 0 then vtOrtho = -vtOrtho EgtInvertSurf( nSurfInt) end end if bMakePocket 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 SetOpenSide( nPathInt, vtOrtho, b3Solid, nAddGrpId) end -- variabili per parametri lavorazione local dMachDepth local dElev = 0 local bDoubleSide local bOneShot local bComplete = true -- imposto altezza aggiuntiva di elevazione local dCollSic = 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 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 -- 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 -1, sErr end -- prendo l'id della prima lavorazione inserita if not nFirstMachId then nFirstMachId = nMchFId end -- aggiungo geometria EgtSetMachiningGeometry( {{ nPathInt, -1}}) -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) local bInvertMach 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 -- 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 EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposto affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- 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) -- 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 -- 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 -- inserisco la lavorazione di svuotatura local sName = 'PockOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local 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 -- prendo l'id della prima lavorazione inserita if not nFirstMachId then nFirstMachId = nMchFId end -- aggiungo geometria EgtSetMachiningGeometry( {{ nPathInt, -1}}) -- 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) -- imposo affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- 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) -- 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.Id, 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 = 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, 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() < -(10 * GEO.EPS_SMALL) 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 local dDepth = 0 if bIsU then if abs(vtN:getZ()) > 0.63 or abs(vtN:getY()) > 0.63 then -- if abs(vtN:getZ()) > 0.7 or abs(vtN:getY()) > 0.7 then -- prendo il vettore normale alla faccia local _, vtNFc = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) -- se superficie principale parallela al piano XZ if nPrefSide == 0 then -- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto) if 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 end -- eseguo inversione if bInvertMach then local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT) local nWS = EgtGetMachiningParam( MCH_MP.WORKSIDE) local nInvWS = EgtIf( nWS == MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT) 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.WORKSIDE, nInvWS) EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert) -- setto l'offset pari allo spessore lama EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick) end end -- posizione del braccio : se primo taglio la recupero, altrimenti la imposto if not nPrevSCC then nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC) else 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.Id, nFacInd) 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 = 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.Id, nFacInd) -- 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 = 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.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) else dExtraDepth = dMaxElevMaster - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end -- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie else dExtraDepth = dMaxElevMaster - BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) end end vtN1 = Vector3d(vtOrtho) -- imposto i lati aperti e con il parametro 2 li cancello per evitare di lavorarli local bOkPath = SetOpenSide( nFirstId, vtOrtho, b3Solid, nAddGrpId, 2) -- se non ho un percorso chiuso estraggo i percorsi if bOkPath 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.GetChainSawBlockedAxis( 1)) 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.GetChainSawBlockedAxis( 2)) 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 --------------------------------------------------------------------- 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 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.Id, 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 è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura for i = 1, Proc.Fct do local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL -- elimino una faccia nBottomFace = i - 1 if EgtSurfTmRemoveFacet( nNewProc, nBottomFace) then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( nNewProc, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 EgtErase( nNewProc) break else EgtErase( nNewProc) local sErr = 'Error : MakeMoreFaces could not find reference face' EgtOutLog( sErr) return false, sErr end end -- altrimenti esco else EgtErase( nNewProc) break end end -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo if bClosedOrthoFaces then nFacInd = nBottomFace -- rendo nulla la faccia opzionale perchè si tratta di una fessura nFacInd2 = nil dFacElev = BL.GetFaceElevation( Proc.Id, nFacInd) bClosedOrthoFaces = false -- non setto come tunnel end 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 -- se è un tunnel provo a vedere se è possibile lavorarlo con la svuotatura o con la sega catena if bClosedOrthoFaces then local bTryWithBlades = true -- lavoro fessura con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' local 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 -- 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 = VerifyChainSaw( Proc, dDimMin, dDimMax) if bMakeChainSaw then -- 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 local dWorkDepth = dDepth -- cerco di estendere il taglio considerando la parte arrotondata della lama + 1 if dMaxMat > 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 < dDepth then dWorkDepth = dMaxMat 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° local bForceSideMill = ( 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 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)) -- 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 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 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 = 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) 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()) then bSpecial3faces = true end -- se riconosciuta gestione 3 facce -- e limitata per ora alla feature 20 if bSpecial3faces and Proc.Prc == 20 and nFacInd2 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 -- se orientata verso il basso e non c'è testa da sotto, verifico l'alternativa if 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 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.Id, nFacInd) 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 = 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) 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( dDiam, 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) - 1, BD.MAXDIAM_POCK_CORNER) else dDiam = 2 * 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 -- 03/12/2020 aggiunto controllo su feature 30 senza uso truciolatore if bNewCheck and Proc.Prc == 30 and nUseRoughTool == 0 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 da sotto, imposto massima lunghezza secondo la direzione local dMaxTotLen if bMillDown and BD.GetBottomToolMaxTotLen then dMaxTotLen = BD.GetBottomToolMaxTotLen( vtN) end -- ricerca lavorazione local sPocketing local _, sMyPocketing, dMyTMaxDepth, dMyTDiam = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind, bMillDown) if not sMyPocketing and bMillUp then _, sMyPocketing, dMyTMaxDepth, dMyTDiam = VerifyPocket( Proc, dDiam, dFacElev + dCollSic, dMaxTotLen, sMchFind) bMillDown = false end --local sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, dFacElev + dCollSic, dMaxTotLen) --if not sMyPocketing then -- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, nil, dMaxTotLen) --end --if not sMyPocketing and bMillUp then -- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam, dFacElev + dCollSic) -- if not sMyPocketing then -- sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam) -- end -- bMillDown = false --end 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)) then sPocketing = sMyPocketing end if bMillDown then sMchFind = sMchFind ..'_H2' end -- 2021.09.16 Richiesta di Fabio Squaratti per lavorazione "Lamello": -- se ho attiva questo tipo di lavorazione (delle fresature) e una di queste feature: L016, L030, L032, L039 -- verifico se sono compatibili con questa lavorazione forma a U e larga più dell'altezza tagliente e profondità compatibile con local bSpecialMillOnSide local dThickMillOnSide = 0 local sMillingOnSide local dToolDiamOnSide = 0 local dMaxDepthOnSide = 0 if ( Proc.Prc == 16 or Proc.Prc == 30 or Proc.Prc == 32 or Proc.Prc == 39) then -- verifico se ho una gola con 3 facce ed eventualmente delle facce terminali: -- faccio una copia della superfice ed elimino le facce che hanno dimensione X < 1 e le facce risultanti devono essere una U local nTestId = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL if nTestId then local bNewIsU local bExit local nFaces = EgtSurfTmFacetCount( nTestId) while not bExit and nFaces >= 3 do local bDeleteFace 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)) bExit = true end end -- verifico che la componente x della faccia o deve essere nulla local vtN1 = EgtSurfTmFacetNormVersor( nTestId, 0, GDB_ID.ROOT) if bNewIsU and abs( vtN1:getX()) > 0.01 then bNewIsU = false end -- cancello la copia del percorso EgtErase( nTestId) if bNewIsU and ( not BD.MIN_LEN_LAMELLO or ( Proc.TotBox and Proc.TotBox:getDimX() > BD.MIN_LEN_LAMELLO) or ( not Proc.TotBox and Proc.Box:getDimX() > BD.MIN_LEN_LAMELLO)) then -- recupero la lavorazione local bDownHead = BD.DOWN_HEAD and vtN:getZ() < BD.NZ_MINA sMillingOnSide = ML.FindMilling( 'SideMillAsBlade_H2', nil, nil, nil, nil, not bDownHead, bDownHead) if sMillingOnSide then -- recupero i dati dell'utensile local dToolLength = 0 local sUserNote if EgtMdbSetCurrMachining( sMillingOnSide) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength dToolDiamOnSide = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiamOnSide dThickMillOnSide = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dThickMillOnSide dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide end end -- 2021.09.17 Su conferma di Fabio Squaratti, se la gola è più streta dell'utensile o la profondità della gole è maggiore -- del valore parametro SIDEDEPTH (preso dalle note utente dell'utensile) allora si prosegue come se non fosse abilitata -- questo tipo di lavorazione SideMillAsBlade if dDiam > dThickMillOnSide - 10 * GEO.EPS_SMALL and dFacElev < dMaxDepthOnSide + 10 * GEO.EPS_SMALL then bSpecialMillOnSide = true -- disabilito eventulae svuotatura sPocketing = nil end end end end 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 -- 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 trova 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, bSpecialMillOnSide, nBottomFace, nAddGrpId, b3Solid, dMaxDepthOnSide, sMillingOnSide, dToolDiamOnSide, dThickMillOnSide) 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 = 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 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()) if nChamfer < 2 and nQAntisplintResult == 1 and (( bIsU or bIsL) and ( bPassThrou or bPassEdge)) then local bOk local bSawDown = ( bMillDown and not bMillUp) bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, bIsU, vtN, nFacInd, 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) -- 20220719 -> settate tutte come OpenPocket; prima era Pocket local sMyMchFind = 'OpenPocket' 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) then nFacInd, vtN, ptC = nFacApproxY, vtNFacApproxY, ptCFacApproxY local tvtNx = {} tvtNx[2] = vtN local ptPs = ptC dFacElev = BL.GetFaceElevation( Proc.Id, nFacInd) dCollSic = CalcCollisionSafety( tvtNx[2]) local dMachDepth = dFacElev + dCollSic local frFacRec, dFacDim1, dFacDim2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- limito il diametro utensile massimo a 100 per queste lavorazioni dToolTargetDiam = min( BD.MAXDIAM_POCK_CORNER, 100) -- 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.Id, i - 1) 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 = min ( dFacDim1, dFacDim2, dToolTargetDiam) end local _, sPocketing = VerifyPocket( Proc, dToolMaxDiam, dFacElev, nil, sMyMchFind) bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, nPartId, ptPs, tvtNx, nFacInd, sMyMchFind, nUseRoughTool, sPocketing, dMachDepth, nil, nil, bAllWithEndCap) 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, bDoubleSide, vtOrtho, nPathInt, nSurfInt, 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 lancio la MakeByPockets (lavorazione singola o doppia contrapposta, fondo della tasca una faccia fittizia perpendicolare al lato lungo) else -- 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) 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 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 if nChamfer < 2 and nQAntisplintResult == 2 then local bOk, sWarn2 = ManageAntiSplintByMill( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, bMillDown, dDiamTool, bDoubleSide, vtOrtho, nPathInt, nSurfInt, 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 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 = 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 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()) if nChamfer < 2 and nQAntisplintResult == 1 and (( bIsU or bIsL) and ( bPassThrou or bPassEdge)) then local bOk local bSawDown = ( bMillDown and not bMillUp) bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, bIsU, vtN, nFacInd, sWarn, bSawDown) if not bOk then return false, sWarn end end if nChamfer < 2 and nQAntisplintResult == 2 then local bOk, sWarn2 bOk, sWarn2 = ManageAntiSplintByMill( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, bMillDown) 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 local bOk, sWarn2 bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, nPartId, ptC, tvtNx, nFacInd, sMchFind, nUseRoughTool, sPocketing, dFacElev + dCollSic, nil, nil, bAllWithEndCap) 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 -- 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)) 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), 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 = EgtGetInfo( nRawId, 'BDST', 'd') or BD.OVM_MID -- verifico se applicare gestione speciale delle giunzioni (U diretta come asse X) local bAddEndCap = false local dAddLen = 0 local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc)) if bIsU 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 vtN0:getX() < 0.0175 and vtN1:getX() < 0.0175 and vtN2:getX() < 0.0175 then local dWidth = 0 if vtN0 * vtN1 < -0.9998 then bAddEndCap = true dWidth = ( ptC1 - ptC0) * vtN0 elseif vtN0 * vtN2 < -0.9998 then bAddEndCap = true dWidth = ( ptC2 - ptC0) * vtN0 elseif vtN1 * vtN2 < -0.9998 then bAddEndCap = true dWidth = ( ptC2 - ptC1) * vtN1 end dAddLen = min( dWidth, 100) / 2 end end -- la divido in parti lungo X local vAddId = {} local bAllWithEndCap = bAddEndCap local nPart = max( ceil( Proc.Box:getDimX() / BD.LONGCUT_MAXLEN), 2) local dPartLen = Proc.Box:getDimX() / nPart local Xmin = Proc.Box:getMin():getX() for i = 1, nPart do -- eseguo divisione local AddId = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL EgtSetName( AddId, 'AddPart_' .. tostring( Proc.Id) .. '_' .. tostring( i)) if i > 1 or bAddEndCap then -- definizione del piano 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 local CapId if bAddEndCap then local nFirstId, nPnt, nCrv, nSrf = EgtPlaneSurfTmInters( ptOn, vtN, AddId, nAddGrpId, GDB_RT.GLOB) if nPnt == 0 and nCrv == 1 and nSrf == 0 then EgtCloseCurveCompo( nFirstId) CapId = EgtSurfTmByFlatContour( nAddGrpId, nFirstId) if not CapId then bAllWithEndCap = false end end if nFirstId then for nId = nFirstId, nFirstId + nPnt + nCrv + nSrf - 1 do EgtErase( nId) end end end -- taglio della superficie EgtCutSurfTmPlane( AddId, ptOn, vtN, true, GDB_RT.GLOB) -- se esiste, aggiunta del tappo if CapId then AddId = EgtSurfTmBySewing( nAddGrpId, { AddId, CapId}) -- 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 local ptOn = Point3d( Xmin + i * dPartLen, 0, 0) local vtN = X_AX() EgtCutSurfTmPlane( AddId, ptOn, vtN, true, GDB_RT.GLOB) end -- eseguo inserimento in modo da ordinare da X+ a X- table.insert( vAddId, 1, AddId) end -- 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} -- 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 then sWarn = sMyWarn end if not bOk then return bOk, sWarn end end return true, sWarn end --------------------------------------------------------------------- local function TestTwoFacesDownHead( Proc) -- verifico ci siano due facce if Proc.Fct ~= 2 then return false end -- verifico se da lavorare con testa da sotto local bDownHead = false if BD.DOWN_HEAD then 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) local vtNm = ( vtN[1] + vtN[2]) ; vtNm:normalize() bDownHead = ( vtNm:getZ() < -0.5) end return bDownHead end --------------------------------------------------------------------- -- Applicazione della lavorazione --------------------------------------------------------------------- function ProcessLapJoint.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) -- 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 = 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 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) 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 bDownHead = 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 return Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool) -- 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) 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( bDownHead, '_H2', ''), true, bDownHead) 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( bDownHead, '_H2', ''), true, bDownHead) 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( bDownHead, '_H2', ''), true, bDownHead) 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) bApplyBladeOnLongNotContinueFace = true elseif b3Fac1:getDimX() < 1 and b3Fac2:getDimX() < 1 then -- la faccia 0 deve essere quella lunga EgtSurfTmSwapFacets( Proc.Id, 0, 2) 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) -- altrimenti, con lama else return Cut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) end -- due facce elseif Proc.Fct == 2 then -- 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 return Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool) -- altrimenti else -- verifico se da lavorare con testa da sotto local bDownHead = 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 and bAdj and abs( dAng + 90) < 1 then -- se piccole if Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN) then return MakeTwoFacesByMill( Proc, nPhase, nRawId, nPartId, bDownHead) 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 = 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( bDownHead, '_H2', ''), true, bDownHead 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