-- WProcessLapJoint.lua by Egaltech s.r.l. 2023/10/02 -- Gestione calcolo mezzo-legno per Pareti -- 2021/08/27 DS Se tre o più facce con flag PCKT=1 forzo svuotatura con fresa (per Variant). -- 2021/08/29 DS Se svuotatura di fianco setto flag per farla dopo i tagli. -- 2021/09/03 DS Se due facce con sottosquadra ora si restituisce mesaaggio di errore. -- 2021/10/05 FM Gestione lavorazioni SideMill con creazione gola passaggio gambo utensile -- 2021/11/29 DS Correzione lav.ni SideMill quando più profonde che larghe. -- 2022/01/04 DS Se U con fondo verso basso o alto non ci possono essere spigoli verticali da pulire. -- 2022/01/17 ES Migliorata scelta fresa per lavorazione di fianco sotto. -- 2022/02/03 DS Gorge larga come gambo più sicurezza. -- 2022/02/04 DS In svuotatura aggiunta gestione WD.MAXDIAM_POCK_CORNER in presenza di almeno un angolo interno. -- 2022/09/30 In MakeSideGrooveByMill sistemato il calcolo del massimo sottosquadro dell'utensile per determinare la fattibilità della tasca. -- 2022/10/05 In MakeSideGrooveByMill implementata l'inversione dello step se la tasca guarda verso il basso -- 2022/11/15 DS Con lama massima inclinazione 60deg. -- 2022/12/01 Per 2 facce con angolo > 90° implementata lavorazione principale verticale. Se da sopra, aggiunta ripresa del lato inclinato. -- 2022/12/14 Nel caso di 2 facce piccola correzione al modo di ordinare le facce. -- 2023/03/09 Gestito caso riconoscimento errato Stype 3. -- 2023/03/09 In MakeMoreFaces aggiunta la possibilità di lavorare le fessure con la lama. -- 2023/03/17 In MakeByMill gestito correttamente il caso di Workside destro. -- 2023/04/15 Corretta scelta tipo lavorazione 'SideGroove' aggiungendo massimo spessore. -- 2023/04/17 Sistemata gestione parametri Q, eliminando quello non usato di forzatura lama e abilitandoli anche per DoubleCut. -- Lavorazione CleanCorner sempre forzata con lato di lavoro in centro. -- 2023/05/25 Funzioni EgtAddMachining sostituite da WM.AddMachining in modo da trascrivere le priorità da btl alle lavorazioni. -- 2023/06/30 Aggiunta lettura delle note esistenti dalle lavorazioni per evitare di sovrascriverle. -- 2023/07/10 In MakeSideGrooveByMill si impedisce ora di lavorare una groove se la testa deve scendere sotto al limite superiore del grezzo. -- 2023/07/25 Aggiunte passate laterali per SideGroove, se specificato SIDESTEP nelle note utensile. -- 2023/08/01 Migliorato controllo testa sotto al grezzo in SieGroove. -- 2023/08/07 Controllo testa sotto al grezzo in SideGroove escluso se richiesto il move after. -- 2023/09/19 Controllo lavorabilità con una sola faccia ora ha limiti come FreeContour. -- 2023/09/21 Modifica controllo lavorabilità con tre facce tipo tunnel ma non ortogonali tra loro. -- 2023/09/21 In MakeByMill modificato SCC per correggere caso con lama su testa fresa. -- 2023/10/02 Aggiunta segnalazione lavorazione tipo Side non trovata. -- 2023/11/14 Aggiunta tasche in doppio. -- Miglioramenti sostanziali nella gestione delle tasche. -- 2023/11/16 Fresature a salire estese a groove cieche. -- 2024/02/20 Piccola correzione ai casi in cui si utilizza il SIDESTEP. -- Tabella per definizione modulo local WPL = {} -- Include require( 'EgtBase') local WL = require( 'WallLib') local FreeContour = require( 'WProcessFreeContour') EgtOutLog( ' WProcessLapJoint started', 1) -- Dati local WD = require( 'WallData') local WM = require( 'WMachiningLib') local WHISK_OFFS = 0.1 local WHISK_SAFE = 5 local MIN_LEN_CUT = 30 -- variabili assegnazione parametri Q local Q_SIDE_MILL = '' -- d local Q_CORNER_CUT = '' -- i -- variabile settaggio doppia lavorazione su angolo > 90 local bMakeTwinCut = true -- angolo sottosquadra ammesso per fresa cono 30° local dAngleSmall = 70 --------------------------------------------------------------------- -- Riconoscimento della feature function WPL.Identify( Proc) return ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) or ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) or ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) or ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30) or ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32) or ( ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) or ( ( Proc.Grp == 4) and Proc.Prc == 39) end --------------------------------------------------------------------- local function AssignQIdent( Proc) -- reset assegnazione parametri Q Q_SIDE_MILL = '' Q_CORNER_CUT = '' if Proc.Prc == 11 then Q_SIDE_MILL = 'Q02' -- i Q_CORNER_CUT = 'Q05' -- i elseif Proc.Prc == 12 then Q_SIDE_MILL = 'Q02' -- i Q_CORNER_CUT = '' -- i elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then Q_SIDE_MILL = 'Q08' -- i Q_CORNER_CUT = 'Q05' -- i else Q_SIDE_MILL = 'Q03' -- i Q_CORNER_CUT = 'Q05' -- i end -- le altre features gestite non hanno parametri Q end --------------------------------------------------------------------- local function EvaluateQParam( Proc) -- Verifico se utilizzare la fresa di lato : -- 0 : niente -- 1 : utilizzo fresa di lato (alla faccia selezionata) local nUseSideMillAsBlade = EgtGetInfo( Proc.Id, Q_SIDE_MILL, 'i') or 0 -- Verifico il tipo di lavorazione su angolo : -- 0 : niente -- 1 : ripresa corner dopo pausa per rimozione sfridi (fresa 60deg) -- 2 : ripresa corner senza pausa (fresa 30 deg) -- 3 : scarico corner (tipo foro). local nTypeCornerCut = EgtGetInfo( Proc.Id, Q_CORNER_CUT, 'i') or 0 return nTypeCornerCut, nUseSideMillAsBlade end --------------------------------------------------------------------- -- Classificazione della feature function WPL.Classify( Proc, b3Raw) -- se 1 faccia if Proc.Fct == 1 then -- dati della faccia local vtN = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) -- verifico se è lavorabile da sopra o di fianco return vtN:getZ() >= -0.5 -- se 2 facce elseif Proc.Fct == 2 then -- dati delle facce local vtN = {} vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT) -- verifico se è lavorabile da sopra o di fianco return ( vtN[1]:getZ() >= -0.028 or vtN[2]:getZ() >= -0.028) -- se più di 2 facce else local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId) -- se trovata faccia di fondo if nFacInd >= 0 then -- determino componente Z della normale più diretta verso il basso local dMinNz = 1 for i = 1, Proc.Fct do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT) if vtN:getZ() < dMinNz then dMinNz = vtN:getZ() end end -- dati della faccia local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- per lavorare alcune superfici che sono di poco negative controllo che la minima Z sia al di sopra del punto minimo calcolato per -- una lama da 500 local bAllowNegativeFace if vtN:getZ() < - 0.01 then if vtN:getZ() > - 0.088 and Proc.Box:getMin():getZ() - b3Raw:getMin():getZ() - (500 * abs(vtN:getZ())) >= 0 then bAllowNegativeFace = true end end -- conto le adiacenze delle facce local vAdj = {} local nFacesWithMoreThanOneAdj = 0 for i = 1, Proc.Fct do -- recupero le adiacenze del loop esterno local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.Id, i - 1)[1] -- le conto local nCount = 0 for j = 1, #vFacAdj do if vFacAdj[j] >= 0 then nCount = nCount + 1 end end vAdj[i] = nCount if nCount > 1 then nFacesWithMoreThanOneAdj = nFacesWithMoreThanOneAdj + 1 end end -- verifico se la faccia è lavorabile da sopra o di fianco if ( vtN:getZ() >= WD.NZ_MINA or ( dMinNz < -0.866 and Proc.Fct >= 3 and ( vtN:getZ() > - 0.01 or bAllowNegativeFace))) then Proc.Stype = 1 return true -- altrimenti verifico la eventuale seconda faccia elseif nFacInd2 then -- dati della faccia local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT) local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd2, GDB_ID.ROOT) -- restituisco se faccia lavorabile Proc.Stype = 2 return ( vtN2:getZ() >= WD.NZ_MINA or ( dMinNz < -0.866 and Proc.Fct >= 3 and vtN2:getZ() > - 0.01)) -- se tre facce elseif Proc.Fct == 3 and nFacesWithMoreThanOneAdj < 2 then -- verifico se U da sopra -- dati della faccia local nFac2 = EgtIf( nFacInd == 0, 1, 0) local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFac2, GDB_ID.ROOT) Proc.Stype = 3 return ( abs( ( vtN ^ vtN2) * Z_AX()) >= WD.NZ_MINA) -- altrimenti non lavorabile else return false end -- se altrimenti tunnel o assimilabile elseif nFacInd == -1 or nFacInd == -2 then -- dati delle prime tre facce local vtN = {} vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT) vtN[3] = EgtSurfTmFacetNormVersor( Proc.Id, 2, GDB_ID.ROOT) -- verifico se è lavorabile da sopra local vtAxN = vtN[1] ^ vtN[2] if vtAxN:isSmall() then vtAxN = vtN[1] ^ vtN[3] end Proc.Stype = 4 return ( abs( vtAxN:getZ()) >= WD.NZ_MINA) -- altrimenti non lavorabile else return false end end end -- funzione che verifica se faccia lavorabile da sopra local function VerifyVtN( ProcId, nFct) local nFlip0 = 0 local nFlip1 = 0 -- dati della faccia local vtN = EgtSurfTmFacetNormVersor( ProcId, nFct, GDB_ID.ROOT) local dVtNZ = vtN:getZ() -- verifico se è lavorabile da sopra nFlip0 = EgtIf( dVtNZ >= WD.NZ_MINA, 100, 0) -- verifico se e' lavorabile da fliped: cambio segno al versore nFlip1 = EgtIf( -dVtNZ >= WD.NZ_MINA, 100, 0) return nFlip0, nFlip1 end -- funzione che fa la media dei versori per assegnare punteggi flip local function VerifyVtNMedia(ProcId, nFct1, nFct2) local nFlip0 = 0 local nFlip1 = 0 -- dati delle facce local vtN = {} vtN[1] = EgtSurfTmFacetNormVersor( ProcId, nFct1, GDB_ID.ROOT) vtN[2] = EgtSurfTmFacetNormVersor( ProcId, nFct2, GDB_ID.ROOT) local dVtN1Z = vtN[1]:getZ() local dVtN2Z = vtN[2]:getZ() -- se entrambi i versori positivi if (dVtN1Z >= - 0.01 and dVtN2Z >= - 0.01) then -- posso lavorarlo da sopra nFlip0 = 100 -- se almeno un versore positivo elseif (dVtN1Z >= - 0.01 or dVtN2Z >= - 0.01) then -- calcolo media dei versori: se positiva tende verso alto local dVtNMedia = ( dVtN1Z + dVtN2Z) / 2 if dVtNMedia >= 0 - GEO.EPS_SMALL and dVtNMedia <= 0 + GEO.EPS_SMALL then nFlip0 = 100 elseif dVtNMedia >= 0 + GEO.EPS_SMALL then nFlip0 = 75 else nFlip0 = 25 end -- se entrambi i versori negativi, impossibile da fare else nFlip0 = 0 end -- verifico se e' lavorabile da fliped: cambio segno ai versori dVtN1Z = -dVtN1Z dVtN2Z = -dVtN2Z -- se entrambi i versori positivi if (dVtN1Z >= - 0.01 and dVtN2Z >= - 0.01) then -- posso lavorarlo da sopra nFlip1 = 100 -- se almeno un versore positivo elseif (dVtN1Z >= - 0.01 or dVtN2Z >= - 0.01) then -- calcolo media dei versori: se positiva tende verso alto local dVtNMedia = ( dVtN1Z + dVtN2Z) / 2 if dVtNMedia >= 0 - GEO.EPS_SMALL and dVtNMedia <= 0 + GEO.EPS_SMALL then nFlip1 = 100 elseif dVtNMedia >= 0 + GEO.EPS_SMALL then nFlip1 = 75 else nFlip1 = 25 end -- se entrambi i versori negativi, impossibile da fare else nFlip0 = 0 end return nFlip0, nFlip1 end -- Classificazione del flip della feature per nesting -- return nFlip0, nFlip1 function WPL.FlipClassify( Proc) local nFlip0 = -1 local nFlip1 = -1 -- se 1 faccia if Proc.Fct == 1 then -- verifico che la normale permetta la lavorazione da sopra ed assegno punteggio di conseguenza nFlip0, nFlip1 = VerifyVtN( Proc.Id, 0) -- se 2 facce elseif Proc.Fct == 2 then -- calcolo la media delle normali delle facce ed assegno punteggio maggiore se positiva nFlip0, nFlip1 = VerifyVtNMedia(Proc.Id, 0, 1) -- se più di 2 facce else local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId) if nFacInd == -2 then return 0, 0 end -- se 3 facce if Proc.Fct == 3 then -- se forma ad U if not nFacInd2 or nFacInd2 == 0 then -- verifico che la normale del fondo permetta la lavorazione da sopra ed assegno punteggio di conseguenza nFlip0, nFlip1 = VerifyVtN( Proc.Id, nFacInd) -- se non ad U else -- calcolo la media delle normali delle facce di fondo ed assegno punteggio maggiore se positiva nFlip0, nFlip1 = VerifyVtNMedia(Proc.Id, nFacInd, nFacInd2) end -- se 4 facce elseif Proc.Fct == 4 then -- se senza fondo (tunnel) if not nFacInd or nFacInd == -1 then -- dati delle facce local vtN = {} vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT) vtN[3] = EgtSurfTmFacetNormVersor( Proc.Id, 2, GDB_ID.ROOT) vtN[4] = EgtSurfTmFacetNormVersor( Proc.Id, 3, GDB_ID.ROOT) -- verifico se è lavorabile da sopra local vtAxN = vtN[1] ^ vtN[2] if vtAxN:isSmall() then vtAxN = vtN[1] ^ vtN[3] end if ( abs( vtAxN:getZ()) >= WD.NZ_MINA) then -- calcolo la media dei versori delle facce local dVtNMedia = ( vtN[1]:getZ() + vtN[2]:getZ() + vtN[3]:getZ() + vtN[4]:getZ()) / 4 if dVtNMedia >= 0 - GEO.EPS_SMALL and dVtNMedia <= 0 + GEO.EPS_SMALL then nFlip0 = 100 nFlip1 = 100 elseif dVtNMedia >= 0 + GEO.EPS_SMALL then nFlip0 = 75 nFlip1 = 25 else nFlip0 = 25 nFlip1 = 75 end end -- se con fondo else -- calcolo la media delle normali delle facce di fondo ed assegno punteggio maggiore se positiva local vtN = {} vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT) if vtN[1]:getZ() == -1 or vtN[2]:getZ() == -1 then return 0, 100 end if vtN[1]:getZ() == 1 or vtN[2]:getZ() == 1 then return 100, 0 end nFlip0, nFlip1 = VerifyVtNMedia(Proc.Id, nFacInd, nFacInd2) end -- se 5 facce elseif Proc.Fct == 5 then -- verifico che la normale del fondo permetta la lavorazione da sopra ed assegno punteggio di conseguenza nFlip0, nFlip1 = VerifyVtN( Proc.Id, nFacInd) end end return nFlip0, nFlip1 end --------------------------------------------------------------------- local function GetOtherRegions( nPartId) local vOthers = {} local nOtherId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL) while nOtherId do local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL) while nRegId do local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT) if EgtExistsInfo( nRegId, 'REGION') and vtN and AreSameVectorApprox( vtN, Z_AX()) then local b3Reg = EgtGetBBoxGlob( nRegId, GDB_BB.STANDARD) if b3Reg then table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg}) end end nRegId = EgtGetNext( nRegId) end nOtherId = EgtGetNextPartInRawPart( nOtherId) end return vOthers end --------------------------------------------------------------------- local function ReorderFaces( nIdSurf, nNumFacet) -- cerco una faccia senza precedenti local nFirstFac for i = 1, nNumFacet do -- centro e normale della faccia local ptCen, vtN = EgtSurfTmFacetCenter( nIdSurf, i - 1, GDB_ID.ROOT) -- verifico con le altre facce local bFoundPrec for j = 1, nNumFacet do if j ~= i then -- verifico se è precedente local bAdj, ptP1, _, _ = EgtSurfTmFacetsContact( nIdSurf, i - 1, j - 1, GDB_ID.ROOT) if bAdj and ( vtN ^ ( ptCen - ptP1)) * Z_AX() > 0 then bFoundPrec = true break end end end if not bFoundPrec then nFirstFac = i break end end -- se trovata, la metto al primo posto if nFirstFac and nFirstFac ~= 1 then EgtSurfTmSwapFacets( nIdSurf, nFirstFac - 1, 0) end -- ordino le facce in modo da avere una sequenza ordinata con le normali a destra for i = 1, nNumFacet - 1 do -- centro e normale della faccia local ptCen, vtN = EgtSurfTmFacetCenter( nIdSurf, i - 1, GDB_ID.ROOT) -- cerco la successiva for j = i + 1, nNumFacet do -- verifico se è successiva local bAdj, ptP1, _, _ = EgtSurfTmFacetsContact( nIdSurf, i - 1, j - 1, GDB_ID.ROOT) if bAdj and ( vtN ^ ( ptP1 - ptCen)) * Z_AX() > 0 then EgtSurfTmSwapFacets( nIdSurf, i, j - 1) break end end end end --------------------------------------------------------------------- local function RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFaceToDel) -- copio la superfice nel gruppo ausiliario local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL EgtSurfTmRemoveFacet( nNewProc, nFaceToDel) local nNumFacet = EgtSurfTmFacetCount( nNewProc) ReorderFaces( nNewProc, nNumFacet) return nNewProc, nNumFacet end --------------------------------------------------------------------- local function GetFacesData( nNewProc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, nPartId) local nNumFacet = EgtSurfTmFacetCount( nNewProc) local vFace = {} -- recupero i dati di tutte le facce for i = 1, nNumFacet do -- indici faccia corrente e precedente local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1) local nPrecFac if bOpposite then nPrecFac = EgtIf( i == 1, 0, nFac + 1) else nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2) end -- recupero centro e normale della faccia local ptCen, vtN = EgtSurfTmFacetCenter( nNewProc, nFac, GDB_ID.ROOT) -- recupero le dimensioni della faccia local _, dLen, dWidth = WL.GetFaceHvRefDim( nNewProc, nFac) -- recupero l'angolo con la faccia precedente local bAdj, ptLocP1, ptLocP2, dAng = EgtSurfTmFacetsContact( nNewProc, nPrecFac, nFac, GDB_ID.ROOT) -- verifico che l'adiacenza sia veramente con il precedente (percorro con normale a destra) if bAdj then if ( vtN ^ ( ptLocP1 - ptCen)) * Z_AX() > 0 then bAdj = false end end -- salvo i dati vFace[i] = { Fac = nFac, Cen = ptCen, Norm = vtN, Len = dLen, Width = dWidth, AngPrev = EgtIf( bAdj, dAng, 0)} if bAdj then if ptLocP1:getZ() < ptLocP2:getZ() then vFace[i].PPrev = ptLocP1 else vFace[i].PPrev = ptLocP2 end end end -- analizzo le facce local dMaxWidth = 0 for i = 1, #vFace do -- aggiorno la massima larghezza if vFace[i].Width > dMaxWidth then dMaxWidth = vFace[i].Width end -- verifico l'affondamento local dDepth = WD.CUT_EXTRA if vFace[i].Width + WD.CUT_EXTRA > dToolMaxDepth then dDepth = dToolMaxDepth - vFace[i].Width end -- lunghezza baffo local dElev = vFace[i].Width + dDepth local dWhisk = EgtIf( bCalclForBlade, ( dElev * sqrt( dToolDiam / dElev - 1) + WHISK_SAFE), (dToolDiam/2) + WHISK_SAFE) -- determino la lunghezza del taglio passante e il tipo di attacco e uscita local dLen = vFace[i].Len local nType = 0 if vFace[i].AngPrev < -0.1 then dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0) nType = nType + 1 end if vFace[EgtIf( i < nNumFacet, i + 1, 1)].AngPrev < -0.1 then dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0) nType = nType + 2 end -- se lunghezza non significativa, non va inserito il taglio if dLen < MIN_LEN_CUT then nType = 4 end vFace[i].Depth = dDepth vFace[i].Whisk = dWhisk vFace[i].Type = nType end -- recupero le regioni degli altri pezzi local vOthers = GetOtherRegions( nPartId) -- verifico i baffi sporgenti dei tagli rispetto alle altre regioni for i = 1, #vFace do -- verifico il baffo iniziale if vFace[i].Type ~= 4 and ( vFace[i].Type & 1) == 0 then -- creo il rettangolo del baffo local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize() local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), -90) local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, -90) local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt local ptDir = ptIni + ( vFace[i].Whisk - WHISK_OFFS) * vtDir local ptCross = ptDir + ( dToolThick - WHISK_OFFS) * vtOrt local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB) local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD) -- verifico se interferisce con gli altri pezzi for j = 1, #vOthers do if OverlapsXY( b3Wh, vOthers[j].Box) then local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0) if nClass ~= GDB_RC.OUT then local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 2) ~= 0, -vFace[i].Whisk, 0) if dLen >= MIN_LEN_CUT then vFace[i].Type = vFace[i].Type + 1 else vFace[i].Type = 4 end break end end end EgtErase( WhId) end -- verifico il baffo finale if vFace[i].Type ~= 4 and ( vFace[i].Type & 2) == 0 then -- creo il rettangolo del baffo local vtOrt = Vector3d( vFace[i].Norm:getX(), vFace[i].Norm:getY(), 0) ; vtOrt:normalize() local vtDir = Vector3d( vtOrt) ; vtDir:rotate( Z_AX(), 90) local vtUp = Vector3d( vtDir) ; vtUp:rotate( vFace[i].Norm, 90) local ptIni = vFace[i].Cen + vFace[i].Width / 2 * vtUp + ( vFace[i].Len / 2 + WHISK_OFFS) * vtDir + WHISK_OFFS * vtOrt local ptDir = ptIni + ( vFace[i].Whisk - WHISK_OFFS) * vtDir local ptCross = ptDir + ( dToolThick - WHISK_OFFS) * vtOrt local WhId = EgtSurfFrRectangle3P( nAddGrpId, ptIni, ptCross, ptDir, GDB_RT.GLOB) local b3Wh = EgtGetBBoxGlob( WhId or GDB_ID.NULL, GDB_BB.STANDARD) -- verifico se interferisce con gli altri pezzi for j = 1, #vOthers do if OverlapsXY( b3Wh, vOthers[j].Box) then local nClass = EgtSurfFrChunkSimpleClassify( WhId, 0, vOthers[j].RegId, 0) if nClass ~= GDB_RC.OUT then local dLen = vFace[i].Len - vFace[i].Whisk + EgtIf( ( vFace[i].Type & 1) ~= 0, -vFace[i].Whisk, 0) if dLen >= MIN_LEN_CUT then vFace[i].Type = vFace[i].Type + 2 else vFace[i].Type = 4 end break end end end EgtErase( WhId) end end -- eventuali stampe for i = 1, #vFace do local Face = vFace[i] local sOut = 'Face '..tostring( Face.Fac)..' C'..tostring( Face.Cen)..' N'..tostring( Face.Norm).. ' L='..EgtNumToString( Face.Len, 1)..' W='..EgtNumToString( Face.Width, 1)..' Ap='..EgtNumToString( Face.AngPrev, 1).. ' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1)..' T='..tostring( Face.Type) EgtOutLog( sOut, 3) end return vFace, dMaxWidth, nNewProc end --------------------------------------------------------------------- local function GetTunnelDimension( nId, nPartId, nAddGrpId) -- ottengo i versori delle 4 facce e ottengo l'orientamento del tunnel -- recupero il numero di facce local nFacCnt = EgtSurfTmFacetCount( nId) -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- variabili dimensioni fessura e id faccia lunga local dDimMin local dDimMax local nLongIdFace = 0 local bNegFace local bOppoFace = false -- ottengo il versore ortogonale local ptN1, vtN1 = EgtSurfTmFacetCenter( nId, 0, GDB_ID.ROOT) local _, vtN2 = EgtSurfTmFacetCenter( nId, 1, GDB_ID.ROOT) local vtOrtho = vtN1 ^ vtN2 if vtOrtho:isSmall() then if nFacCnt >= 3 then _, vtN2 = EgtSurfTmFacetCenter( nId, 2, GDB_ID.ROOT) vtOrtho = vtN1 ^ vtN2 bOppoFace = true else return end end if vtOrtho:getZ() < -0.5 then vtOrtho = -vtOrtho bNegFace = true end -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta la profondità della fessura local frFc = Frame3d( ptN1, vtOrtho) ; local bBoxLoc = EgtGetBBoxRef( nId, GDB_BB.STANDARD, frFc) local dDepth = bBoxLoc:getDimZ() -- mi assicuro che la Z del punto utilizzato per creare la superficie sia alla Z inferiore del bounding box locale local ptN2 = Point3d(ptN1) ptN2:toLoc(frFc) ptN2 = Point3d( ptN2:getX(), ptN2:getY(), bBoxLoc:getMin():getZ() + 2*GEO.EPS_SMALL) ptN2:toGlob(frFc) -- creo superficie intermedia local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptN2, vtOrtho, b3Solid, GDB_ID.ROOT) -- ritaglio la superficie con le facce della fessura for i = 1, nFacCnt do local ptN, vtN = EgtSurfTmFacetCenter( nId, i - 1, GDB_ID.ROOT) EgtCutSurfTmPlane( nSurfInt, ptN, -vtN, false, GDB_ID.ROOT) end -- sposto la geometria trovata sulla Z minima (era su di 2 * GEO.EPS_SMALL) EgtMove( nSurfInt, Point3d(0,0,-2*GEO.EPS_SMALL) - ORIG(), GDB_RT.GLOB) -- mi faccio dare il contorno della superfice e la ricreo in modo più corretto local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) -- elimino le entità allineate dello stesso tipo EgtMergeCurvesInCurveCompo( nIdCont, 2*GEO.EPS_SMALL) EgtErase(nSurfInt) nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2*GEO.EPS_SMALL) -- elimino il contorno EgtErase(nIdCont) -- se normale negativa inverto _, vtN1 = EgtSurfTmFacetCenter( nSurfInt, 0, GDB_ID.ROOT) if vtN1:getZ() < -0.5 then EgtInvertSurf( nSurfInt) end local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) dDimMin = min( DimH, DimV) dDimMax = max( DimH, DimV) _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFacCnt-1, GDB_ID.ROOT) -- se faccia pari alla larghezza fessura if abs(DimH - dDimMax) < GEO.EPS_SMALL or abs(DimV - dDimMax) < GEO.EPS_SMALL then nLongIdFace = nFacCnt-1 -- altrimenti verifico anche con la faccia precedente else local nFaceToCheck = EgtIf( bOppoFace, nFacCnt-3, nFacCnt-2) -- prendo le dimensioni della faccia e poi confronto con il minimo _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, nFaceToCheck, GDB_ID.ROOT) -- se trovato con il minimo, questa seconda faccia non è la più lunga if abs(DimH - dDimMin) < GEO.EPS_SMALL or abs(DimV - dDimMin) < GEO.EPS_SMALL then nLongIdFace = nFacCnt-1 else nLongIdFace = nFaceToCheck end end if not dDimMax then return dDimMin, dDimMax, dDepth, nil, nil end return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt end --------------------------------------------------------------------- local function ReorderFacesFromTab( nIdSurf, vFace) local nFacCnt = EgtSurfTmFacetCount( nIdSurf) for i = 1, #vFace do for j = 1, nFacCnt do -- ottengo punto iniziale e versore della faccia local ptC, vtN = EgtSurfTmFacetCenter( nIdSurf, (j-1), GDB_ID.ROOT) -- se versore e posizione coincidono e non corrispondono al numero faccia, faccio lo swap if AreSameVectorExact( vFace[i].Norm, vtN) and AreSamePointEpsilon( vFace[i].Cen, ptC, 50*GEO.EPS_SMALL) then if j - 1 ~= vFace[i].Fac then EgtSurfTmSwapFacets( nIdSurf, vFace[i].Fac, (j-1)) end break end end end return nIdSurf end --------------------------------------------------------------------- local function CalcInterference( nNewProc, vtExtr, ptCentr, dDiam1, dDiam2, dTall1, dTall2, dDiam3, dTall3) local ptCentrGrid1 = ptCentr + ( vtExtr * 0.01) local frOriTool = Frame3d( ptCentrGrid1, vtExtr) local bColl1 = EgtCDeConeSolid( frOriTool, dDiam1/2, dDiam2/2, dTall1, nNewProc, 0, GDB_RT.GLOB) if bColl1 then return true end local ptCentrGrid2 = ptCentr + ( vtExtr * ( dTall1 + 0.01)) frOriTool = Frame3d( ptCentrGrid2, vtExtr) local bColl2 = EgtCDeCylSolid( frOriTool, dDiam2/2, (dTall2-dTall1), nNewProc, 0, GDB_RT.GLOB) if bColl2 then return true end local ptCentrGrid3 = ptCentr + ( vtExtr * ( dTall2 + 0.01)) frOriTool = Frame3d( ptCentrGrid3, vtExtr) local bColl3 = EgtCDeCylSolid( frOriTool, dDiam3/2, (dTall3-dTall2), nNewProc, 0, GDB_RT.GLOB) if bColl3 then return true end -- restituisco risultato controllo collisioni return false end --------------------------------------------------------------------- local function MakeLocalSurf( ptP1, ptP2, ptP3, nAddGrpId) if not ptP1 or not ptP2 or not ptP3 then return nil end local pAuxId = {} local nAuxId, AuxId nAuxId = EgtLine( nAddGrpId, ptP1, ptP2, GDB_RT.GLOB) table.insert( pAuxId, nAuxId) nAuxId = EgtLine( nAddGrpId, ptP2, ptP3, GDB_RT.GLOB) table.insert( pAuxId, nAuxId) nAuxId = EgtLine( nAddGrpId, ptP3, ptP1, GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- trasformo in percorso if #pAuxId ~= 3 then return nil end AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true) -- se non c'é il percorso esco if not AuxId then return nil end -- creo la superfice piana local nidFace = EgtSurfTmByFlatContour( nAddGrpId, AuxId, 0.01) if not nidFace then EgtErase(AuxId) return nil end -- se normale negativa inverto local _, vtN1 = EgtSurfTmFacetCenter( nidFace, 0, GDB_ID.ROOT) if vtN1:getZ() < -0.5 then EgtInvertSurf( nidFace) end EgtErase(AuxId) return nidFace end --------------------------------------------------------------------- local function AddMillCornerMachining( nPartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, dOffsAng, dDepthMach, bThruThick, dThSurf, dDiam1, dDiam2, dTall1, dTall2, dDiam3, dTall3, bMakeLocSurf, vFace) -- variabili costruzione geometria local pAuxId = {} local nAuxId local ptApPoint local AuxId local nNewProcLoc -- se devo creare superfice locale if bMakeLocSurf then -- creo superfice locale o esco local nSurfToAdd = MakeLocalSurf( tFacAdj[7], tFacAdj[8], tFacAdj[9], nAddGrpId) if nSurfToAdd then local nFacCntPre = EgtSurfTmFacetCount( nNewProc) -- creo copia del percorso principale e gli aggiungo la nuova faccia nNewProcLoc = EgtCopyGlob( nNewProc, nAddGrpId) nNewProcLoc = EgtSurfTmBySewing( nAddGrpId, {nNewProcLoc,nSurfToAdd} , true) -- riordino le facce nNewProcLoc = ReorderFacesFromTab( nNewProcLoc, vFace) -- acquisisco il numero della faccia local nFacCnt = EgtSurfTmFacetCount( nNewProcLoc) nFacInd = nFacCnt - 1 else local sErr = 'Cannot make local bottom surface' EgtOutLog( sErr) return true, '' end else nNewProcLoc = nNewProc end -- prendo il primo versore local _, vtN1 = EgtSurfTmFacetCenter( nNewProcLoc, nFacInd, GDB_ID.ROOT) local _, vtN2 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[1], GDB_ID.ROOT) local _, vtN3 = EgtSurfTmFacetCenter( nNewProcLoc, tFacAdj[2], GDB_ID.ROOT) -- trovo il punto sulla superfice di riferimento local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[1], GDB_ID.ROOT) local _, ptLocP3, ptLocP4, _ = EgtSurfTmFacetsContact( nNewProcLoc, nFacInd, tFacAdj[2], GDB_ID.ROOT) -- se ho creato faccia locale su copia superficie, cancella la copia if bMakeLocSurf then EgtErase( nNewProcLoc) end local nIdIniPoint local nIdEndPoint if ptLocP1 and ptLocP2 then if ( dist( ptLocP1, tFacAdj[4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[4]) < GEO.EPS_SMALL) then nIdEndPoint = 4 nIdIniPoint = 5 elseif ( dist( ptLocP1, tFacAdj[5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[5]) < GEO.EPS_SMALL) then nIdEndPoint = 5 nIdIniPoint = 4 end end -- versore direzione local vtExtr = tFacAdj[nIdIniPoint] - tFacAdj[nIdEndPoint] vtExtr:normalize() -- versore direzione di uscita local vtExtrExit -- inserisco le prime tre linee if nIdIniPoint and nIdEndPoint then -- se fresatura da sotto salto la lavorazione if vtExtr:getZ() < WD.DRILL_VZ_MIN then local sErr = 'Error : Impossible insert clean corner from bottom' EgtOutLog( sErr) return false, sErr end -- sommo i tre versori per avere una direzione media vtExtrExit = vtN2 + vtN3 vtExtrExit:normalize() -- se tipo 1 calcolo angolo tilt di 45° if nTypeConeCut == 1 then vtExtr = vtExtrExit + Z_AX() -- altrimenti tipo 2, calcolo angolo tilt di 33° (dalla verticale) else vtExtr = vtExtrExit + Vector3d(0,0,1.539865) end vtExtr:normalize() local vtCheck = Vector3d(vtExtr) -- se ho un offset angolare ruoto il percorso if abs(dOffsAng) > 100 * GEO.EPS_SMALL then vtCheck:rotate( Z_AX(), dOffsAng) end -- controllo se c'è collisione con le facce della superfice if nTypeConeCut == 1 and CalcInterference( nNewProc, vtCheck, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), dDiam1, dDiam2, dTall1, dTall2, dDiam3, dTall3) then local sErr = 'Collision detect from clean corner tool and surface' EgtOutLog( sErr) return true, '' end nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdIniPoint], tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- se uso utensile cono 60° if nTypeConeCut == 1 then -- se offset angolare valido e/o negativo creo il baffo precedente if dOffsAng < ( 100 * GEO.EPS_SMALL) then -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro if dist( tFacAdj[nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then ptApPoint = ptLocP2 else ptApPoint = ptLocP1 end nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) local dLenTrimExt = dist( tFacAdj[nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.2) -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta if dLenTrimExt > 10 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata if abs(dOffsAng) > 100 * GEO.EPS_SMALL then EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB) end -- prendo il nuovo punto finale ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach) else -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata if abs(dOffsAng) > 100 * GEO.EPS_SMALL then EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB) end end table.insert( pAuxId, nAuxId) -- creo linea di ritorno nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end end end -- inserisco le ultime tre linee -- trovo il secondo punto sulla superfice di riferimento ptLocP1, ptLocP2 = ptLocP3, ptLocP4 if ptLocP1 and ptLocP2 then -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro if dist( tFacAdj[nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then ptApPoint = ptLocP2 else ptApPoint = ptLocP1 end -- se uso utensile cono 60° if nTypeConeCut == 1 then -- se offset angolare valido e/o negativo creo il baffo precedente if dOffsAng > -( 100 * GEO.EPS_SMALL) then nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) local dLenTrimExt = dist( tFacAdj[nIdEndPoint], ptApPoint) - (( dToolDiam/2) + 0.2) -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta if dLenTrimExt > 10 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata if abs(dOffsAng) > 100 * GEO.EPS_SMALL then EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB) end -- prendo il nuovo punto finale ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) + Point3d( 0, 0, dDepthMach) else -- se ho l'offset angolare ruoto la linea per compensare la rotazione che verrà applicata if abs(dOffsAng) > 100 * GEO.EPS_SMALL then EgtRotate( nAuxId, tFacAdj[nIdEndPoint], Z_AX(), -dOffsAng, GDB_RT.GLOB) end end table.insert( pAuxId, nAuxId) -- creo linea di ritorno nAuxId = EgtLine( nAddGrpId, ptApPoint + Point3d( 0, 0, -dDepthMach), tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end -- ultima linea di distacco (5mm in direzione utensile) local pEnd = tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach) + ( 5 * vtExtr) nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint] + Point3d( 0, 0, -dDepthMach), pEnd, GDB_RT.GLOB) table.insert( pAuxId, nAuxId) else -- linea di distacco (2mm in direzione utensile) local pEnd = tFacAdj[nIdEndPoint] + ( 2 * vtExtr) nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdEndPoint], pEnd, GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- ultima linea di risalita in Z local pIni = pEnd pEnd = pIni + ( dThick * Z_AX()) nAuxId = EgtLine( nAddGrpId, pIni, pEnd, GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end end -- trasformo in percorso if #pAuxId > 0 then AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true) end -- se non c'é il percorso do errore if not AuxId then local sErr = 'Error : impossible make clean corner path' EgtOutLog( sErr) return false, sErr end -- modifico versore direzione EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB) -- se ho un offset angolare ruoto il percorso if abs(dOffsAng) > 100 * GEO.EPS_SMALL then EgtRotate( AuxId, tFacAdj[nIdEndPoint], Z_AX(), dOffsAng, GDB_RT.GLOB) end -- inserisco la lavorazione local sName = 'Clean_' .. ( EgtGetName( nNewProc) or tostring( nNewProc)) local nMchId = WM.AddMachining( nNewProc, sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchId, 'Part', nPartId) -- se flag lavorazione spessore passante setto la nota per spostarla dopo i tagli di lama if bThruThick and nTypeConeCut == 1 then EgtSetInfo( nMchId, 'MOVE_AFTER', 1) end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP EgtSetMachiningParam( MCH_MP.SCC, nSCC) EgtSetMachiningParam( MCH_MP.LEADINTYPE, 0) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 4) -- allungo inizio e fine di 10mm EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10) -- setto affondamento 0 EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- forzo lato correzione a centrato EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) -- leggo eventuali note esistenti della lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0) -- aggiungo alle note massima elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( 0.0, 1)) -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr else local _, sWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) return false, sWarn end end return true, '' end --------------------------------------------------------------------- local function AddMillCorner( nTypeConeCut, vFace, Proc, nRawId, b3Raw, dToolDiam, nAddGrpId, dThick, nMasterNewProc, dDepthMach, bThruThick) local sMilling, dMaxDepth -- se ripresa angolo con fresa cono 60° con ripresa if nTypeConeCut == 1 then -- recupero la lavorazione di fresatura sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner60') if not sMilling then local sErr = 'Error : CleanCorner 60 not found in library' EgtOutLog( sErr) return false, sErr end -- se ripresa angolo con fresa cono piccola senza ripresa else sMilling, dMaxDepth = WM.FindMilling( 'CleanCorner30') if not sMilling then local sErr = 'Error : CleanCorner 30 not found in library' EgtOutLog( sErr) return false, sErr end end -- recupero i dati dell'utensile local dMillDiam = 20 local dMillTotDiam = 20 local dMillDiamTh = 20 local dToolLength = 20 local dThickTool = 20 local dSideAng = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh dMillTotDiam = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) or dMillTotDiam dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or dSideAng dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dThickTool = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dThickTool dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth -- qui è la distanza dal portautensile -- calcolo il secondo diametro del cono dMillTotDiam = dMillDiam + ( abs(dThickTool) * tan(dSideAng)) * 2 end end -- copio la feature nel layer di appoggio local nNewProc if nMasterNewProc then nNewProc = nMasterNewProc else nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL end local nFacCnt = EgtSurfTmFacetCount( nNewProc) local nFacInd, dDimMin, dDimMax, dDepth, nSurfInt local bMakeLocSurf -- RIMUOVERE if false and nFacCnt <= 4 then -- ottengo le dimensioni apertura, la normale e la faccia inferiore dDimMin, dDimMax, dDepth, _, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId) if nSurfInt then -- uso la dimensione minima anche nel caso che la cava sborda perchè la lavorazione potrebbe collidere con un pezzo limitrofo local dMinWidth = dDimMin nNewProc = EgtSurfTmBySewing( nAddGrpId, {nNewProc,nSurfInt} , true) -- riordino le facce nNewProc = ReorderFacesFromTab( nNewProc, vFace) -- acquisisco il numero della faccia nFacCnt = EgtSurfTmFacetCount( nNewProc) nFacInd = nFacCnt - 1 else local sErr = 'Error : cannot create base surface' EgtOutLog( sErr) return false, sErr end -- FINE PARTE DA RIMUOVERE else bMakeLocSurf = true end -- verifico se ciclo chiuso local bClosed = ( abs( vFace[1].AngPrev) > 0.1) -- ciclo di inserimento delle fresate sulle facce del contorno in esame local i = 1 -- se faccia finale con fine non lavorato, forzo partenza da prima faccia non tutta saltata (tipo 4) if bClosed and ( vFace[#vFace].Type == 4 or ( vFace[#vFace].Type & 2) ~= 0) then while i <= #vFace and vFace[i].Type == 4 do i = i + 1 end end -- se facce tutte da saltare, parto dall'inizio local bAllType4 = ( i > #vFace) if bAllType4 or bClosed then i = 1 end while i <= #vFace do -- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura if ( vFace[i].Type & 2) ~= 0 or vFace[i].Type == 4 then -- variabili costruzione geometria (nFace1, nFace2, tFacAdj) local nFace1 = vFace[i].Fac -- ricavo i tre punti per eventuale superficie locale local ptLoc1, ptLoc2, ptLoc3 -- aggiungo geometria local j = EgtIf( i < #vFace, i + 1, EgtIf( bClosed, 1, nil)) if not j then return true end local nFace2 = vFace[j].Fac -- punto in comune tra le due facce (punto precedente della faccia [j]) ptLoc1 = vFace[j].PPrev -- punto precedente (punto precedente della faccia [i]) if vFace[i].PPrev then ptLoc3 = vFace[i].PPrev else ptLoc3 = Point3d( vFace[i].Cen:getX(), vFace[i].Cen:getY(), ptLoc1:getZ()) end -- punto successivo ( precedente della faccia successiva) local k = EgtIf( j < #vFace, j + 1, EgtIf( bClosed, 1, nil)) -- se è un percorso aperto prendo il punto medio della seconda faccia come punto locale 2 if not k then ptLoc2 = Point3d( vFace[j].Cen:getX(), vFace[j].Cen:getY(), ptLoc1:getZ()) else ptLoc2 = vFace[k].PPrev end -- ricavo i punti e l'angolo interno local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( nNewProc, nFace1, nFace2, GDB_ID.ROOT) -- se punti validi e angolo è interno e non è quasi piatto e >= 90 creo istanza local tFacAdj = {} if ptP1 and ptP2 and dAng < 0 and dAng < -6 and dAng > EgtIf( nTypeConeCut == 1, -(90 + 10 * GEO.EPS_SMALL), -(180-dAngleSmall + 10 * GEO.EPS_SMALL)) then local dLen = dist( ptP1, ptP2) tFacAdj = { nFace1, nFace2, dLen, ptP1, ptP2, dAng, ptLoc1, ptLoc2, ptLoc3} end -- se ho un elemento creo percorso o percorsi in base al tipo di cono e all'apertura dall'angolo rispetto ai 90° -- con una tolleranza di 2 gradi if #tFacAdj > 0 then if nTypeConeCut == 1 and bMakeTwinCut and (dAng + 90) > 2 then local dAngOffs = (dAng + 90) / 2 -- primo taglio local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, -dAngOffs, dDepthMach, bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool), dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace) if not bOk then return bOk, sErr end -- secondo taglio bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, dAngOffs, dDepthMach, bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool), dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace) if not bOk then return bOk, sErr end -- altrimenti ho un solo percorso else local bOk, sErr = AddMillCornerMachining( Proc.PartId, nNewProc, nFacInd, tFacAdj, nTypeConeCut, nAddGrpId, dToolDiam, dThick, sMilling, 0, dDepthMach, bThruThick, dDepth, dMillDiam, dMillTotDiam, abs(dThickTool), dMaxDepth, dMillDiamTh, dToolLength, bMakeLocSurf, vFace) if not bOk then return bOk, sErr end end end end -- passo alla successiva i = i + 1 end -- cancello la copia della superfice if nNewProc then EgtErase(nNewProc) end return true end --------------------------------------------------------------------- local function MakeByChainSaw( Proc, nFacet, nRawId, b3Raw, dElev, dH, dV) local sWarn -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) -- Recupero le facce adiacenti alla principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacet)[1] if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' EgtOutLog( sErr) return false, sErr end EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3) -- Cerco una faccia adiacente alla principale sul lato più lungo local nFacAdj local dMaxLen = 0 for i = 1, #vAdj do if vAdj[i] >= 0 then local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacet, vAdj[i], GDB_ID.ROOT) local dLen = dist( ptP1, ptP2) local vtAdjN = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT) if dLen > dMaxLen - 1 and vtAdjN:getZ() > -0.1 then nFacAdj = vAdj[i] dMaxLen = dLen EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 3) end end end if not nFacAdj then local sErr = 'Error : long adjacent face not found' EgtOutLog( sErr) return false, sErr end -- Recupero la lavorazione local sSawing = WM.FindSawing( 'Sawing') if not sSawing then local sErr = 'Error : chainsawing not found in library' EgtOutLog( sErr) return false, sErr, 'MNF' end -- Recupero i dati dell'utensile local dSawWidth = 75 local dSawThick = 8 local dMaxDepth = 200 if EgtMdbSetCurrMachining( sSawing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawWidth = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawWidth dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end if dSawThick > dV + 10 * GEO.EPS_SMALL then local sErr = 'Error : chainsaw too thick' EgtOutLog( sErr) return false, sErr end -- Calcolo uso faccia local nFaceUse = WL.GetNearestParalOpposite( vtN) -- Calcolo angolo 3° asse rot (da direz. utensile) local sRot3Ang = 'A1=180' if WD.GetChainSawBlockedAxis then sRot3Ang = WD.GetChainSawBlockedAxis( 1) end -- Calcolo angoli iniziali suggeriti local sStartAngs if WD.GetChainSawStartAngs then local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT) sStartAngs = WD.GetChainSawStartAngs( vtN2) end -- Lati chiusi local bOpenStart = false local bOpenEnd = false -- Verifico se necessarie più passate local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dV - dSawThick) / ( nStep - 1) end for i = 1, nStep do -- Applico la lavorazione con sega a catena a questa faccia local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = WM.AddMachining( Proc, sName, sSawing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchFId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto accorciamento iniziale/finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2)) -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang) -- imposto angoli iniziali suggeriti if sStartAngs then EgtSetMachiningParam( MCH_MP.INITANGS, sStartAngs) end -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se necessario, limito l'affondamento if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' local dDepth = dMaxDepth - dElev EgtOutLog( sWarn) EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH '..EgtNumToString( dDepth, 1)) end -- leggo eventuali note esistenti della lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- imposto elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dElev, 2)) -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr elseif EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end return true end --------------------------------------------------------------------- -- restituisce true se la lavorazione potrebbe danneggiare le parti limitrofe local function IsMachiningDamagingOtherParts( Proc, dMillDiameter, nRawId) local bIsMachiningDamagingOtherParts = false -- box da estendere in tutte le direzioni, compreso angolo cieco local b3ProcExtended = EgtGetBBoxGlob( Proc.Id, GDB_BB.STANDARD) -- punto minimo e massimo assoluti del box local ptMin = b3ProcExtended:getMin() local ptMax = b3ProcExtended:getMax() -- estensione aggiunta ai box local dBoxExtensionLength = dMillDiameter / 2 + 5 -- check box verso X- if Proc.AffectedFaces.Left then local vtMove = Vector3d( -dBoxExtensionLength, 0, 0) ptMin:move( vtMove) end -- check box verso X+ if Proc.AffectedFaces.Right then local vtMove = Vector3d( dBoxExtensionLength, 0, 0) ptMax:move( vtMove) end -- check box verso Y- if Proc.AffectedFaces.Front then local vtMove = Vector3d( 0, -dBoxExtensionLength, 0) ptMin:move( vtMove) end -- check box verso Y+ if Proc.AffectedFaces.Back then local vtMove = Vector3d( 0, dBoxExtensionLength, 0) ptMax:move( vtMove) end -- estendo il box in direzione X e Y e verifico se interseca altre parti b3ProcExtended:Add( ptMin) b3ProcExtended:Add( ptMax) local nPartId = EgtGetFirstPartInRawPart( nRawId) while nPartId do local nBoxSolidId = EgtGetFirstNameInGroup( nPartId, 'Box') local b3Solid = EgtGetBBoxGlob( nBoxSolidId or GDB_ID.NULL, GDB_BB.STANDARD) b3Solid:expand( - 10 * GEO.EPS_SMALL) if ( nPartId ~= Proc.PartId) and OverlapsXY( b3ProcExtended, b3Solid) then bIsMachiningDamagingOtherParts = true end nPartId = EgtGetNextPartInRawPart( nPartId) end return bIsMachiningDamagingOtherParts end --------------------------------------------------------------------- local function MakeByMill( Proc, nFacet, nOthFac, nRawId, b3Raw, dSideDist) -- dati della faccia e dell'altra local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) local dDiam = min( dH, dV) local _, vtRef = EgtSurfTmFacetCenter( Proc.Id, nOthFac, GDB_ID.ROOT) -- recupero la lavorazione local sMilling = WM.FindMilling( 'Side') if Proc.Double and Proc.Double == 2 then local sMillingBackup = sMilling sMilling = WM.FindMilling( 'Side', nil, nil, nil, nil, nil, nil, nil, 'H1') if not WM.IsMachiningOkForDouble( sMilling) then Proc.Double = 0 sMilling = sMillingBackup end end if not sMilling then local sErr = 'Error : Side not found in library' EgtOutLog( sErr) return false, sErr, true end -- recupero i dati dell'utensile local dMillDiam = 20 local dMillLen = 10 local dMillTotLen = 30 local dMaxDepth = 0 local dThDiam = 100 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMillLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLen dMillTotLen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dMillTotLen dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam end end if dMillDiam < dDiam or dMaxDepth < dElev then local sErr = 'Error : Side Elevation too big' EgtOutLog( sErr) return false, sErr end local dMillExtra = dMillTotLen - dMillLen if Proc.Box:getMin():getZ() - dMillExtra < b3Raw:getMin():getZ() - 10 * GEO.EPS_SMALL then local sErr = 'Error : Tool collide with table' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di contornatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = WM.AddMachining( Proc, sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchFId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacet}}) -- sistemo i parametri di attacco e uscita local dAddLen = ( WD.MID_GAP or 50) - ( WD.MID_SIC or 5) EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) -- -dMillDiam/2 + dAddLen) EgtSetMachiningParam( MCH_MP.LITANG, 0) EgtSetMachiningParam( MCH_MP.LIPERP, dSideDist + WD.CUT_SIC) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) -- -dMillDiam/2 + dAddLen) EgtSetMachiningParam( MCH_MP.LOTANG, 0) EgtSetMachiningParam( MCH_MP.LOPERP, dSideDist + WD.CUT_SIC) -- setto inversione in base al workside local bIsWorkSideRight = ( EgtGetMachiningParam( MCH_MP.WORKSIDE) == MCH_MILL_WS.RIGHT) local bInvert = false if bIsWorkSideRight then bInvert = true end EgtSetMachiningParam( MCH_MP.INVERT, bInvert) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if AreSameOrOppositeVectorApprox( vtN, Z_AX()) then nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XM) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto modo di lavorare la faccia local nFaceUse = WL.GetNearestOrthoOpposite( vtRef, vtN) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- leggo eventuali note esistenti della lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- se lavorazione in doppio aggiungo le rispettive note if Proc.Double and Proc.Double == 2 then sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ) end -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end return true end --------------------------------------------------------------------- local function MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, sCustomMach, dMaxDepthOnSide, bEnablePreMill, bMachFromDn, dAng, bAsEnablePreMill, nSinglePass, bExcludeFinishing, bDoubleCustomMach) local sWarn -- dati della faccia principale (la più verticale) local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) -- dati della faccia più orizzontale local nOtherFacet local dMinZ = 1 for i = 1, Proc.Fct do local dCurrentZ = Proc.Face[i].VtN:getZ() if dCurrentZ < dMinZ then nOtherFacet = Proc.Face[i].Id dMinZ = dCurrentZ end end local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFacet, GDB_ID.ROOT) local dElevOtherFacet = WL.GetFaceElevation( Proc.Id, nOtherFacet, nRawId) -- se lap joint 2 facce dal basso e angolo negativo local bExcludeSideMill = Proc.Fct == 2 and vtN:getZ() < -0.01 and vtN2:getZ() < -0.01 -- dimensioni della faccia principale local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) local dThick = min( dH, dV) local frFace = Frame3d( ptC, vtN) local b3Proc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFace) local dSideElev = b3Proc:getDimZ() local sMilling -- se ho lavorazione custom if sCustomMach then sMilling = sCustomMach -- se avevo stabilito che la customMach non era adatta al double, setto per non specchiare if not bDoubleCustomMach then Proc.Double = 0 end -- altrimenti la cerco else sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV)) -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata if Proc.Double and Proc.Double == 2 then local sMillOnSideBackup = sMilling sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, nil, 'H1') if not WM.IsMachiningOkForDouble( sMilling) then Proc.Double = 0 sMilling = sMillOnSideBackup end end end if not sMilling then local sErr = 'Error : SideGroove not found in library' EgtOutLog( sErr) return false, sErr end local dGrooveMinZ = max( b3Raw:getMin():getZ(), Proc.Box:getMin():getZ()) local dRawMaxZ = b3Raw:getMax():getZ() -- recupero i dati dell'utensile local dMillDiam = 20 local dMillLen = 10 local dMillTotLen = 30 local dMaxMat = 0 local dMillDiamTh = 999 local dMillDiamThStem = 0 local dMillLenTh = 0 local dSideStep = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMillLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLen dMillTotLen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) or dMillTotLen -- di default uso il diametro "alto" del portautensile come diametro del gambo dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh dMillDiamThStem = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or dMillDiamThStem dMillLenTh = EgtTdbGetCurrToolThLength() or dMillLenTh dSideStep = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDESTEP', 'd') or dSideStep if ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE) ~= 0 then dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dMaxMat if not dMaxDepthOnSide or dMaxDepthOnSide < 0.1 then dMaxDepthOnSide = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) end else dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat if not dMaxDepthOnSide or dMaxDepthOnSide < 0.1 then dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') end end -- se riesco a lavorare il sottosquadro senza arrivare alla parte larga del portautensile uso la sidedepth o il diametro stretto del portautensile come diametro del gambo if ( dMillTotLen - dMillLenTh) > ( abs( dRawMaxZ - dGrooveMinZ) + 1) then if dMaxDepthOnSide and dMaxDepthOnSide > 0 then dMillDiamTh = dMillDiam - dMaxDepthOnSide * 2 elseif dMillDiamThStem > 0 then dMillDiamTh = dMillDiamThStem end end end end -- se profondità ribasso è maggiore della capacità di sottosquadro dell'utensile if ( dElev > 0.5 * ( dMillDiam - dMillDiamTh) - 10 * GEO.EPS_SMALL) then if ( not bEnablePreMill and ( bMachFromDn or Proc.Fct > 2)) then local sErr = 'Error : Side Elevation (' .. dElev .. ') bigger than max tool side depth (' .. ( 0.5 * ( dMillDiam - dMillDiamTh)) ..')' EgtOutLog( sErr) return false, sErr elseif Proc.Double then Proc.Double = 0 end end local dMillExtra = dMillTotLen - dMillLen if Proc.Box:getMin():getZ() - dMillExtra < b3Raw:getMin():getZ() - 10 * GEO.EPS_SMALL then local sErr = 'Error : Tool collide with table' EgtOutLog( sErr) return false, sErr end if Proc.Fct == 2 and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + 100 * GEO.EPS_SMALL and dMaxMat > dThick + 10 * GEO.EPS_SMALL then local sErr = 'Error : Tool thickness is too big' EgtOutLog( sErr) return false, sErr end -- dimensioni della testa local dHeadMaxWidth = 250 local dHeadMinWidth = 160 local dHeadMinWidthHeight = 30 -- se la testa scende sotto al limite superiore del grezzo e non c'è sufficiente capacità di sottosquadro -- controllo disattivato se move after if WD.SIDEMILL_BEFORE and not ( bEnablePreMill or bAsEnablePreMill) and ( ( dMillTotLen < ( abs( dRawMaxZ - dGrooveMinZ) + 10 * GEO.EPS_SMALL) and ( dElev > 0.5 * ( dMillDiam - dHeadMinWidth) - 10 * GEO.EPS_SMALL)) or ( dMillTotLen + dHeadMinWidthHeight < ( abs( dRawMaxZ - dGrooveMinZ) + 10 * GEO.EPS_SMALL) and ( dElev > 0.5 * ( dMillDiam - dHeadMaxWidth) - 10 * GEO.EPS_SMALL))) then local sErr = 'Error : Tool too short, head will collide with rawpart' EgtOutLog( sErr) return false, sErr end -- verifico che la lavorazione sia passante dal grezzo local dLongGorge = max( dH, dV) local dExtraLongExtPlus = 0 local dExtraLongExtNeg = 0 local dExtraLongIni = 0 local dExtraLongEnd = 0 local bStartPos local bInvertMach local nModifyLeadInOut = 0 local nFace2ndFace local dMaxDistToOut = EgtIf( bMachFromDn, 1800, 300) -- se orientato lungo la Y if abs( vtN:getX()) > 0.866 then dExtraLongExtPlus = abs( Proc.Box:getMax():getY() - b3Raw:getMax():getY()) dExtraLongExtNeg = abs( Proc.Box:getMin():getY() - b3Raw:getMin():getY()) if dLongGorge + dMillDiamTh < b3Raw:getDimY() then nModifyLeadInOut = 1 -- se non può sbordare da nessuna parte do errore if dExtraLongExtPlus > dMaxDistToOut and dExtraLongExtNeg > dMaxDistToOut and dElev > dMaxDistToOut then local sErr = 'Error : Not possible insert SideMill groove machining' EgtOutLog( sErr) return false, sErr end -- se non sborda solo dai lati if dElev < dExtraLongExtPlus and dElev < dExtraLongExtNeg then nModifyLeadInOut = 2 end end -- se la distanza superiore è minore della distanza inferiore segno di partire dalla parte positiva if dExtraLongExtPlus < dExtraLongExtNeg then bStartPos = true end -- se normale su X positivo parte dall'alto if vtN:getX() > 0.866 then -- se deve partire dalla parte negativa setto il flag di inversione lavorazione if not bStartPos then bInvertMach = true dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5) else dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5) end -- asseggno lato di lavoro seconda faccia if bMachFromDn then nFace2ndFace = MCH_MILL_FU.ORTUP_LEFT else nFace2ndFace = MCH_MILL_FU.ORTHO_LEFT end -- altrimenti normale su X negativa parte dal basso else -- se deve partire dalla parte positiva setto il flag di inversione lavorazione if bStartPos then bInvertMach = true dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5) else dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5) end -- asseggno lato di lavoro seconda faccia if bMachFromDn then nFace2ndFace = MCH_MILL_FU.ORTUP_RIGHT else nFace2ndFace = MCH_MILL_FU.ORTHO_RIGHT end end -- altrimenti orientato lungo la X elseif abs( vtN:getY()) > 0.866 then dExtraLongExtPlus = abs( Proc.Box:getMax():getX() - b3Raw:getMax():getX()) dExtraLongExtNeg = abs( Proc.Box:getMin():getX() - b3Raw:getMin():getX()) if dLongGorge + dMillDiamTh < b3Raw:getDimX() then nModifyLeadInOut = 1 -- se non può sbordare da nessuna parte do errore if dExtraLongExtPlus > dMaxDistToOut and dExtraLongExtNeg > dMaxDistToOut and dElev > dMaxDistToOut then local sErr = 'Error : Not possible insert SideMill groove machining' EgtOutLog( sErr) return false, sErr end -- se non sborda solo dai lati if dElev < dExtraLongExtPlus and dElev < dExtraLongExtNeg then nModifyLeadInOut = 2 end end -- se la distanza positiva è minore della distanza negativa segno di partire dalla parte positiva if dExtraLongExtPlus < dExtraLongExtNeg then bStartPos = true end -- se normale su Y positivo parte da sinistra (parte negativa) if vtN:getY() > 0.866 then -- se deve partire dalla parte positiva setto il flag di inversione lavorazione if bStartPos then bInvertMach = true dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5) else dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5) end -- assegno lato di lavoro seconda faccia if bMachFromDn then nFace2ndFace = MCH_MILL_FU.ORTUP_FRONT else nFace2ndFace = MCH_MILL_FU.ORTHO_FRONT end -- altrimenti normale su Y negativa parte da destra (parte positiva) else -- se deve partire dalla parte negativa setto il flag di inversione lavorazione if not bStartPos then bInvertMach = true dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtNeg + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtPlus + dMillDiam/2 + 5) else dExtraLongIni = EgtIf( nModifyLeadInOut == 2, 1, dExtraLongExtPlus + dMillDiam/2 + 5) dExtraLongEnd = EgtIf( nModifyLeadInOut > 0, 1, dExtraLongExtNeg + dMillDiam/2 + 5) end -- assegno lato di lavoro seconda faccia if bMachFromDn then nFace2ndFace = MCH_MILL_FU.ORTUP_BACK else nFace2ndFace = MCH_MILL_FU.ORTHO_BACK end end end if not bEnablePreMill and not bAsEnablePreMill then dExtraLongIni = 0 dExtraLongEnd = 0 end -- se ho abilitato la lavorazione di fresatura per garantire passaggio gambo utensile, inserisco la lavorazione local bThroughRaw = false if bEnablePreMill then -- verifico se feature e' passante if ((Proc.Box:getMin():getX() < ( b3Raw:getMin():getX() + 50)) and (Proc.Box:getMax():getX() > ( b3Raw:getMax():getX() - 50))) or ((Proc.Box:getMin():getY() < ( b3Raw:getMin():getY() + 50)) and (Proc.Box:getMax():getY() > ( b3Raw:getMax():getY() - 50))) then bThroughRaw = true end -- recupero la lavorazione di taglio local sCuttingGorge = WM.FindCutting( 'Standard') if not sCuttingGorge then local sErr = 'Error : Sawblade not found in library' EgtOutLog( sErr) return false, sErr end -- acquisisco dati utensile lama local dSawThickness = 0 local dSawDiam = 0 if EgtMdbSetCurrMachining( sCuttingGorge) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawThickness = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThickness dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam end end -- calcolo larghezza canale local dGorgeWidth = dMillDiam -- verifico se elevazione minore per fare meno tagli if dElev + 2 * WD.COLL_SIC < dGorgeWidth then dGorgeWidth = max( dElev + 2 * WD.COLL_SIC, 0) end -- sottraggo lato esterno lapjoint per ottenere larghezza netta del gorge dGorgeWidth = dGorgeWidth - dSideElev -- calcolo quanti passi devo fare in larghezza per scaricare l'area di impegno utensile local nNumStep = ceil( ( dGorgeWidth) / ( WD.SAWGORGE_INTERAX or 100)) -- calcolo larghezza passate local dC = 0 if ( nNumStep - 1) > 0 then dC = ( dGorgeWidth) / ( nNumStep) else nNumStep = 1 end -- dati utensile fresa piccola local dMillDiamFirst = 0 local dMaxMatFirst = 0 local bMillInvert = false local bSawInvertSE = false -- se non passante, aggiungo fresatura area della fresa if not bThroughRaw and nNumStep - 1 > 0 then local SquareId -- Id della composita da fresare local dSawShortening = sqrt( b3Raw:getDimZ() * ( dSawDiam - b3Raw:getDimZ())) -- da calcolare in base a raggio lama e spessore grezzo -- gruppo ausiliario local nAddGrpId = WL.GetAddGroup( Proc.PartId) -- disegno quadrato di fresatura local p3Start -- se orientato lungo la Y (direzione) if abs( vtN:getX()) > 0.866 then local dStartX = EgtIf( vtN:getX() > 0.866, Proc.Box:getMax():getX(), Proc.Box:getMin():getX()) local dStartY = EgtIf( bStartPos, Proc.Box:getMin():getY(), Proc.Box:getMax():getY()) p3Start = Point3d( dStartX, dStartY, Proc.Box:getMin():getZ()) local vtNPerp = Vector3d( vtN) vtNPerp:rotate(-Z_AX(), 90 * EgtIf( bStartPos, 1, -1) * EgtIf( vtN:getX() > 0.866, 1, -1)) local FirstLineId = EgtLinePVL( nAddGrpId, p3Start, vtNPerp, dMillDiam / 2 , GDB_RT.GLOB) -- Y_AX() local SecondLineId = EgtLinePVL( nAddGrpId, EgtEP( FirstLineId, GDB_RT.GLOB), vtN, dMillDiam - dSideElev, GDB_RT.GLOB) -- -X_AX() local dThirdLineLen = min( (dMillDiam / 2) + ( Proc.Box:getMax():getY() - Proc.Box:getMin():getY()), dSawShortening + 10) local ThirdLineId = EgtLinePVL( nAddGrpId, EgtEP( SecondLineId, GDB_RT.GLOB), -vtNPerp, dThirdLineLen, GDB_RT.GLOB) -- -Y_AX() local FourthLineId = EgtLinePVL( nAddGrpId, EgtEP( ThirdLineId, GDB_RT.GLOB), -vtN, dMillDiam -dSideElev , GDB_RT.GLOB) -- X_AX() SquareId = EgtCurveCompo( nAddGrpId, { FirstLineId, SecondLineId, ThirdLineId, FourthLineId}) bMillInvert = EgtIf( vtN:getX() > 0.866, not (bStartPos or false), bStartPos or false) bSawInvertSE = EgtIf( vtN:getX() > 0.866, bStartPos or false, not (bStartPos or false)) -- altrimenti orientato lungo la X elseif abs( vtN:getY()) > 0.866 then local dStartX = EgtIf( bStartPos, Proc.Box:getMin():getX(), Proc.Box:getMax():getX()) local dStartY = EgtIf( vtN:getY() > 0.866, Proc.Box:getMax():getY(), Proc.Box:getMin():getY()) p3Start = Point3d( dStartX, dStartY, Proc.Box:getMin():getZ()) local vtNPerp = Vector3d( vtN) vtNPerp:rotate(-Z_AX(), 90 * EgtIf( bStartPos, -1, 1) * EgtIf( vtN:getY() > 0.866, 1, -1)) local FirstLineId = EgtLinePVL( nAddGrpId, p3Start, vtNPerp, dMillDiam / 2 , GDB_RT.GLOB) -- Y_AX() local SecondLineId = EgtLinePVL( nAddGrpId, EgtEP( FirstLineId, GDB_RT.GLOB), vtN, dMillDiam -dSideElev, GDB_RT.GLOB) -- -X_AX() local dThirdLineLen = min( (dMillDiam / 2) + ( Proc.Box:getMax():getX() - Proc.Box:getMin():getX()), dSawShortening + 10) local ThirdLineId = EgtLinePVL( nAddGrpId, EgtEP( SecondLineId, GDB_RT.GLOB), -vtNPerp, dThirdLineLen, GDB_RT.GLOB) -- -Y_AX() local FourthLineId = EgtLinePVL( nAddGrpId, EgtEP( ThirdLineId, GDB_RT.GLOB), -vtN, dMillDiam -dSideElev , GDB_RT.GLOB) -- X_AX() SquareId = EgtCurveCompo( nAddGrpId, { FirstLineId, SecondLineId, ThirdLineId, FourthLineId}) bMillInvert = EgtIf( vtN:getY() > 0.866, bStartPos or false, not (bStartPos or false)) bSawInvertSE = EgtIf( vtN:getY() > 0.866, not (bStartPos or false), bStartPos or false) end -- recupero la lavorazione local sMillingGorge = WM.FindMilling( 'Gorge', nil, nil, nil, 80) if not sMillingGorge then local sErr = 'Error : Gorge not found in library' EgtOutLog( sErr) return false, sErr end -- acquisisco dati utensile if EgtMdbSetCurrMachining( sMillingGorge) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiamFirst = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiamFirst dMaxMatFirst = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMatFirst end end -- inserisco la lavorazione di fresatura local sNameGorge = 'Gorge_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. tostring( nFacet) local nMchFId = WM.AddMachining( Proc, sNameGorge, sMillingGorge) if not nMchFId then local sErr = 'Error adding machining ' .. sNameGorge .. '-' .. sMillingGorge EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( SquareId) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if abs( vtN:getZ()) < GEO.EPS_SMALL then nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto modo di lavorare la faccia local nFaceUse = WL.GetNearestParalOpposite( Z_AX()) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto elevazione e step local dStep = EgtGetMachiningParam( MCH_MP.STEP) if dStep < GEO.EPS_SMALL then dStep = dMaxMat end ---- se sto lavorando la gola centrale setto l'elevazione e l'affondamento --if nSinglePass and nSinglePass == 0 then -- local dZElev = b3Raw:getDimZ() -- local dDepth = Proc.Box:getMax():getZ() - b3Raw:getMin():getZ() -- EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dZElev, 3) .. ';') -- EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) --end EgtSetMachiningParam( MCH_MP.STEP, dStep) -- imposto invert in base al lato fresa local bWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE) if bWorkSide == MCH_MILL_WS.RIGHT then bMillInvert = not bMillInvert end EgtSetMachiningParam( MCH_MP.INVERT, bMillInvert) -- aggiungo allungamenti iniziali e finali EgtSetMachiningParam( EgtIf( bMillInvert, MCH_MP.STARTADDLEN, MCH_MP.ENDADDLEN), -dMillDiamFirst / 2 - dSawThickness / 2) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- inserisco la lavorazione local nNm = 0 -- passi di allargamento for i = 1, nNumStep - 1 do nNm = nNm + 1 -- inserisco la lavorazione di taglio sfrido gorge local sNameGorge = 'GorgeCut_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. tostring( nFacet) .. '_' .. tostring( nNm) local nMchFId = WM.AddMachining( Proc, sNameGorge, sCuttingGorge) if not nMchFId then local sErr = 'Error adding machining ' .. sNameGorge .. '-' .. sCuttingGorge EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacet}}) EgtSetInfo( nMchFId, 'Part', Proc.PartId) -- assegno invert EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- assegno il lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- EgtIf( bMillInvert, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)) -- assegno l'attacco e l'uscita if not bThroughRaw and bSawInvertSE then EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.STRICT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.CENT) -- aggiungo allungamento finale if not bThroughRaw then EgtSetMachiningParam( MCH_MP.STARTADDLEN, ( dMillDiam / 2) - ( dMillDiamFirst / 2)) end elseif not bThroughRaw and not bSawInvertSE then EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LO.CENT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LI.STRICT) -- aggiungo allungamento finale if not bThroughRaw then EgtSetMachiningParam( MCH_MP.ENDADDLEN, ( dMillDiam / 2) - ( dMillDiamFirst / 2)) end else EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LO.CENT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LI.CENT) end -- aggiungo l'offset laterale EgtSetMachiningParam( MCH_MP.OFFSL, ( dSideElev - dSawThickness + ( dC * ( i)))) -- nessun criterio per il braccio è necessario EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end -- se la groove è rivolta verso il basso (-85°) lavoro a salire con step negativo local bUpwardMilling = false if vtN2:getZ() < -0.996 then bUpwardMilling = true end -- step extra in caso di doppio con mix rabbet dal basso e dall'alto, per eliminare la lamina che potrebbe rimanere if Proc.Double and Proc.Double == 2 and ( Proc.Topology == 'Rabbet' or Proc.Topology == 'Groove') and not ( Proc.AffectedFaces.Bottom and Proc.Mirror.AffectedFaces.Bottom) and not ( Proc.AffectedFaces.Top and Proc.AffectedFaces.Bottom) then -- determino a quale delle due feature applicare la lavorazione local bProcVsMirrorToCopy = true local nFacetToMachine = nFacet if Proc.AffectedFaces.Bottom then bProcVsMirrorToCopy = false for i = 1, Proc.Mirror.Fct do local vtNMirror = Proc.Mirror.Face[i].VtN if AreOppositeVectorApprox( vtN, vtNMirror) then nFacetToMachine = Proc.Mirror.Face[i].Id break end end end local nAddGrpId = WL.GetAddGroup( EgtIf( bProcVsMirrorToCopy, Proc.PartId, Proc.Mirror.PartId)) local nNewProc = EgtCopyGlob( EgtIf( bProcVsMirrorToCopy, Proc.Id, Proc.Mirror.Id), nAddGrpId) or GDB_ID.NULL local NewProc = { Id = nNewProc, PartId = EgtIf( bProcVsMirrorToCopy, Proc.PartId, Proc.Mirror.PartId)} -- lavorazione local sName = 'PreSideMill_' .. EgtGetName( NewProc.Id) or tostring( NewProc.Id) local nMchFId = WM.AddMachining( NewProc, sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchFId, 'Part', NewProc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ NewProc.Id, nFacetToMachine}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_NEAR EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto modo di lavorare la faccia local nFaceUse = WL.GetNearestParalOpposite( Z_AX()) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto elevazione e step local dDepth = 5 EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) EgtSetMachiningParam( MCH_MP.STEP, dElev) -- setto il lato di lavoro standard EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita if dElev > ( 0.5 * dMillDiam) then -- setto allungamenti perpendicolari EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LOPERP, 0) end -- se richiesto, setto la nota per spostare la lavorazione alla fine if not WD.SIDEMILL_BEFORE then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end -- eseguo if not EgtApplyMachining( true, false) then -- provo a invertire posizione braccio porta testa nSCC = MCH_SCC.ADIR_FAR EgtSetMachiningParam( MCH_MP.SCC, nSCC) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- se faccio lo step extra e ho rimosso la lamina, in doppio lavorerò dal basso verso l'alto bUpwardMilling = true end -- lavorazione local dStepOri if not bExcludeSideMill then local nSideStep = 1 if dSideStep > 0 and not ( bEnablePreMill or bAsEnablePreMill) then nSideStep = ceil( dElev / dSideStep) dSideStep = max( dElev / nSideStep, 0) end for i = 1, nSideStep do -- inserisco la lavorazione di ribasso o gola local sName = EgtIf( bEnablePreMill ~= nil, 'SideMill_', 'Mill_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = WM.AddMachining( Proc, sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchFId, 'Part', Proc.PartId) -- se ho abilitato la lavorazione di lama per garantire passaggio utensile, setto la nota per spostare la fresatura dopo i tagli di lama if bEnablePreMill or bAsEnablePreMill then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacet}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_NEAR EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto modo di lavorare la faccia local nFaceUse = WL.GetNearestParalOpposite( Z_AX()) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto elevazione e step local dStep = EgtGetMachiningParam( MCH_MP.STEP) dStepOri = dStep if dStep < GEO.EPS_SMALL then dStep = 0.75 * dMaxMat end local nStep = ceil( ( dThick - dMaxMat) / dStep) dStep = max( ( dThick - dMaxMat) / max( nStep, 1), 0) local dMaxElev = max( ( nStep + 1) * dStep - GEO.EPS_SMALL, 0) if nSinglePass and nSinglePass > 0 then dStep = 0 if nSinglePass == 1 then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat) end end if bUpwardMilling then dStep = -dStep end EgtSetMachiningParam( MCH_MP.STEP, dStep) -- leggo eventuali note esistenti della lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- aggiungo alle note massima elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev, 3)) -- se lavorazione in doppio aggiungo le rispettive note if Proc.Double and Proc.Double == 2 then sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ) end -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- setto il lato di lavoro standard EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- setto offset radiale per gestire le eventuali passate in orizzontale local dRadialOffset = dSideStep * ( nSideStep - i) EgtSetMachiningParam( MCH_MP.OFFSR, dRadialOffset) -- modifico ingressi e uscita -- se ho inserito il pretaglio modifico if bEnablePreMill or bAsEnablePreMill then if nModifyLeadInOut > 0 then -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita if dElev > ( 0.5 * dMillDiam) then if nModifyLeadInOut == 1 then -- setto il tipo di passo a una via EgtSetMachiningParam( MCH_MP.STEPTYPE, MCH_MILL_ST.ONEWAY) -- modifico il tipo di uscita EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.PERP_TG) EgtSetMachiningParam( MCH_MP.LIPERP, 0) -- modifico dati supplementari uscita EgtSetMachiningParam( MCH_MP.LOPERP, 0.5) EgtSetMachiningParam( MCH_MP.LOTANG, -( dLongGorge + dExtraLongIni + dExtraLongEnd)) else EgtSetMachiningParam( MCH_MP.LIPERP, dElev) EgtSetMachiningParam( MCH_MP.LOPERP, dElev) end end -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) if bInvertMach then -- setto il lato di lavoro invertito EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) end else -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita if dElev > ( 0.5 * dMillDiam) then -- setto allungamenti perpendicolari EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LOPERP, 0) end end -- se richiesto, setto la nota per spostare la lavorazione alla fine if not WD.SIDEMILL_BEFORE then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end else if nModifyLeadInOut > 0 then -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita if dElev > ( 0.5 * dMillDiam) then -- setto il tipo di passo a una via EgtSetMachiningParam( MCH_MP.STEPTYPE, 1) end if bInvertMach then -- setto il lato di lavoro invertito EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) end end -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) -- se ho passate orizzontali riduco l'eventuale allungamento settato dall'utente local dLiPerp = EgtGetMachiningParam( MCH_MP.LIPERP) local dLoPerp = EgtGetMachiningParam( MCH_MP.LOPERP) if dLiPerp > 0 then dLiPerp = dLiPerp - dRadialOffset end if dLoPerp > 0 then dLoPerp = dLoPerp - dRadialOffset end EgtSetMachiningParam( MCH_MP.LIPERP, dLiPerp) EgtSetMachiningParam( MCH_MP.LOPERP, dLoPerp) -- se richiesto, setto la nota per spostare la lavorazione alla fine if not WD.SIDEMILL_BEFORE then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end end -- eseguo if not EgtApplyMachining( true, false) then -- provo a invertire posizione braccio porta testa nSCC = MCH_SCC.ADIR_FAR EgtSetMachiningParam( MCH_MP.SCC, nSCC) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end else sWarn = 'Warning in LapJoint : upside down groove with obtuse angle not completed' EgtOutLog( sWarn) end -- verifico se devo lavorare anche la seconda faccia basandomi sul valore dell'angolo interno if dAng and dAng > -90 + 10 * GEO.EPS_SMALL and not bExcludeFinishing then -- inserisco la lavorazione di contornatura local sName = 'Mill_Oth_Fac_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = WM.AddMachining( Proc, sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchFId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nOtherFacet}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if AreSameOrOppositeVectorApprox( vtN2, Z_AX()) then nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto modo di lavorare la faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFace2ndFace) local dMaxElev = dMaxMat local dStepOtherFace = 0 local dDepthOtherFace = dMaxMat if Proc.Fct == 2 and abs( vtN2:getZ()) > 0.99 and abs( vtN2:getZ()) < 1.01 then dStepOtherFace = dStepOri or EgtGetMachiningParam( MCH_MP.STEP) if dStepOtherFace < GEO.EPS_SMALL then dStepOtherFace = 0.75 * dMaxMat end local nStepOtherFace = ceil( ( dElevOtherFacet - dMaxMat) / dStepOtherFace) dStepOtherFace = max( ( dElevOtherFacet - dMaxMat) / max( nStepOtherFace, 1), 0) dMaxElev = max( ( nStepOtherFace + 1) * dStepOtherFace - GEO.EPS_SMALL, 0) dDepthOtherFace = dElevOtherFacet end if bUpwardMilling then dStepOtherFace = -dStepOtherFace end EgtSetMachiningParam( MCH_MP.STEP, dStepOtherFace) -- leggo eventuali note esistenti della lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- aggiungo alle note massima elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dMaxElev, 3)) -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) if bMachFromDn then EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.DEPTH, dDepthOtherFace) else EgtSetMachiningParam( MCH_MP.INVERT, false) end EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- modifico ingressi e uscita -- se ho inserito il pretaglio modifico if bEnablePreMill or bAsEnablePreMill then if nModifyLeadInOut > 0 then -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita if dElev > ( 0.5 * dMillDiam) then -- setto il tipo di passo a una via EgtSetMachiningParam( MCH_MP.STEPTYPE, 1) -- modifico il tipo di uscita EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, 5) EgtSetMachiningParam( MCH_MP.LIPERP, 0) -- modifico dati supplementari uscita EgtSetMachiningParam( MCH_MP.LOPERP, 0.5) EgtSetMachiningParam( MCH_MP.LOTANG, -( dLongGorge + dExtraLongIni + dExtraLongEnd)) end -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) if bInvertMach then -- setto il lato di lavoro invertito if bMachFromDn then EgtSetMachiningParam( MCH_MP.INVERT, false) else EgtSetMachiningParam( MCH_MP.INVERT, true) end EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) end else -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) -- Invece del numero di passi in sgrossatura confronto il raggio fresa con l'elevazione dalla normale -- per vedere se devo modificare l'uscita -- if nNumStep > 1 then if dElev > ( 0.5 * dMillDiam) then -- setto allungamenti perpendicolari EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LOPERP, 0) end end -- se richiesto, setto la nota per spostare la lavorazione alla fine if bEnablePreMill or bAsEnablePreMill or not WD.SIDEMILL_BEFORE then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end else if nModifyLeadInOut > 0 then -- Confronto il raggio fresa con l'elevazione dalla normale per vedere se devo modificare l'uscita if dElev > ( 0.5 * dMillDiam) then -- setto il tipo di passo a una via EgtSetMachiningParam( MCH_MP.STEPTYPE, 1) end if bInvertMach then -- setto il lato di lavoro invertito if bMachFromDn then EgtSetMachiningParam( MCH_MP.INVERT, false) else EgtSetMachiningParam( MCH_MP.INVERT, true) end EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) end end -- setto allungamenti iniziali e finali EgtSetMachiningParam( MCH_MP.STARTADDLEN, dExtraLongIni) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dExtraLongEnd) -- se richiesto, setto la nota per spostare la lavorazione alla fine if not WD.SIDEMILL_BEFORE then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end elseif bExcludeSideMill then local sErr = 'Feature not machinable by orientation' EgtOutLog( sErr) return false, sErr end return true, sWarn end --------------------------------------------------------------------- -- trova la migliore lavorazione tasca in base a diametro utensile, elevazione, doppio e eventuale interferenza di parti vicine -- se necessario forza la tasca a chiusa local function VerifyPocket( Proc, nFacet, dElev, nRawId) local bForceClosedPocket = false local b3Raw = EgtGetRawPartBBox( nRawId) -- verifico se la feature è sul bordo (non ci sono altri pezzi davanti alla tasca). Se è sul bordo, l'utensile potrà attaccare da fuori. local bIsFeatureOnEdge = ( Proc.Topology == 'Groove' and Proc.Fct == 4 and Proc.DistanceToNearestParts.Front > b3Raw:getDimY()) -- trovo il massimo diametro utensile ammissibile per la tasca local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) local dStartDiameter = min( dH, dV) local dMaxDiameter = dStartDiameter -- se una sola faccia posso usare un utensile più grande della faccia if Proc.Fct == 1 then dMaxDiameter = 2 * dMaxDiameter end -- se forma ad L posso usare un utensile più grande della faccia local bIsL = ( Proc.Fct == 2 or WL.TestElleShape3( Proc.Id, Proc.Fct) or WL.TestElleShape4( Proc.Id, Proc.Fct) == 2) if bIsL then dMaxDiameter = 2 * dMaxDiameter end -- se forma ad U riduco il diametro se necessario local bIsU = ( Proc.Fct == 3 and not WL.TestElleShape3( Proc.Id, Proc.Fct)) if bIsU then -- prendo la linea di base local dMiddleFacetLength = 0 if abs( dElev - dH) < 1 and abs( dElev - dV) > 1 then dMiddleFacetLength = dV elseif abs( dElev - dV) < 1 and abs( dElev - dH) > 1 then dMiddleFacetLength = dH end if dMiddleFacetLength > dMaxDiameter then dMaxDiameter = min( 2 * dMaxDiameter, dMiddleFacetLength) end end -- in presenza di angoli interni, limito secondo impostazione globale il diametro massimo utensile if Proc.Fct == 3 and bIsL then dMaxDiameter = min( dMaxDiameter, WD.MAXDIAM_POCK_CORNER or 1000) elseif Proc.Fct >= 4 then dMaxDiameter = min( dMaxDiameter, WD.MAXDIAM_POCK_CORNER or 1000) end -- verifico la distanza minima dalle parti vicine e nel caso il FindPocketing limiterà il diametro massimo dell'utensile local dDistanceToNearestPart = GEO.INFINITO if Proc.AffectedFaces.Front then dDistanceToNearestPart = Proc.DistanceToNearestParts.Front end if Proc.AffectedFaces.Back then dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Back) end if Proc.AffectedFaces.Left then dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Left) end if Proc.AffectedFaces.Right then dDistanceToNearestPart = min( dDistanceToNearestPart, Proc.DistanceToNearestParts.Right) end -- se la distanza è inferiore ad un valore minimo forzo la tasca chiusa per evitare che la ricerca utensile fallisca local dMinToolDiameter = 25 if dDistanceToNearestPart < dMinToolDiameter / 2 - 10 * GEO.EPS_SMALL then bForceClosedPocket = true dDistanceToNearestPart = dMaxDiameter end local bExcludeNoTipFeed = ( Proc.Topology == 'Pocket') -- recupero la lavorazione local bUseDElevToFindPocketing = true local sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, dElev, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) -- se tasca troppo profonda cerco senza elevazione e limiterò la profondità if not sPocketing then bUseDElevToFindPocketing = false sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, nil, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) end local dMillDiam = 20 local dMaxDepth = 0 local dThDiam = 100 local sTuuid -- se lavorazione trovata verifico eventuale doppio, raccolgo i dati utensile e verifico collisioni dell'utensile con altre parti if sPocketing then -- se doppio cerco una lavorazione adatta if Proc.Double and Proc.Double == 2 then local sPocketingBackup = sPocketing sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, EgtIf( bUseDElevToFindPocketing, dElev, nil), nil, 'H1', true, dDistanceToNearestPart) if not WM.IsMachiningOkForDouble( sPocketing) then Proc.Double = 0 sPocketing = sPocketingBackup end end -- recupero diametro utensile if EgtMdbSetCurrMachining( sPocketing) then sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam end end -- verifico se la lavorazione (o il suo eventuale mirror) potrebbe danneggiare le parti limitrofe e devo quindi forzare una tasca chiusa local bIsMachiningDamagingOtherParts = IsMachiningDamagingOtherParts( Proc, dMillDiam, nRawId) if bIsMachiningDamagingOtherParts then bForceClosedPocket = true end -- disattivo il doppio se devo forzare una tasca chiusa ma l'altra no if Proc.Double and Proc.Double > 0 then local bIsMirrorMachiningDamagingOtherParts = IsMachiningDamagingOtherParts( Proc.Mirror, dMillDiam, nRawId) if bIsMachiningDamagingOtherParts ~= bIsMirrorMachiningDamagingOtherParts then Proc.Double = 0 end end -- altrimenti diametro utensile troppo piccolo: devo forzare tasca chiusa else bForceClosedPocket = true end -- se tasca chiusa cerco lavorazione con diametro massimo pari a dimensione tasca e riverifico per eventuale doppio if bForceClosedPocket then dMaxDiameter = dStartDiameter bUseDElevToFindPocketing = true sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, dElev, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) if not sPocketing then bUseDElevToFindPocketing = false sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, nil, nil, nil, bExcludeNoTipFeed, dDistanceToNearestPart) end -- se doppio cerco una lavorazione adatta if Proc.Double and Proc.Double == 2 then local sPocketingBackup = sPocketing sPocketing = WM.FindPocketing( 'Pocket', dMaxDiameter, EgtIf( bUseDElevToFindPocketing, dElev, nil), nil, 'H1', true, dDistanceToNearestPart) if not WM.IsMachiningOkForDouble( sPocketing) then Proc.Double = 0 sPocketing = sPocketingBackup end end end -- recupero dati utensile if sPocketing and EgtMdbSetCurrMachining( sPocketing) then sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), EgtTdbGetCurrToolMaxDepth()) or dMaxDepth dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam end end return sPocketing, bForceClosedPocket, bIsFeatureOnEdge, sTuuid, dMillDiam, dMaxDepth, dThDiam end --------------------------------------------------------------------- local function MakeByPocketing( Proc, nFacet, nRawId, b3Raw, bCheckQPar) -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) local dElev = WL.GetFaceElevation( Proc.Id, nFacet, nRawId) -- gruppo ausiliario local nAddGrpId = WL.GetAddGroup( Proc.PartId) local nNewProc = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet) -- cerco lavorazione adatta e recupero i dati utensile local sPocketing, bForceClosedPocket, bIsFeatureOnEdge, sTuuid, dMillDiam, dMaxDepth, dThDiam = VerifyPocket( Proc, nFacet, dElev, nRawId) if not sPocketing then local sErr = 'Error : pocketing not found in library' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = WM.AddMachining( Proc, sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchFId, 'Part', Proc.PartId) -- se lavorazione di fianco setto la nota per spostarla dopo i tagli di lama if vtN:getZ() < WD.NZ_MINA then EgtSetInfo( nMchFId, 'MOVE_AFTER', 1) end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacet}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if AreSameVectorApprox( vtN, Z_AX()) then nSCC = EgtIf( Proc.Box:getDimX() >= Proc.Box:getDimY(), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_XP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local dThElev = dThDiam / 2 * sqrt( vtN:getX() * vtN:getX() + vtN:getY() * vtN:getY()) local dDepth = 0 local sWarn = '' if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then dDepth = dMaxDepth - dElev - dThElev sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- leggo eventuali note della lavorazione local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- imposto elevazione sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( min( dElev, dMaxDepth), 1)) -- se lavorazione in doppio aggiungo le rispettive note if Proc.Double and Proc.Double == 2 then sUserNotes = EgtSetValInNotes( sUserNotes, 'DOUBLE', Proc.Double) sUserNotes = EgtSetValInNotes( sUserNotes, 'MirrorAx', Proc.MirrorAx) sUserNotes = EgtSetValInNotes( sUserNotes, 'DeltaZ', Proc.MirrorDeltaZ) -- escludo ottimizzazioni e forzo attacco interno perchè la tasca specchiata potrebbe essere nel mezzo del pannello sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxOptSize', 0.1) EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALOUT) end -- setto eventuale nota per forzare tasca chiusa if bForceClosedPocket then sUserNotes = EgtSetValInNotes( sUserNotes, 'Open', 0) end -- setto eventuale nota per forzare attacco esterno, fino ad un certo spessore del grezzo local dMaxRawThicknessToStartOut = 75 if bIsFeatureOnEdge and ( not Proc.Double or Proc.Double == 0) then sUserNotes = EgtSetValInNotes( sUserNotes, 'OpenMinSafe', dMaxRawThicknessToStartOut) end -- scrivo le note della lavorazione EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- verifica parametro Q per pulitura spigoli local bIsU = ( Proc.Fct == 3 and not WL.TestElleShape3( Proc.Id, Proc.Fct)) if bCheckQPar and not ( bIsU and AreSameOrOppositeVectorApprox( vtN, Z_AX())) then -- lettura parametri (probabile/i parametro/i Q) local nConeCut = EvaluateQParam( Proc) -- recupero i dati di tutte le facce local vFace, dMaxWidth = GetFacesData( nNewProc, false, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, Proc.PartId) -- se abilitata la lavorazione corner con stop macchina if nConeCut == 1 then local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, dMillDiam, nAddGrpId, dMaxWidth, nNewProc, dDepth) if not bMcok then return bMcok, sMcErr end elseif nConeCut == 2 then local sErr = 'Clean corner 30° is not applied on pocketing' EgtOutLog( sErr) EgtErase( nNewProc) else EgtErase( nNewProc) end else EgtErase( nNewProc) end return true, sWarn, sTuuid end --------------------------------------------------------------------- local function MakeOneFace( Proc, nRawId, b3Raw) -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- dimensioni della faccia local _, dDimH, dDimV = WL.GetFaceHvRefDim( Proc.Id, 0) -- recupero la lavorazione di taglio con lama e i suoi parametri local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard') -- se non inclinata o capacità di taglio non sufficiente, provo con svuotatura if not sCutting or vtN:getZ() > 0.866 or dSawMaxDepth < dDimV + WD.CUT_EXTRA then -- faccio con svuotatura local nFacet = 0 return MakeByPocketing( Proc, nFacet, nRawId, b3Raw) end -- eseguo il taglio di lama local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. tostring( Proc.Id) local nMchId = WM.AddMachining( Proc, sName, sCutting) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( { { Proc.Id, 0}}) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- assegno il lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- assegno l'attacco e l'uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.CENT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.CENT) -- nessun criterio per il braccio è necessario EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end return true end --------------------------------------------------------------------- local function MakeTwoFaces( Proc, nRawId, b3Raw) -- dati delle facce local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- determino l'intersezione tra le due facce local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) if not bAdj then return false, 'Feature with two faces not adjacentes' end -- se equivalente ad un contorno if abs( ptP1:getZ() - ptP2:getZ()) > 0.9 * b3Raw:getDimZ() then -- verifico ordinamento (esterno a destra) local ptPM = ( ptP1 + ptP2) / 2 if ( vtN[1] ^ ( ptPM - ptC[1])) * Z_AX() < 0 then EgtSurfTmSwapFacets( Proc.Id, 0, 1) end -- applico lavorazione di contorno libero return FreeContour.Make( Proc, nRawId, b3Raw) end -- versore della linea di intersezione local vtX = ptP2 - ptP1 ; vtX:normalize() -- larghezza delle facce ortogonalmente all'intersezione local dDimY = {} for i = 1, 2 do local vtY = vtN[i] ^ vtX ; vtY:normalize() local frRef = Frame3d( ptC[i], ptC[i] + 100 * vtX, ptC[i] + 100 * vtY) local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, i - 1, GDB_BB.STANDARD, frRef) dDimY[i] = b3Ref:getDimY() end -- recupero la lavorazione di taglio con lama e i suoi parametri local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard') -- se parametro Q abilita lavorazione ribasso con fresa di fianco local _, nUseMillOnSide = EvaluateQParam( Proc) local dMaxZVers, dMinZVers if nUseMillOnSide >= 1 then dMaxZVers = 0.866 dMinZVers = 0.5 else dMaxZVers = 0.95 dMinZVers = 0.1 end -- se di fianco in basso local dMaxThick, dMinSideElev if vtN[1]:getZ() < -dMaxZVers or vtN[2]:getZ() < -dMaxZVers then if vtN[1]:getZ() < -0.5 then dMaxThick = dDimY[2] dMinSideElev = dDimY[1] elseif vtN[2]:getZ() < -0.5 then dMaxThick = dDimY[1] dMinSideElev = dDimY[2] end end local sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev) -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata local bDoubleMillOnSide = false if Proc.Double and Proc.Double == 2 then local sMillOnSideBackup = sMillOnSide sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, dMaxThick, nil, dMinSideElev, 'H1') if WM.IsMachiningOkForDouble( sMillOnSide) then bDoubleMillOnSide = true else sMillOnSide = sMillOnSideBackup end end local bEnableMillOnSide if sMillOnSide and nUseMillOnSide >= 1 then dMaxZVers = 0.866 dMinZVers = 0.5 bEnableMillOnSide = true else dMaxZVers = 0.95 dMinZVers = 0.1 end -- se di fianco in basso if vtN[1]:getZ() < -dMaxZVers or vtN[2]:getZ() < -dMaxZVers then -- cerco la faccia verticale o quasi local nFacet = EgtIf( abs( vtN[1]:getZ()) < dMinZVers, 0, 1) -- cerco nei parametri utensili la nota di affondamento di fianco SIDEDEPTH local dMaxDepthOnSide = 0 local dMillDiam = 0 local dMillDiamTh = 0 if bEnableMillOnSide and EgtMdbSetCurrMachining( sMillOnSide) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMillDiamTh = EgtTdbGetCurrToolThDiam() or dMillDiamTh dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide dMaxDepthOnSide = min( dMaxDepthOnSide, 0.5 * ( dMillDiam - dMillDiamTh)) end end local dMaxDist = 300 if bEnableMillOnSide and dMaxDepthOnSide > 0 then dMaxDist = dMaxDepthOnSide end -- se vicino al bordo del grezzo e non troppo larga, provo con fresatura di fianco local ptMid = ( ptP1 + ptP2) / 2 local bMakeFirstGroove local bMachFromDn = true local bInsertMach local dSideDist -- per evitare errori in casi di pezzi molto stretti, verifico le distanze in base alla direzione della faccia -- se normale verso X if vtN[nFacet+1]:getX() > 0.99 then dSideDist = abs( ptMid:getX() - b3Raw:getMax():getX()) -- altrimenti se normale verso X- elseif vtN[nFacet+1]:getX() < -0.99 then dSideDist = abs( ptMid:getX() - b3Raw:getMin():getX()) -- altrimenti se normale verso Y+ elseif vtN[nFacet+1]:getY() > 0.99 then dSideDist = abs( ptMid:getY() - b3Raw:getMax():getY()) -- altrimenti se normale verso Y- elseif vtN[nFacet+1]:getY() < -0.99 then dSideDist = abs( ptMid:getY() - b3Raw:getMin():getY()) end if dSideDist and dSideDist < dMaxDist then bInsertMach = true bMakeFirstGroove = false -- altrimenti la distanza è maggiore e se è sempre abilitata la lavorazione MillOnSide elseif bEnableMillOnSide and dMaxDepthOnSide then bInsertMach = true bMakeFirstGroove = true end -- se posso eseguire la lavorazione per distanza inferiore utensile o lavorazione preceduta da sgossatura gola if bInsertMach then return MakeSideGrooveByMill( Proc, nFacet, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, nil, nil, nil, bDoubleMillOnSide) else local sErr = 'Error feature not machinable (dimensions)' EgtOutLog( sErr) return false, sErr end -- se altrimenti di fianco in alto elseif vtN[1]:getZ() > dMaxZVers or vtN[2]:getZ() > dMaxZVers then -- cerco la faccia con il maggior numero di adiacenze (e minor elevazione) local nFacInd, _, nFacInd2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId) if nFacInd == -2 then local sErr = 'Error feature with 2 faces with undercut' EgtOutLog( sErr) return false, sErr end local vtNTemp = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) local dSideDist local ptMid = ( ptP1 + ptP2) / 2 -- faccia orizzontale local nFacet = EgtIf( vtNTemp:getZ() >= WD.NZ_MINA, nFacInd, nFacInd2) local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacet, GDB_ID.ROOT) -- faccia verticale local nFacetVert = EgtIf( nFacet == nFacInd, nFacInd2, nFacInd) local vtNV = EgtSurfTmFacetNormVersor( Proc.Id, nFacetVert, GDB_ID.ROOT) -- per evitare errori in casi di pezzi molto stretti, verifico le distanze in base alla direzione della faccia -- local dSideDist = min( abs( ptMid:getX() - b3Raw:getMin():getX()), abs( ptMid:getX() - b3Raw:getMax():getX()), -- abs( ptMid:getY() - b3Raw:getMin():getY()), abs( ptMid:getY() - b3Raw:getMax():getY())) -- se normale verso X if vtNV:getX() > 0.99 then dSideDist = abs( ptMid:getX() - b3Raw:getMax():getX()) -- altrimenti se normale verso X- elseif vtNV:getX() < -0.99 then dSideDist = abs( ptMid:getX() - b3Raw:getMin():getX()) -- altrimenti se normale verso Y+ elseif vtNV:getY() > 0.99 then dSideDist = abs( ptMid:getY() - b3Raw:getMax():getY()) -- altrimenti se normale verso Y- elseif vtNV:getY() < -0.99 then dSideDist = abs( ptMid:getY() - b3Raw:getMin():getY()) end -- cerco nei parametri utensili la nota di affondamento di fianco SIDEDEPTH local dMaxDepthOnSide = 0 local dMillDiam = 0 if bEnableMillOnSide and EgtMdbSetCurrMachining( sMillOnSide) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide end end -- 2021.10.08 E.S. in base a richieste del cliente: -- Se parametro Q riduce utilizzo lavorazione di lato come lama ed elevazione laterale supera il 60% diametro utensile -- disabilito if nUseMillOnSide == 2 and dSideDist > 0.6 * dMillDiam then bEnableMillOnSide = false end -- per il fianco in alto non ci sono problemi di inserimento massimo laterale, setto la variabile pari al raggio utensile - 1mm dMaxDepthOnSide = ( 0.5 * dMillDiam) - 1 local dMaxDist = 300 if bEnableMillOnSide and dMaxDepthOnSide > 0 then dMaxDist = dMaxDepthOnSide end -- se vicino al bordo del grezzo e non troppo larga, provo con fresatura di fianco local bMakeFirstGroove = false local bLikeAsMakeFirstGroove local bMachFromDn = false local bInsertMach if dSideDist and dSideDist < dMaxDist then -- se abilitata SideMill oppure se la specchiata guarda in basso e quindi l'attacco deve essere a filo if ( bEnableMillOnSide and dMaxDepthOnSide > 0) or ( Proc.Double == 2 and Proc.MirrorDeltaZ and abs( Proc.MirrorDeltaZ) > GEO.EPS_SMALL) then bLikeAsMakeFirstGroove = false return MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove, nil, nil, bDoubleMillOnSide) else local bOk, sErr, bSideMachiningNotFound = MakeByMill( Proc, nFacet, 1 - nFacet, nRawId, b3Raw, dSideDist) if not bOk and bSideMachiningNotFound then bOk, sErr = MakeByPocketing( Proc, nFacet, nRawId, b3Raw) end -- se angolo ottuso riprendo il lato quasi verticale if bOk and dAng and dAng > -90 + 10 * GEO.EPS_SMALL then local bOk2, sErr2 = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, false, nil, true) end return bOk, sErr end elseif bEnableMillOnSide and dMaxDepthOnSide > 0 then bLikeAsMakeFirstGroove = true local bOk, sErr = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, EgtIf( bEnableMillOnSide and dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, bLikeAsMakeFirstGroove, nil, nil, bDoubleMillOnSide) if bOk then return true end end -- se non inclinate o capacità di taglio non sufficiente o non molto grandi (80mm), provo con contornatura o svuotatura if vtN:getZ() > 0.866 or vtNV:getZ() > 0.866 or not sCutting or dSawMaxDepth < dDimY[1] + WD.CUT_SIC or dSawMaxDepth < dDimY[2] + WD.CUT_SIC or dDimY[1] < 80 or dDimY[2] < 80 then -- eseguo la svuotatura local bOk, sErr, sTuuid = MakeByPocketing( Proc, nFacet, nRawId, b3Raw) -- se angolo ottuso riprendo il lato quasi verticale if bOk and dAng and dAng > -90 + 10 * GEO.EPS_SMALL then local _, dHVert, dVVert = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacetVert, GDB_ID.ROOT) local dDepth = min( dHVert, dVVert) local _, dHHor, dVHor = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacet, GDB_ID.ROOT) local dDiam = 2 * min( dHHor, dVHor) local sMillObtuseAngle = WM.FindMilling( 'FreeContour', dDepth, sTuuid, nil, dDiam, nil, nil, nil) if not sMillObtuseAngle then sMillObtuseAngle = WM.FindMilling( 'FreeContour', dDepth, nil, nil, dDiam, nil, nil, nil) end if not sMillObtuseAngle then local sErrMillNotFound = 'Error : Processing to finish obtuse angle not found in library' EgtOutLog( sErrMillNotFound) return true, sErrMillNotFound end local bOk2, sErr2 = MakeSideGrooveByMill( Proc, nFacetVert, nRawId, b3Raw, sMillObtuseAngle, dMaxDepthOnSide, bMakeFirstGroove, bMachFromDn, dAng, false, nil, true) end return bOk, sErr end -- se una delle due facce rivolta verso il basso elseif vtN[1]:getZ() < -0.001 or vtN[2]:getZ() < -0.001 then -- cerco la faccia rivolta verso l'alto local nFacet if vtN[1]:getZ() > 0 then nFacet = 0 elseif vtN[2]:getZ() > 0 then nFacet = 1 else local sErr = 'Error feature with 2 faces facing down' EgtOutLog( sErr) return false, sErr end -- eseguo la svuotatura return MakeByPocketing( Proc, nFacet, nRawId, b3Raw) end -- ordino i tagli per fare prima quello meno inclinato local nOrd = { 0, 1} if vtN[2]:getZ() > vtN[1]:getZ() then nOrd = { 1, 0} end -- eseguo i tagli di lama for i = 1, 2 do -- inserisco la lavorazione local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. tostring( Proc.Id) .. '_' .. tostring( i) local nMchId = WM.AddMachining( Proc, sName, sCutting) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sCutting EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( { { Proc.Id, nOrd[i]}}) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- assegno il lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- assegno l'attacco e l'uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.CENT) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.CENT) -- nessun criterio per il braccio è necessario EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end end return true end --------------------------------------------------------------------- local function MakeMoreFaces( Proc, nRawId, b3Raw) -- con una faccia di fondo valida if Proc.Stype == 1 or Proc.Stype == 2 then -- recupero eventuale flag forzatura svuotatura local bPckt = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1) -- cerco la faccia con il maggior numero di adiacenze local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId) -- se necessario scambio le facce if Proc.Stype == 2 then nFacInd, dElev, nFacInd2, dElev2 = nFacInd2, dElev2, nFacInd, dElev end local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) local dMaxSlotThicknessForBlade = 25 local bIsSmallSlot = ( Proc.Fct == 3 and ( min( dH, dV) < dMaxSlotThicknessForBlade - 10 * GEO.EPS_SMALL) and vtN:getZ() > -0.01) -- se di fianco if not bPckt and Proc.Fct >= 3 and ( ( vtN:getZ() < WD.NZ_MINA) or bIsSmallSlot) then -- recupero elevazione faccia in feature local dSideElev = WL.GetFaceElevation( Proc.Id, nFacInd) -- se abilitata lavorazione ribasso con fresa di fianco e parametro Q03 abilitato local sMillOnSide, dTMaxDepth, dMaxMat, dDiam = WM.FindMilling( 'SideMill', nil, nil, nil, nil, min( dH, dV), nil, dSideElev) -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata local bDoubleMillOnSide = false if Proc.Double and Proc.Double == 2 then local sMillOnSideBackup = sMillOnSide sMillOnSide = WM.FindMilling( 'SideMill', nil, nil, nil, nil, min( dH, dV), nil, dSideElev, 'H1') if WM.IsMachiningOkForDouble( sMillOnSide) then bDoubleMillOnSide = true else sMillOnSide = sMillOnSideBackup end end local _, nUseMillOnSide = EvaluateQParam( Proc) -- se ho abilitata lavorazione di fresa di fianco if Proc.Fct >= 3 and sMillOnSide and nUseMillOnSide >= 1 and not bIsSmallSlot then -- cerco nei parametri utensili la nota di affondamento di fianco SIDEDEPTH local dMaxDepthOnSide = 0 local dMillDiam = 0 if EgtMdbSetCurrMachining( sMillOnSide) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') or dMaxDepthOnSide end end local bMakeFirstGroove local bLikeAsMakeFirstGroove local bInsertMach local dElevToPiece = WL.GetFaceElevation( Proc.Id, nFacInd, nRawId) -- Se distanza dal grezzo è minore della Max lavorazione laterale utensile if dElevToPiece < dMaxDepthOnSide then bInsertMach = true bMakeFirstGroove = false -- altrimenti la distanza è maggiore e se è sempre abilitata la lavorazione MillOnSide elseif dMaxDepthOnSide > 0 then bInsertMach = true bMakeFirstGroove = true end -- se posso eseguire la lavorazione per distanza inferiore utensile o lavorazione preceduta da sgossatura gola -- e gola più grande o uguale spessore utensile if bInsertMach and dMaxMat <= min( dH, dV) + 20 * GEO.EPS_SMALL then local nSinglePass = 0 bLikeAsMakeFirstGroove = bMakeFirstGroove -- se positivo setto il flag per lavorare singola passata bassa e disabilito sgrossatura if vtN:getZ() > 20 * GEO.EPS_SMALL then nSinglePass = 1 bMakeFirstGroove = false -- se negativo setto il flag per lavorare singola passata alta e disabilito sgrossatura elseif vtN:getZ() < -20 * GEO.EPS_SMALL then nSinglePass = 2 bMakeFirstGroove = false end return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, EgtIf( dMaxDepthOnSide, sMillOnSide, nil), dMaxDepthOnSide, bMakeFirstGroove, nil, nil, bLikeAsMakeFirstGroove, nSinglePass, nil, bDoubleMillOnSide) end else -- fresatura (se definita); se disponibile, cerco di usare un utensile che non lavori al limite della capacità di sottosquadro local dSideElevMultiplier = 1.1 local sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElevMultiplier * dSideElev) -- se non ho trovato un utensile un po' più grande del sottosquadro richiesto, passo alla ricerca standard if not sMilling then sMilling = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElev) dSideElevMultiplier = 1 end -- se Proc è settata per essere specchiata cerco la lavorazione adatta e verifico possa essere effettivamente specchiata bDoubleMillOnSide = false if Proc.Double and Proc.Double == 2 then local sMillOnSideBackup = sMillOnSide sMillOnSide = WM.FindMilling( 'SideGroove', nil, nil, nil, nil, min( dH, dV), nil, dSideElevMultiplier * dSideElev, 'H1') if WM.IsMachiningOkForDouble( sMillOnSide) then bDoubleMillOnSide = true else sMillOnSide = sMillOnSideBackup end end -- recupero i dati dell'utensile local dMaxMat = 1000 local dMaxDepthOnSide = 0 local bIsBlade = false if sMilling and EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then local dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0 bIsBlade = EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE ~= 0 if bIsBlade then dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dMaxMat dMaxDepthOnSide = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) else dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat dMaxDepthOnSide = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDEDEPTH', 'd') end if not dMaxDepthOnSide then local dMillDiamTh = EgtTdbGetCurrToolThDiam() or 60 dMaxDepthOnSide = ( dMillDiam - dMillDiamTh) / 2 end end end if sMilling and dElev < dMaxDepthOnSide then return MakeSideGrooveByMill( Proc, nFacInd, nRawId, b3Raw, sMilling, nil, nil, nil, nil, nil, nil, nil, bDoubleMillOnSide) -- altrimenti sega a catena else return MakeByChainSaw( Proc, nFacInd, nRawId, b3Raw, dElev, dH, dV) end end end local nFacet = EgtIf( bPckt or vtN:getZ() >= WD.NZ_MINA, nFacInd, nFacInd2) if nFacet then -- eseguo la svuotatura return MakeByPocketing( Proc, nFacet, nRawId, b3Raw, true) else local sErr = 'Side milling not possible' EgtOutLog( sErr) return true, sErr end -- fessura verticale elseif Proc.Stype == 3 then -- riordino le facce come contorno libero da lavorare a destra (sono una U) -- porto la faccia centrale in seconda posizione (indice 1) local nFacInd = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId) if nFacInd ~= 1 then EgtSurfTmSwapFacets( Proc.Id, 1, nFacInd) end -- verifico se la prima (indice 0) la deve precedere o seguire local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) local bAdj, ptAdj, _, _ = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) if bAdj and ( vtN ^ ( ptAdj - ptC)) * Z_AX() < 0 then EgtSurfTmSwapFacets( Proc.Id, 0, 2) end -- applico lavorazione di contorno libero return FreeContour.Make( Proc, nRawId, b3Raw) -- tunnel elseif Proc.Stype == 4 then -- riordino le facce come contorno libero da lavorare a destra (formano un anello chiuso e quindi posso partire da una qualunque) for i = 1, Proc.Fct - 2 do local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT) for j = i + 1, Proc.Fct do local bAdj, ptAdj, _, _ = EgtSurfTmFacetsContact( Proc.Id, i - 1, j - 1, GDB_ID.ROOT) if bAdj and ( vtN ^ ( ptAdj - ptC)) * Z_AX() > 0 then if i ~= j - 1 then EgtSurfTmSwapFacets( Proc.Id, i, j - 1) end break end end end -- applico lavorazione di contorno libero return FreeContour.Make( Proc, nRawId, b3Raw) end end --------------------------------------------------------------------- -- Applicazione della lavorazione function WPL.Make( Proc, nRawId, b3Raw) -- in base al tipo di feature attribuisco il significato dei parametri Q AssignQIdent( Proc) if Proc.Fct == 1 then return MakeOneFace( Proc, nRawId, b3Raw) elseif Proc.Fct == 2 then return MakeTwoFaces( Proc, nRawId, b3Raw) else return MakeMoreFaces( Proc, nRawId, b3Raw) end end --------------------------------------------------------------------- return WPL