-- ProcessFreeContour.lua by Egaltech s.r.l. 2024/03/24 -- Gestione calcolo profilo libero per Pareti -- 2021/11/15 Penna e chiodature sono sempre riportate sulla faccia sopra anche se nel progetto sono sotto. -- 2021/12/10 In taglio con lama aggiunta gestione SCC per testa Gearbox. -- 2022/01/13 Aggiunta gestione massimo affondamento in Z anche per pulizia spigoli con fresa 60deg (WD.MAX_CLEAN_CRN60). -- 2022/02/03 Corretto controllo massimo affondamento nella tavola. -- 2022/02/21 Corretti allungamenti/accorciamenti tagli inclinati con fresa. Migliorata gestione tagli trasversali per macchine travi. -- 2022/03/14 Corretto riconoscimento lato esterno per percorsi aperti. -- 2022/03/16 Ulteriore modifica per riconoscimento lato esterno (aggiunto uso vExtr a GetFacesExternalSide). -- 2022/04/03 Correzioni e modifiche per pulitura spigoli tipo 2 e 3. -- 2022/04/19 Aggiunta passibilita' fresatura ad affondamento ridotto quando non possibile completa o sega a catena. -- 2022/04/26 Migliorata gestione caso pocketing. -- 2022/08/05 Aggiunta segnalazione aree vietate non gestite. -- 2022/08/29 Corretta gestione tipo Pocket senza fondo (sono lavorabili da entrambe le parti con fresatura). -- 2022/12/13 Aggiunta la funzione Is3EdgesApprox per riconoscere come 3 lati anche facce con lati aggiuntivi molto corti (<15 mm) -- 2022/12/14 Aggiunto l'accorciamento della lama in caso di facce vicine orientate verso il basso -- 2023/02/28 In lavorazioni con sega a catena per invertire lato mandrino ora Invert + Left invece di MCH_SCC.OPPOSITE. -- 2023/03/08 In lavorazione con fresa, se imposto Tool_ID non si controlla più possa lavorare di testa. -- 2023/04/14 Aggiunta pulitura spigoli Q05=1 anche su sole fresature. -- 2023/04/17 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/06 Aggiunta gestione lavorazione per lamatura speciale affondata con Tool_ID specifico. -- 2023/07/26 In MakeByCut migliorata la scelta della fresa secondaria nel caso non sia disponibile una fresa di lunghezza sufficiente. -- 2023/09/12 Modifiche a GetTunnelDimension (asse deve essere com Z globale) e MakeLocalSurf per gestire finestre con lati inclinati. -- 2023/09/21 In MakeByMill modificato SCC per correggere caso con lama su testa fresa. -- 2023/09/26 In Is3EdgesApprox aggiunta cancellazione dei loop temporanei. -- 2023/10/02 Correzione a MakeCustomPath per calcolare correttamente puliture spigoli di tipo 2 (Clean 30) e 3 (Gola di Scarico). -- 2023/11/14 Spostamento di alcune funzioni in WallLib. -- Aggiunta dei FreeContour in doppio. -- 2023/12/13 In MakeByPocket aggiunta la possibilità di svuotare tasche passanti. -- 2024/03/24 Sostituite funzioni di Collision Detection (EgtCDe*) con quelle di verifica interferenza (EgtTest*). -- Tabella per definizione modulo local WPF = {} -- Include require( 'EgtBase') local WL = require( 'WallLib') EgtOutLog( ' WProcessFreeContour started', 1) -- Dati local WD = require( 'WallData') local WM = require( 'WMachiningLib') if WD.CHECK_MIN_Z_SAW == nil then WD.CHECK_MIN_Z_SAW = true end if not WD.MIN_Z_SAW then WD.MIN_Z_SAW = 0 end if not WD.MAX_CLEAN_CRN60 then WD.MAX_CLEAN_CRN60 = 150 end if not WD.MAX_CLEAN_CRN30 then WD.MAX_CLEAN_CRN30 = 68 end local WHISK_OFFS = 0.1 local WHISK_SAFE = 5 local MIN_LEN_CUT = 250 -- variabili assegnazione parametri Q local sTypeCornerCut = 'Q05' -- i -- variabile settaggio doppia lavorazione su angoo > 90 local bMakeTwinCut = true -- variabile per valore sfondamento spigolo local dExtraCorner = 1 -- angolo sottosquadra ammesso per fresa cono 30° local dAngleSmall = 70 --------------------------------------------------------------------- -- Riconoscimento della feature function WPF.Identify( Proc) return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and ( Proc.Prc == 250 or Proc.Prc == 251 or Proc.Prc == 252)) end --------------------------------------------------------------------- -- Classificazione della feature function WPF.Classify( Proc, b3Raw) -- se area vietata (LockOut) non faccio nulla if Proc.LockOut then return true end -- verifico se di tipo pocket local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1) -- recupero la curva associata local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if not AuxId then return false end AuxId = AuxId + Proc.Id local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) -- recupero il tipo di lavorazione local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0 local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') -- se tasca if bPocket then -- cerco la faccia di fondo della superfice (deve avere direzione circa quella di estrusione della curva) local nFacet for i = 1, Proc.Fct do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) if abs( vtN * vtExtr) > 0.99 then nFacet = i - 1 vtExtr = vtN break end end local bDown = ( nFacet and vtExtr:getZ() < - 0.5) return not bDown -- se altrimenti profilo orizzontale elseif abs( vtExtr:getZ()) < 0.5 then return false -- se penna o chiodatura va sempre bene (vengono sempre riportati sopra) elseif nCntType == 10 or nCntType == 20 then return true -- se altrimenti profilo verticale che non interessa tutta la sezione e non caso speciale con lamatura affondata elseif ( Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 2) and ( not nTool_ID or ( nTool_ID ~= ( WD.RECESSED_COUNTERBORE_TOOLID or 0)) or ( not EgtCurveIsACircle( AuxId))) then return false -- altrimenti è profilo verticale che interessa tutta la sezione o caso speciale con lamatura affondata else return true end end ---------------------------------------------------------------------- -- Classificazione del flip della feature per nesting -- return nFlip0, nFlip1 function WPF.FlipClassify( Proc, b3Raw) local nFlip0 = 0 local nFlip1 = 0 -- verifico se di tipo pocket local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1) -- recupero la curva associata se esiste local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if not AuxId then return false end AuxId = AuxId + Proc.Id local vtN = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local dVtNZ = vtN:getZ() -- se tasca if bPocket then -- verifico se è lavorabile da sopra nFlip0 = EgtIf( dVtNZ < -0.5, 0, 100) -- verifico se e' lavorabile da fliped: cambio segno al versore nFlip1 = EgtIf( -dVtNZ < -0.5, 0, 100) -- se altrimenti profilo orizzontale elseif abs( dVtNZ) < WD.NZ_MINA then return 0, 0 -- se altrimenti profilo verticale che non interessa tutta la sezione elseif Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() - 2 then return 0 , 0 -- altrimenti è profilo verticale che interessa tutta la sezione else local dVtNZMedia = 0 for i = 1, Proc.Fct do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT) dVtNZMedia = dVtNZMedia + vtN:getZ() end dVtNZMedia = dVtNZMedia / Proc.Fct if abs( dVtNZMedia) <= GEO.EPS_SMALL then nFlip0 = 100 nFlip1 = 100 elseif dVtNZMedia >= 0 + GEO.EPS_SMALL then nFlip0 = 75 nFlip1 = 50 else nFlip0 = 50 nFlip1 = 75 end end return nFlip0, nFlip1 end --------------------------------------------------------------------- local function VerifyCornerType( Proc) -- 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 nVal = EgtGetInfo( Proc.Id, sTypeCornerCut, 'i') return ( nVal or 0) end --------------------------------------------------------------------- local function IsPointOnRawLongEdges( ptCen, b3Raw) return ( abs( ptCen:getY() - b3Raw:getMin():getY()) < 0.1 or abs( ptCen:getY() - b3Raw:getMax():getY()) < 0.1) end --------------------------------------------------------------------- local function GetOtherRegions( nPartId) local vOthers = {} -- ciclo sui pezzi local nOtherId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL) while nOtherId do -- cerco le regioni marcate local nCount = 0 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 nCount = nCount + 1 table.insert( vOthers, { PartId = nOtherId, RegId = nRegId, Box = b3Reg}) end end nRegId = EgtGetNext( nRegId) end -- se non trovate regioni marcate, cerco regioni con la normale corretta if nCount == 0 then local nRegId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nOtherId, 'Outline') or GDB_ID.NULL) while nRegId do local vtN = EgtSurfFrNormVersor( nRegId, GDB_ID.ROOT) if EgtGetType( nRegId) == GDB_TY.SRF_FRGN 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 end -- passo al pezzo successivo nOtherId = EgtGetNextPartInRawPart( nOtherId) end return vOthers end --------------------------------------------------------------------- local function ReorderFaces( nIdSurf, nNumFacet) -- recupero le adiacenze di tutte le facce local vAdj = {} for i = 1, nNumFacet do -- recupero le adiacenze della faccia local vFacAdj = EgtSurfTmFacetAdjacencies( nIdSurf, 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 end -- sposto le facce isolate alla fine for i = #vAdj, 1, -1 do if vAdj[i] == 0 then if vAdj[#vAdj] == 0 then table.remove( vAdj, i) end EgtSurfTmSwapFacets( nIdSurf, i - 1, #vAdj) end end -- se facce tutte isolate, esco if #vAdj == 0 then return end -- cerco la faccia non isolata con il minor numero di adiacenze local nIdFace local nAdjMin = 1000 for i = 1, #vAdj do if vAdj[i] < nAdjMin then nAdjMin = vAdj[i] nIdFace = i end end -- se la faccia non isolata con minori adiacenze non è in prima posizione, eseguo scambio if nIdFace and nIdFace ~= 1 and nAdjMin == 1 then EgtSurfTmSwapFacets( nIdSurf, nIdFace-1, 0) end -- ordino le facce in modo da avere una sequenza di facce concatenate for i = 1, #vAdj - 1 do -- recupero l'angolo con la faccia successiva local bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, i, GDB_ID.ROOT) -- se non ho adiacenza if not bAdj then for j = i+1, #vAdj do bAdj, _, _, _ = EgtSurfTmFacetsContact( nIdSurf, i-1, j-1, GDB_ID.ROOT) -- se ho adiacenza scambio le facce if bAdj then EgtSurfTmSwapFacets( nIdSurf, i, (j-1)) break end 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 GetFacesExternalSide( Proc, vtExtr) -- 3=sinistra, 4=destra -- se meno di due facce considero esterno come dichiarato dal gruppo local nNumFacet = EgtSurfTmFacetCount( Proc.Id) if nNumFacet < 2 then return Proc.Grp end -- se facce isolate, considero esterno come dichiarato dal gruppo local bAdj, ptV1, ptV2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) if not bAdj then return Proc.Grp end -- calcolo dell'esterno rispetto all'avanzamento local ptC1, vtN1 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) local ptV = ( ptV1 + ptV2) / 2 local vtDir1 = ptV - ptC1 if ( vtN1 ^ vtDir1) * vtExtr > 0 then return 4 else return 3 end end --------------------------------------------------------------------- local function GetFacesData( Proc, bOpposite, bCalclForBlade, dToolDiam, dToolMaxDepth, dToolThick, nAddGrpId, b3Raw, nMasterNewProc) --se richiesto, copio la superficie nel gruppo ausiliario local nNewProc if nMasterNewProc then nNewProc = nMasterNewProc else nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL end -- recupero i dati di tutte le facce local vFace = {} local nNumFacet = EgtSurfTmFacetCount( nNewProc) for i = 1, nNumFacet do -- indice faccia corrente e precedente local nFac = EgtIf( bOpposite, nNumFacet - i, i - 1) local nPrecFac if bOpposite then if nNumFacet > 2 then nPrecFac = EgtIf( i == 1, 0, nFac + 1) else nPrecFac = EgtIf( i == 1, -1, nFac + 1) end else if nNumFacet > 2 then nPrecFac = EgtIf( i == 1, nNumFacet - 1, i - 2) else nPrecFac = EgtIf( i == 1, - 1, i - 2) end end -- recupero centro e normale della faccia local vtN = EgtSurfTmFacetNormVersor( nNewProc, nFac, GDB_ID.ROOT) -- recupero le dimensioni della faccia local frHV, 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) local dPrevAng = EgtIf( bAdj, dAng, 0) -- se angolo con faccia precedente negativo, calcolo anche angolo tra le facce nel piano local dPlanePrevAng = 0 if dPrevAng < 0 then local vtPrevN = EgtSurfTmFacetNormVersor( nNewProc, nPrecFac, GDB_ID.ROOT) local dCosA = ( Z_AX() ^ vtPrevN) * ( Z_AX() ^ vtN) dPlanePrevAng = -acos( dCosA) end -- calcolo l'angolo di inclinazione (dalla verticale) local dSideAng = asin( vtN:getZ()) -- salvo i dati vFace[i] = { Fac = nFac, Cen = frHV:getOrigin(), Norm = vtN, Len = dLen, Width = dWidth, PrevAng = dPrevAng, PlPrevAng = dPlanePrevAng, SideAng = dSideAng} 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 dLenY = dLen * abs( vFace[i].Norm:getX()) / sqrt( 1 - vFace[i].Norm:getZ() * vFace[i].Norm:getZ()) local nType = 0 if vFace[i].PrevAng < -0.1 or ( WD.BEAM_MACHINE and not IsPointOnRawLongEdges( vFace[i].Cen, b3Raw) and ( dLen > 0.5 * WD.CUT_MAX_LENGTH or dLenY > 0.4 * b3Raw:getDimY())) then dLen = dLen - EgtIf( bCalclForBlade, dWhisk, 0) nType = nType + 1 end if vFace[EgtIf( i < nNumFacet, i + 1, 1)].PrevAng < -0.1 or ( WD.BEAM_MACHINE and not IsPointOnRawLongEdges( vFace[i].Cen, b3Raw) and ( dLen > 0.5 * WD.CUT_MAX_LENGTH or dLenY > 0.4 * b3Raw:getDimY())) 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 -- numero dei lati local nEdges = #(EgtSurfTmFacetAdjacencies( nNewProc, i - 1)[1]) -- assegno i nuovi dati vFace[i].Depth = dDepth vFace[i].Whisk = dWhisk vFace[i].Type = nType vFace[i].Edges = nEdges end -- recupero le regioni degli altri pezzi local vOthers = GetOtherRegions( Proc.PartId) -- 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 - 2 * WHISK_OFFS) * vtDir local ptCross = ptDir + ( dToolThick - 2 * 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 - 2 * WHISK_OFFS) * vtDir local ptCross = ptDir + ( dToolThick - 2 * 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 -- se ciclo chiuso if abs( vFace[1].PrevAng) > 0.1 then -- verifico se c'è un solo tipo 3 e nessun tipo 0, 1 o 2 local nInd3 local nTot3 = 0 local nTot012 = 0 for i = 1, #vFace do local Face = vFace[i] if Face.Type == 0 or Face.Type == 1 or Face.Type == 2 then nTot012 = nTot012 + 1 elseif Face.Type == 3 then nTot3 = nTot3 + 1 nInd3 = i end end -- se trovato il caso, trasformo il 3 in 4 (per evitare problemi con fresature con la stessa faccia a inizio e fine) if nTot3 == 1 and nTot012 == 0 then vFace[nInd3].Type = 4 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.PrevAng, 1).. ' App='..EgtNumToString( Face.PlPrevAng, 1)..' D='..EgtNumToString( Face.Depth, 1)..' B='..EgtNumToString( Face.Whisk, 1).. ' As='..EgtNumToString( Face.SideAng, 1)..' T='..tostring( Face.Type)..' E='..tostring( Face.Edges) EgtOutLog( sOut) end return vFace, dMaxWidth, nNewProc end --------------------------------------------------------------------- local function GetTunnelDimension( nId, nPartId, nAddGrpId, bClosed) -- sono necessarie almeno 2 facce local nFacCnt = EgtSurfTmFacetCount( nId) if nFacCnt < 2 then return end -- recupero l'ingombro del pezzo local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- recupero centro e normale delle facce local ptC = {} local vtN = {} for i = 1, nFacCnt do ptC[i], vtN[i] = EgtSurfTmFacetCenter( nId, i - 1, GDB_ID.ROOT) end -- determino l'asse medio (le facce sono già ordinate consecutivamente) local vtAx = V_NULL() for i = 1, EgtIf( bClosed, nFacCnt, nFacCnt - 1) do local j = i % nFacCnt + 1 local vtOrtho = vtN[i] ^ vtN[j] if vtOrtho:normalize() then vtAx = vtAx + vtOrtho end end if not vtAx:normalize() or abs( vtAx:getZ()) < 0.5 then return end -- impongo come asse Z globale vtAx = Z_AX() -- recupero ingombro del tunnel nel riferimento globale local b3Box = EgtGetBBoxGlob( nId, GDB_BB.STANDARD) local dDepth = b3Box:getDimZ() -- creo faccia in basso (di poco sollevata) local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, b3Box:getMin() + 2 * GEO.EPS_SMALL * vtAx, vtAx, b3Solid, GDB_ID.ROOT) if not nSurfInt then return end -- 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 del pezzo EgtMove( nSurfInt, -2 * GEO.EPS_SMALL * vtAx, GDB_RT.GLOB) -- mi faccio dare il contorno della superfice e la ricreo in modo più corretto local nIdCont, nIdNum = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) if not nIdCont then return end -- elimino le entità allineate dello stesso tipo EgtMergeCurvesInCurveCompo( nIdCont, 2 * GEO.EPS_SMALL) EgtErase( nSurfInt) nSurfInt = EgtSurfTmByFlatContour( nAddGrpId, nIdCont, 2 * GEO.EPS_SMALL) EgtErase(nIdCont) -- ne recupero le dimensioni local _, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) -- cerco faccia del contorno con lunghezza vicino alla massima local nLongIdFace for i = 1, nFacCnt do local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nId, i - 1, GDB_ID.ROOT) if DimH > dDimMax - 100 * GEO.EPS_SMALL then nLongIdFace = i - 1 break end end return dDimMin, dDimMax, dDepth, vtAx, 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 MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick, bClosed) -- creo il percorso di lavorazione come contorni inferiori delle facce local nPath = {} for i = 1, #vGeom do -- ottengo curva inferiore 1 local ptP1, _, ptP3 = EgtSurfTmFacetOppositeSide( vGeom[i][1], vGeom[i][2], Z_AX() , GDB_ID.ROOT) -- creo linea local nId1 = EgtLine( nAddGrpId, ptP1, ptP3, GDB_RT.GLOB) table.insert( nPath, nId1) end local AuxId = EgtCurveCompo( nAddGrpId, nPath, true) -- offsetto a destra il percorso del raggio utensile EgtOffsetCurve( AuxId, dMillDiam / 2, GDB_OT.FILLET) -- spezzo il percorso nelle entità componenti local nId1st, nIdCount = EgtExplodeCurveCompo( AuxId) -- se il numero entità è diverso da quelle iniziali esco con errore if not nId1st then local sErr = 'Error : cannot make offset path' return 0, sErr end -- calcolo angoli tra le entità consecutive local nPathData = {} local nIdLast = nId1st + nIdCount - 1 for i = nId1st, nIdLast do if i < nIdLast or bClosed then local j = EgtIf( i < nIdLast, i + 1, nId1st) local vtDirFin = EgtEV( i, GDB_ID.ROOT) local vtDirSta = EgtSV( j, GDB_ID.ROOT) local dAng = GetAngleXY( vtDirFin, vtDirSta) local vtBisett = -vtDirFin + vtDirSta if not vtBisett:normalize() then vtBisett = VectorFromRotated( vtDirFin, Z_AX(), -90) end table.insert( nPathData, { i, dAng, vtBisett}) end end -- resetto la tabella nPath = {} AuxId = nil -- in base al tipo di ripresa spigolo modifico il percorso if nConeCut == 2 then -- acquisisco la lunghezza utensile local sMilling = WM.FindMilling( 'CleanCorner30') if not sMilling then local sErr = 'Error : CleanCorner 30 not found in library' return 0, sErr end -- recupero i dati dell'utensile local dMillDiam = 20 local dMillLength = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dMillLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dMillLength end end -- calcolo la lunghezza della linea da inserire in base all'angolo e alla lunghezza utensile local dLenAdd = abs(( dMillLength * sin( 33)) - ( dMillDiam / 2)) -- per ogni entità compongo la nuova lista per creare percorso for i = 1, nIdCount do -- aggiungo linea precedente table.insert( nPath, ( nId1st + i - 1)) -- se non è la linea finale e l'angolo tra le due facce è ammesso if ( i < nIdCount or bClosed) and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL) and nPathData[i][2] < -5 and nPathData[i][2] > -( 180 - dAngleSmall + 10 * GEO.EPS_SMALL) then -- aggiungo una retta sulla bisettrice local ptP1 = EgtEP( ( nId1st + i - 1), GDB_ID.ROOT) local vtExtrExit = nPathData[i][3] vtExtrExit:normalize() -- linea intermedia (componente lunghezza utensile in direzione bisettrice) local pEnd = ptP1 + ( dLenAdd * vtExtrExit) local nAuxId = EgtLine( nAddGrpId, ptP1, pEnd, GDB_RT.GLOB) table.insert( nPath, nAuxId) -- linea di ritorno nAuxId = EgtLine( nAddGrpId, pEnd, ptP1, GDB_RT.GLOB) table.insert( nPath, nAuxId) end end -- ricreo il percorso AuxId = EgtCurveCompo( nAddGrpId, nPath, true) -- altrimenti sfondo spigolo elseif nConeCut == 3 then -- per ogni entità compongo la nuova lista per creare percorso for i = 1, nIdCount do -- aggiungo linea precedente table.insert( nPath, ( nId1st + i - 1)) -- se non è la linea finale e l'angolo tra le due facce è ammesso if ( i < nIdCount or bClosed) and nPathData[i][2] < 0 then -- aggiungo una retta sulla bisettrice local ptP1 = EgtEP( ( nId1st + i - 1), GDB_ID.ROOT) local vtExtrExit = nPathData[i][3] vtExtrExit:normalize() vtExtrExit = -vtExtrExit -- calcolo di quanto entrare local dLenAdd = abs( (dMillDiam/2) / cos( nPathData[i][2]/2)) + dExtraCorner - ( dMillDiam / 2) -- linea intermedia (componente lunghezza utensile in direzione bisettrice) local pEnd = ptP1 + ( dLenAdd * vtExtrExit) local nAuxId = EgtLine( nAddGrpId, ptP1, pEnd, GDB_RT.GLOB) table.insert( nPath, nAuxId) -- linea di ritorno nAuxId = EgtLine( nAddGrpId, pEnd, ptP1, GDB_RT.GLOB) table.insert( nPath, nAuxId) end end -- ricreo il percorso AuxId = EgtCurveCompo( nAddGrpId, nPath, true) end if not AuxId then local sErr = 'Error : Impossibe make custom machining path' return 0, sErr end return AuxId end --------------------------------------------------------------------- local function CalcInterference( nNewProc, vtExtr, ptCentr, dDiam1, dDiam2, dTall1, dTall2, dDiam3, dTall3) local ptCentrGrid1 = ptCentr + ( vtExtr * 0.01) local frOriTool = Frame3d( ptCentrGrid1, vtExtr) local bColl1 = EgtTestConeSurface( frOriTool, dDiam1/2, dDiam2/2, dTall1, nNewProc, 0, GDB_RT.GLOB) if bColl1 then return true end local ptCentrGrid2 = ptCentr + ( vtExtr * ( dTall1 + 0.01)) frOriTool = Frame3d( ptCentrGrid2, vtExtr) local bColl2 = EgtTestCylSurface( frOriTool, dDiam2/2, (dTall2-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 = EgtTestCylSurface( 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) -- verifico che i tre punti siano definiti if not ptP1 or not ptP2 or not ptP3 then return nil end -- creo il contorno local nLoopId = EgtCurveCompoFromPoints( nAddGrpId, { ptP1, ptP2, ptP3, ptP1}, GDB_RT.GLOB) if not nLoopId then return nil end -- creo la superfice triangolare (quindi piana) local nFaceId = EgtSurfTmByFlatContour( nAddGrpId, nLoopId, 0.01) EgtErase( nLoopId) if not nFaceId then return nil end -- se normale negativa inverto local vtN1 = EgtSurfTmFacetNormVersor( nFaceId, 0, GDB_ID.ROOT) if vtN1:getZ() < -0.01 then EgtInvertSurf( nFaceId) end return nFaceId end --------------------------------------------------------------------- local function AddMillCornerMachining( nPartId, nNewProc, nFacInd, tFacAdj, 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 ReorderFacesFromTab( nNewProcLoc, vFace) -- acquisisco il numero della faccia local nFacCnt = EgtSurfTmFacetCount( nNewProcLoc) nFacInd = nFacCnt - 1 else 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 if not ptLocP1 or not ptLocP2 then return false, 'Error : clean corner with non adjacent faces' 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) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill local sUserNotes = 'VMRS=0;' -- aggiungo alle note massima elevazione sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( 0.0, 1) .. ';' 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 -- verifico se ciclo chiuso local bClosed = ( abs( vFace[1].PrevAng) > 0.1) -- 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, dDepth, nSurfInt local bMakeLocSurf -- RIMUOVERE if false and nFacCnt <= 4 then -- recupero profondità e faccia di fondo _, _, dDepth, _, _, nSurfInt = GetTunnelDimension( nNewProc, Proc.PartId, nAddGrpId, bClosed) if nSurfInt then -- aggiungo la faccia di fondo appena calcolata nNewProc = EgtSurfTmBySewing( nAddGrpId, { nNewProc, nSurfInt}, true) -- riordino le facce ReorderFacesFromTab( nNewProc, vFace) -- aggiorno numero di facce e assegno indice di quella di fondo (sempre ultima) nFacCnt = EgtSurfTmFacetCount( nNewProc) nFacInd = nFacCnt - 1 else return true end -- FINE PARTE DA RIMUOVERE else bMakeLocSurf = true end -- 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 -- 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 -- ricavo i tre punti per eventuale superficie locale local ptLoc1, ptLoc2, ptLoc3 -- 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 GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen) local CosA = abs( vtNz) if CosA >= 0.05 then local SinA = sqrt( 1 - CosA * CosA) local dRad = dDiamTh / 2 + dMillDiam / 2 * EgtIf( vtNz > 0, -1, 1) local dSlantFreeLen = dFreeLen - ( dRad * CosA / SinA) return min( dMaxDepth, dSlantFreeLen) else return dMaxDepth end end --------------------------------------------------------------------- local function AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId) -- flag per fresature non passanti local bNotThrou local dThick local dOriDepth -- recupero i dati dell'utensile local dMillDiam = 20 local dMaxDepth = 0 local dFreeLen = 0 local dDiamTh = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMillDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dMillDiam dDiamTh = EgtTdbGetCurrToolThDiam() dFreeLen = EgtTdbGetCurrToolMaxDepth() dMaxDepth = EgtIf( WD.MILL_MAX_DEPTH_AS_MAT, EgtTdbGetCurrToolParam( MCH_TP.MAXMAT), dFreeLen) or dMaxDepth end end -- verifico se le facce hanno alcuni lati molto corti e possono quindi essere approssimate a 3 lati for currentFace = 1, #vFace do if WL.Is3EdgesApprox( Proc, vFace[currentFace].Fac, nAddGrpId) then vFace[currentFace].Is3EdgesApprox = true end end -- verifico se ciclo chiuso local bClosed = ( abs( vFace[1].PrevAng) > 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 and ( vFace[#vFace].Edges > 3 and not vFace[#vFace].Is3EdgesApprox)) or ( vFace[#vFace].Type & 2) ~= 0) then while i <= #vFace and vFace[i].Type == 4 and ( vFace[i].Edges > 3 and not vFace[i].Is3EdgesApprox) and abs( vFace[i].SideAng) < 0.1 do i = i + 1 end end -- se facce tutte da saltare, parto dall'inizio local bAllType4 = ( i > #vFace) if bAllType4 then i = 1 end while i <= #vFace do -- se inizio faccia senza taglio e non è successiva di senza taglio, inserisco una fresatura local j = EgtIf( i > 1, i - 1, EgtIf( bClosed, #vFace, nil)) if ( vFace[i].Type & 1) ~= 0 and ( not j or vFace[j].Type == 0 or vFace[j].Type == 1 or abs( vFace[i].SideAng) > 0.1 or abs( vFace[j].SideAng) > 0.1) then -- inserisco la lavorazione local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) local nMchId = WM.AddMachining( Proc, sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return 0, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- calcolo l'affondamento local dDepth = vFace[i].Width + WD.CUT_EXTRA dThick = vFace[i].Width local vtNz = vFace[i].Norm:getZ() if WD.CHECK_MIN_Z_SAW then if vtNz >= 0 then dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW) else dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz)) end end local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen) -- se affondamento superiore ai limiti della fresa if dDepth > dCurrMaxDepth then dOriDepth = dDepth -- lo limito e tolgo eventuali Tabs dDepth = dCurrMaxDepth EgtSetMachiningParam( MCH_MP.LEAVETAB, false) bNotThrou = true end -- tolgo i Tabs se devo rimuovere lo sfrido if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) local dSal = 0 if #vFace == 1 then dSal = -dMillDiam / 2 end -- se angolo interno prima if vFace[i].PrevAng < -30 then local dSinA = -sin( vFace[i].PlPrevAng + 90) local dTanA = -tan( vFace[i].PlPrevAng + 90) dSal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[i].Width * vFace[i].Norm:getZ() * dTanA) -- se faccia precedente inclinata verso il basso if j and vFace[j].Norm:getZ() < -0.017 then dSal = dSal + vFace[j].Width * vFace[j].Norm:getZ() end -- se angolo esterno prima elseif vFace[i].PrevAng > 30 then -- se faccia precedente inclinata verso il basso if j and vFace[j].Norm:getZ() < -0.017 then dSal = dSal - vFace[j].Width * vFace[j].Norm:getZ() end end local dEal = vFace[i].Whisk - vFace[i].Len -- se faccia precedente inclinata verso il basso prolungo il finale per adeguarmi all percorso della lama if j and vFace[j].Norm:getZ() < -0.017 then dEal = dEal - vFace[j].Width * vFace[j].Norm:getZ() end -- se angolo interno prima e faccia precedente inclinata verso l'alto oltre 16.1deg if vFace[i].PrevAng < -30 and j and vFace[j].Norm:getZ() < 0.96078 and vFace[j].Norm:getZ() > 0 then dEal = dEal + vFace[j].Width * vFace[j].Norm:getZ() end -- se angolo interno dopo e faccia successiva inclinata verso l'alto oltre 16.1deg local k = EgtIf( i < #vFace, i + 1, EgtIf( bClosed, 1, nil)) if k and vFace[k].PrevAng < -30 and vFace[k].Norm:getZ() < 0.96078 and vFace[k].Norm:getZ() > 0 then dEal = dEal + vFace[k].Width * vFace[k].Norm:getZ() -- se l'inclinazione è inferiore a 46.1deg if vFace[k].Norm:getZ() > 0.72055 then dEal = dEal - vFace[k].Width end end EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno utilizzo faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if abs( vFace[i].Norm:getZ()) < GEO.EPS_SMALL then nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- scrivo nell'operazione il vettore normale alla superfice che servirà per il doppio EgtSetInfo( nMchId or GDB_ID.NULL, 'NORM_SUM', vFace[i].Norm) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return 0, sErr end end -- se tutta la faccia o la sua fine senza taglio, inserisco una fresatura if ( vFace[i].Type & 2) ~= 0 or ( vFace[i].Type == 4 and ( vFace[i].Edges > 3 and not vFace[i].Is3EdgesApprox)) then -- inserisco la lavorazione local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) local nMchId = WM.AddMachining( Proc, sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return 0, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- calcolo l'affondamento local dDepth = vFace[i].Width + WD.CUT_EXTRA dThick = vFace[i].Width local vtNz = vFace[i].Norm:getZ() if WD.CHECK_MIN_Z_SAW then if vtNz >= 0 then dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW) else dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz)) end end local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen) -- se affondamento superiore ai limiti della fresa if dDepth > dCurrMaxDepth then dOriDepth = dDepth -- lo limito e tolgo eventuali Tabs dDepth = dCurrMaxDepth EgtSetMachiningParam( MCH_MP.LEAVETAB, false) bNotThrou = true end -- tolgo i Tabs se devo rimuovere lo sfrido if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end -- aggiungo geometria local vGeom = {{ Proc.Id, vFace[i].Fac}} local dSal = EgtIf( ( vFace[i].Type & 2) ~= 0, vFace[i].Whisk - vFace[i].Len, 0) local dEal = 0 local OrigI = i local OrigH = j local LastJ i = i + 1 local j = EgtIf( i <= #vFace, i, EgtIf( bAllType4 or not bClosed, nil, 1)) while j and ( ( vFace[j].Type & 1) ~= 0 or ( vFace[j].Type == 4 and ( vFace[j].Edges > 3 and not vFace[j].Is3EdgesApprox))) and abs( vFace[j].SideAng) < 0.1 and abs( vFace[OrigI].SideAng) < 0.1 do table.insert( vGeom, { Proc.Id, vFace[j].Fac}) LastJ = j dEal = EgtIf( ( vFace[j].Type & 1) ~= 0, vFace[j].Whisk - vFace[j].Len, 0) if ( vFace[j].Type & 1) ~= 0 then break end i = i + 1 j = EgtIf( j + 1 <= #vFace, j + 1, EgtIf( bAllType4 or not bClosed, nil, 1)) end -- se faccia singola è da fare tutta senza oltrepassare estremi if #vFace == 1 and vFace[OrigI].Type == 4 and ( vFace[OrigI].Edges > 3 and not vFace[OrigI].Is3EdgesApprox) then dSal = -dMillDiam / 2 dEal = -dMillDiam / 2 -- altrimenti va verificato else -- se lavorazione completa su faccia iniziale if vFace[OrigI].Type == 4 and ( vFace[OrigI].Edges > 3 and not vFace[OrigI].Is3EdgesApprox) then -- se angolo interno prima if vFace[OrigI].PrevAng < -30 then local dSinA = -sin( vFace[OrigI].PlPrevAng + 90) local dTanA = -tan( vFace[OrigI].PlPrevAng + 90) dSal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[OrigI].Width * vFace[OrigI].Norm:getZ() * dTanA) -- se faccia precedente inclinata verso il basso if OrigH and vFace[OrigH].Norm:getZ() < -0.017 then dSal = dSal + vFace[OrigH].Width * vFace[OrigH].Norm:getZ() end -- se angolo esterno prima elseif vFace[OrigI].PrevAng > 30 then -- se faccia precedente inclinata verso il basso if OrigH and vFace[OrigH].Norm:getZ() < -0.017 then dSal = dSal - vFace[OrigH].Width * vFace[OrigH].Norm:getZ() end end end -- se lavorazione completa o finale su faccia finale local LastFace = ( LastJ or OrigI) local OrigK = EgtIf( LastFace < #vFace, LastFace + 1, EgtIf( bClosed, 1, nil)) if ( vFace[LastFace].Type == 4 and ( vFace[LastFace].Edges > 3 and not vFace[LastFace].Is3EdgesApprox)) or ( LastFace == OrigI and ( vFace[LastFace].Type & 2) ~= 0) then -- se angolo interno dopo if OrigK and vFace[OrigK].PrevAng < -30 then local dSinA = -sin( vFace[OrigK].PlPrevAng + 90) local dTanA = -sin( vFace[OrigK].PlPrevAng + 90) dEal = -dMillDiam / 2 * ( 1 + ( 1 + dSinA) * dTanA) + min( 0, vFace[OrigI].Width * vFace[OrigI].Norm:getZ() * dTanA) -- se faccia successiva inclinata verso il basso if vFace[OrigK].Norm:getZ() < -0.017 then dEal = dEal + vFace[OrigK].Width * vFace[OrigK].Norm:getZ() end -- se angolo esterno dopo elseif OrigK and vFace[OrigK].PrevAng > 30 then -- se faccia successiva inclinata verso il basso if vFace[OrigK].Norm:getZ() < -0.017 then dEal = dEal - vFace[OrigK].Width * vFace[OrigK].Norm:getZ() end end end -- per sola lavorazione finale if LastFace == OrigI and ( vFace[LastFace].Type & 2) ~= 0 then -- se angolo interno dopo e faccia successiva inclinata verso l'alto oltre 16.1 deg if OrigK and vFace[OrigK].PrevAng < -30 and vFace[OrigK].Norm:getZ() < 0.96078 and vFace[OrigK].Norm:getZ() > 0 then dSal = dSal + vFace[OrigK].Width * vFace[OrigK].Norm:getZ() end -- se angolo interno prima e faccia precedente inclinata verso l'alto oltre 16.1 deg if vFace[OrigI].PrevAng < -30 and OrigH and vFace[OrigH].Norm:getZ() < 0.96078 and vFace[OrigH].Norm:getZ() > 0 then dSal = dSal + vFace[OrigH].Width * vFace[OrigH].Norm:getZ() -- se l'inclinazione è inferiore a 46.1deg if vFace[OrigH].Norm:getZ() > 0.72055 then dSal = dSal - vFace[OrigH].Width end end end -- se percorso chiuso e completo con fresa if bClosed and bAllType4 then dSal = 0 dEal = 0 end -- se faccia singola non oltrepasso l'estremo finale if #vFace == 1 then dEal = -dMillDiam / 2 end end -- se non devo scaricare l'angolo o la faccia è inclinata if nConeCut <= 1 or abs( vFace[OrigI].SideAng) > 0.1 then EgtSetMachiningGeometry( vGeom) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- tolgo i Tabs se devo rimuovere lo sfrido if nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno utilizzo faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP) -- posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if abs( vFace[OrigI].Norm:getZ()) < GEO.EPS_SMALL then nSCC = EgtIf( abs( vFace[OrigI].Norm:getX()) > abs( vFace[OrigI].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- altrimenti se devo fare rientranza per inserimento utensile cono 30° elseif nConeCut == 2 then -- eseguo la costruzione del percorso local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, dThick, bClosed and bAllType4) if nPathId == 0 then return 0, sErr end EgtSetMachiningGeometry({{ nPathId, -1}}) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno utilizzo faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) -- assegno affondamento -- EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) if bNotThrou then EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth - dOriDepth)) else EgtSetMachiningParam( MCH_MP.DEPTH, 0) end -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) -- posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP) -- altrimenti se devo scaricare l'angolo elseif nConeCut == 3 then -- eseguo la costruzione del percorso local nPathId, sErr = MakeCustomPath( vGeom, nConeCut, dMillDiam, nAddGrpId, nil, bClosed and bAllType4) if nPathId == 0 then return 0, sErr end EgtSetMachiningGeometry({{ nPathId, -1}}) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno affondamento if bNotThrou then EgtSetMachiningParam( MCH_MP.DEPTH, ( dDepth - dOriDepth)) else EgtSetMachiningParam( MCH_MP.DEPTH, 0) end -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) -- posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_XP) end --scrivo nell'operazione il vettore somma delle normali alle superfici che servirà per il doppio local vtNSum = Vector3d( 0, 0, 0) for iGeom = 1, #vGeom do local nFace = vGeom[iGeom][2] vtNSum = vtNSum + Proc.Face[ nFace + 1].VtN end EgtSetInfo( nMchId or GDB_ID.NULL, 'NORM_SUM', vtNSum) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return 0, sErr end else i = i + 1 end end -- aggiungo eventuali fresature a metà faccia for i =1, #vFace do if vFace[i].Split then -- inserisco la lavorazione local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_M' local nMchId = WM.AddMachining( Proc, sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return 0, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- calcolo l'affondamento local dDepth = vFace[i].Width + WD.CUT_EXTRA dThick = vFace[i].Width local vtNz = vFace[i].Norm:getZ() if WD.CHECK_MIN_Z_SAW then if vtNz >= 0 then dDepth = min( dDepth, vFace[i].Width - WD.MIN_Z_SAW) else dDepth = min( dDepth, dDepth - WD.MIN_Z_SAW + dMillDiam * vtNz / sqrt( 1 - vtNz * vtNz)) end end local dCurrMaxDepth = GetMaxDepth( vtNz, dMillDiam, dDiamTh, dMaxDepth, dFreeLen) -- se affondamento superiore ai limiti della fresa if dDepth > dCurrMaxDepth then dOriDepth = dDepth -- lo limito e tolgo eventuali Tabs dDepth = dCurrMaxDepth EgtSetMachiningParam( MCH_MP.LEAVETAB, false) bNotThrou = true end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) local dSal = vFace[i].Whisk - vFace[i].Len / 2 local dEal = vFace[i].Whisk - vFace[i].Len / 2 EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- assegno utilizzo faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) -- posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if abs( vFace[i].Norm:getZ()) < GEO.EPS_SMALL then nSCC = EgtIf( abs( vFace[i].Norm:getX()) > abs( vFace[i].Norm:getY()), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- scrivo nell'operazione il vettore normale alla superfice che servirà per il doppio EgtSetInfo( nMchId or GDB_ID.NULL, 'NORM_SUM', vFace[i].Norm) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return 0, sErr end end end -- se fresature non sono passanti if bNotThrou then return 2, dMillDiam, dThick end return 1, dMillDiam, dThick end --------------------------------------------------------------------- local function AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) -- flag per tagli non passanti local bNotThrou local dThick -- recupero i dati dell'utensile local dSawDiam = 0 local dMaxDepth = 0 local dSawThick = 0 if EgtMdbSetCurrMachining( sSawing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end -- Calcolo angolo 3° asse rot (da direz. utensile) local sRot3Ang = 'A1=180' if WD.GetChainSawBlockedAxis then sRot3Ang = WD.GetChainSawBlockedAxis( 1) end -- ciclo di inserimento dei tagli con sega a catena for i = 1, #vFace do -- se inizio faccia non tagliato completamente, inserisco un ripasso con sega a catena if ( vFace[i].Type & 1) ~= 0 then -- inserisco la lavorazione local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) local nMchId = WM.AddMachining( Proc, sName, sSawing) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return 0, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- calcolo l'affondamento local dDepth = vFace[i].Width + min( WD.CUT_EXTRA, -WD.MIN_Z_SAW) dThick = vFace[i].Width -- se affondamento superiore ai limiti della sega a catena if dDepth > dMaxDepth then dDepth = dMaxDepth bNotThrou = true end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) local dSal = - dSawDiam / 2 local dEal = vFace[i].Whisk - vFace[i].Len - dSawDiam / 2 EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- assegno utilizzo faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- assegno lato di lavoro e inversione direzione movimento if vFace[i].Norm:getX() < 0.018 then EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) else EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) end -- posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return 0, sErr end end -- se fine faccia non tagliato completamente o faccia non tagliata completamente e abbastanza lunga, inserisco un ripasso con sega a catena if ( vFace[i].Type & 2) ~= 0 or ( vFace[i].Type == 4 and ( vFace[i].Edges > 3 and not vFace[i].Is3EdgesApprox) and vFace[i].Len > dSawDiam + 1) then -- inserisco la lavorazione local sName = 'Free_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) local nMchId = WM.AddMachining( Proc, sName, sSawing) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return 0, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- calcolo l'affondamento local dDepth = vFace[i].Width + min( WD.CUT_EXTRA, -WD.MIN_Z_SAW) dThick = vFace[i].Width -- se affondamento superiore ai limiti della sega a catena if dDepth > dMaxDepth then dDepth = dMaxDepth bNotThrou = true end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vFace[i].Fac}}) local dSal = - dSawDiam / 2 local dEal = - dSawDiam / 2 if ( vFace[i].Type & 2) ~= 0 then dSal = vFace[i].Whisk - vFace[i].Len - dSawDiam / 2 end EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- assegno utilizzo faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, sRot3Ang) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- assegno lato di lavoro e inversione direzione movimento if vFace[i].Norm:getX() < 0.018 then EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) else EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) end -- posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return 0, sErr end end end -- se fresature non sono passanti if bNotThrou then return 2, dSawThick, dThick end return 1, dSawThick, dThick end --------------------------------------------------------------------- local function AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick) -- verifico se ciclo chiuso local bClosed = ( abs( vFace[1].PrevAng) > 0.1) -- ciclo di inserimento dei tagli sulle facce del contorno in esame for i = 1, #vFace do -- verifico se faccia da saltare, perchè macchina travi e faccia su bordo longitudinale esterno già finito local bToSkip = ( WD.BEAM_MACHINE and IsPointOnRawLongEdges( vFace[i].Cen, b3Raw)) -- se non è faccia da saltare, inserisco il taglio di lama if not bToSkip and vFace[i].Type ~= 4 then -- indice del successivo local j = EgtIf( i < #vFace, i + 1, 1) -- indice del precedente local h = EgtIf( i > 1, i - 1, EgtIf( bClosed, #vFace, nil)) -- inserisco la lavorazione local sName = 'Cut_' .. ( EgtGetName( Proc.PartId) or tostring( Proc.PartId)) .. '_' .. 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) local dSpeed = EgtGetMachiningParam( MCH_MP.SPEED) local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) local bGearbox = EgtGetInfo( EgtGetHeadId( sHead) or GDB_ID.NULL, 'Gearbox', 'b') -- aggiungo geometria EgtSetMachiningGeometry( { { Proc.Id, vFace[i].Fac}}) -- calcolo l'affondamento local dDepth = vFace[i].Depth local vtNz = vFace[i].Norm:getZ() if WD.CHECK_MIN_Z_SAW then if vtNz >= 0 then dDepth = min( dDepth, -WD.MIN_Z_SAW) else dDepth = min( dDepth, -WD.MIN_Z_SAW + dSawThick * vtNz) end end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- verifico se va invertita la direzione di lavorazione perchè faccia verso l'alto (angolo maggiore di 0.01 deg) local bInvert = ( vFace[i].Norm:getZ() > 0.0001745) -- imposto inversione EgtSetMachiningParam( MCH_MP.INVERT, bInvert) -- imposto lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bInvert, MCH_SAW_WS.LEFT, MCH_SAW_WS.RIGHT)) -- lato mandrino ( standard a sinistra se rotazione CCW, altrimenti a destra, oppure da funzione di macchina) local nHeadSide = EgtIf( dSpeed < 0, MCH_SAW_HS.LEFT, MCH_SAW_HS.RIGHT) if WD.GetSawHeadSide then nHeadSide = WD.GetSawHeadSide( dSpeed, sHead) end EgtSetMachiningParam( MCH_MP.HEADSIDE, nHeadSide) -- assegno i dati di attacco (sicurezza solo se angolo interno) local nLeadIn = MCH_SAW_LI.CENT if ( not bInvert and ( vFace[i].Type & 1) ~= 0) or ( bInvert and ( vFace[i].Type & 2) ~= 0) then nLeadIn = MCH_SAW_LI.STRICT end EgtSetMachiningParam( MCH_MP.LEADINTYPE, nLeadIn) local dSal = 0 if ( not bInvert and vFace[i].PrevAng < -0.1) or ( bInvert and vFace[j].PrevAng < -0.1) then -- se faccia precedente inclinata verso il basso if not bInvert and h and vFace[h].Norm:getZ() < -0.017 then dSal = vFace[h].Width * vFace[h].Norm:getZ() - WHISK_SAFE elseif bInvert and j and vFace[j].Norm:getZ() < -0.017 then dSal = vFace[j].Width * vFace[j].Norm:getZ() - WHISK_SAFE else dSal = -WHISK_SAFE end end EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) -- assegno i dati di uscita (sicurezza solo se angolo interno) local nLeadOut = MCH_SAW_LO.CENT if ( not bInvert and ( vFace[i].Type & 2) ~= 0) or ( bInvert and ( vFace[i].Type & 1) ~= 0) then nLeadOut = MCH_SAW_LO.STRICT end EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, nLeadOut) local dEal = 0 if ( not bInvert and vFace[j].PrevAng < -0.1) or ( bInvert and vFace[i].PrevAng < -0.1) then -- se faccia precedente inclinata verso il basso if not bInvert and j and vFace[j].Norm:getZ() < -0.017 then dEal = vFace[j].Width * vFace[j].Norm:getZ() - WHISK_SAFE elseif bInvert and h and vFace[h].Norm:getZ() < -0.017 then dEal = vFace[h].Width * vFace[h].Norm:getZ() - WHISK_SAFE else dEal = -WHISK_SAFE end end EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- posizione braccio porta testa if not bGearbox then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.NONE) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_NEAR) end -- eseguo local bApplyOk = EgtApplyMachining( true, false) if not bApplyOk then -- provo a invertire direzione, lato di lavoro e attacco/uscita EgtSetMachiningParam( MCH_MP.INVERT, not bInvert) EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( not bInvert, MCH_SAW_WS.LEFT, MCH_SAW_WS.RIGHT)) EgtSetMachiningParam( MCH_MP.LEADINTYPE, EgtIf( nLeadOut == MCH_SAW_LO.STRICT, MCH_SAW_LI.STRICT, MCH_SAW_LI.CENT)) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, EgtIf( nLeadIn == MCH_SAW_LI.STRICT, MCH_SAW_LO.STRICT, MCH_SAW_LO.CENT)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) -- ri-eseguo bApplyOk = EgtApplyMachining( true, false) if not bApplyOk then local nErr, sErr = EgtGetLastMachMgrError() -- se direzione irraggiungibile (solitamente lama su testa fresa 5A e taglio inclinato) si imposta di usare fresa if nErr == 2215 then EgtOutLog( ' Warning : sawing impossible due to unreachable direction, try milling') EgtRemoveOperation( nMchId) vFace[i].Type = 4 else EgtSetOperationMode( nMchId, false) return false, sErr end end end -- se limite lunghezza di taglio e taglio lo supera if bApplyOk and WD.CUT_MAX_LENGTH and vFace[i].Len > WD.CUT_MAX_LENGTH then -- sdoppio la lavorazione local sSouName = EgtGetName( nMchId) local nNewMchId = EgtCopyMachining( sSouName..'_B', sSouName) --accorciamento iniziale della seconda EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_SAW_LI.STRICT) EgtSetMachiningParam( MCH_MP.STARTADDLEN, -vFace[i].Len/2) --accorciamento finale della prima EgtSetCurrMachining( nMchId) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_SAW_LO.STRICT) EgtSetMachiningParam( MCH_MP.ENDADDLEN, -vFace[i].Len/2) -- segnalo spezzatura lavorazione faccia vFace[i].Split = true end end end return true end --------------------------------------------------------------------- local function MakeByCut( Proc, nRawId, b3Raw) local sWarn = '' -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- recupero la curva associata local bOpposite = false local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') if AuxId then AuxId = AuxId + Proc.Id local vtExtr= EgtCurveExtrusion( AuxId, GDB_RT.GLOB) if vtExtr then bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0) if GetFacesExternalSide( Proc, vtExtr) ~= Proc.Grp then bOpposite = not bOpposite end end end -- altezza massima delle facce local dWidth = 0 for i = 1, Proc.Fct do local _, _, dFctW = WL.GetFaceHvRefDim( Proc.Id, i - 1) dWidth = max( dWidth, dFctW) end -- lettura parametri (probabile/i parametro/i Q) local nConeCut = VerifyCornerType( Proc) -- recupero la lavorazione di taglio con lama e i suoi parametri (dapprima cerco quella che possa tagliare completamente) local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') local sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard', dWidth, nTool_ID) if not sCutting then sCutting, dSawDiam, dSawThick, dSawMaxDepth = WM.FindCutting( 'Standard', nil, nTool_ID) sWarn = 'Warning : elevation bigger than max sawcut depth' end if not sCutting then local sErr = 'Error : cutting not found in library' EgtOutLog( sErr) return false, sErr end -- gruppo ausiliario local nAddGrpId = WL.GetAddGroup( Proc.PartId) -- recupero i dati di tutte le facce local vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, true, dSawDiam, dSawMaxDepth, dSawThick, nAddGrpId, b3Raw, nil) -- inserimento dei tagli di lama local bCtOk, sCtErr = AddCuts( sCutting, vFace, Proc, nRawId, b3Raw, dSawThick) if not bCtOk then return bCtOk, sCtErr end -- se richiesta solo lama, esco local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0 if nCntType == 1 and nTool_ID ~= 0 then return true, sWarn end -- se ci sono facce inclinate, escludo la sega a catena local bSlanting = false for i = 1, #vFace do if abs( vFace[i].Norm:getZ()) > 0.01 then bSlanting = true break end end -- recupero la lavorazione con sega a catena local sSawing = WM.FindSawing( 'Sawing') -- recupero la lavorazione di fresatura local sMilling, dMillMaxDepth = WM.FindMilling( 'FreeContour', dMaxWidth + WD.CUT_EXTRA, nil, nil, nil, nil, true) local sMilling2 = WM.FindMilling( 'FreeContour', nil, nil, nil, nil, nil, true) if not sMilling and ( not sSawing or bSlanting) then -- se non trovo una fresa di lunghezza sufficiente, prendo la più lunga disponibile local sMillingMaxLength = WM.FindMilling( 'FreeContour', 0.8 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or WM.FindMilling( 'FreeContour', 0.6 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or WM.FindMilling( 'FreeContour', 0.4 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or WM.FindMilling( 'FreeContour', 0.2 * ( dMaxWidth + WD.CUT_EXTRA), nil, nil, nil, nil, true) or WM.FindMilling( 'FreeContour', nil, nil, nil, nil, nil, true) sMilling = sMillingMaxLength if not sMilling then local sErr = 'Error : milling not found in library' EgtOutLog( sErr) return false, sErr end end -- se possibile, inserimento delle fresature local bDone = false if sMilling then local nMlOk, sMlErr, dThick = AddMillings( sMilling, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId) if nMlOk == 0 then return false, sMlErr end bDone = ( dThick ~= nil) -- se ci sono almeno due facce e lavorato almeno un angolo if Proc.Fct >= 2 and bDone then -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite -- o con fresa cono piccola e spessore sotto il limite if ( nConeCut == 1 and nMlOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL)) or ( nConeCut == 2 and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL)) then local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, sMlErr, nAddGrpId, dThick, nNewProc, 0, true) if not bMcok then return bMcok, sMcErr end else -- messaggi nel log if nConeCut == 1 then if nMlOk ~= 1 then local sErr = 'Clean corner 60° not applid because Milling not thru the thickness' EgtOutLog( sErr) else local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2) EgtOutLog( sErr) end elseif nConeCut == 2 then local sErr = 'Clean corner 30° not applid because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN30: ' .. EgtNumToString( WD.MAX_CLEAN_CRN30 , 2) EgtOutLog( sErr) end end end -- altrimenti provo con la sega a catena elseif sSawing then local nCsOk, sCsErr, dThick = AddSawings( sSawing, vFace, Proc, nRawId, b3Raw) if nCsOk == 0 then return false, sCsErr end bDone = ( dThick ~= nil) -- se ci sono almeno due facce e lavorato almeno un angolo if Proc.Fct >= 2 and bDone then -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite if nConeCut == 1 and nCsOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, sCSErr, nAddGrpId, nil, nNewProc, 0, true) if not bMcok then return bMcok, sMcErr end else if nConeCut == 1 then if nCsOk ~= 1 then local sErr = 'Clean corner 60° not applied because Chainsawing not thru the thickness' EgtOutLog( sErr) else local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2) EgtOutLog( sErr) end elseif nConeCut == 2 then local sErr = 'Not possible apply Clean corner 30° after use sawing' EgtOutLog( sErr) end end end end -- altrimenti provo con fresa ad affondamento ridotto if not bDone then local nMlOk, sMlErr, dThick = AddMillings( sMilling2, vFace, Proc, nRawId, b3Raw, nConeCut, nAddGrpId) if nMlOk == 0 then return false, sMlErr end -- se ci sono almeno due facce e lavorato almeno un angolo if Proc.Fct >= 2 and dThick then -- se abilitata la lavorazione corner con stop macchina e lavorazione precedente passante e spessore sotto il limite -- o con fresa cono piccola e spessore sotto il limite if ( nConeCut == 1 and nMlOk == 1 and dThick <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL)) or ( nConeCut == 2 and dThick <= ( WD.MAX_CLEAN_CRN30 + 20 * GEO.EPS_SMALL)) then local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, sMlErr, nAddGrpId, dThick, nNewProc, 0, true) if not bMcok then return bMcok, sMcErr end else -- messaggi nel log if nConeCut == 1 then if nMlOk ~= 1 then local sErr = 'Clean corner 60° not applid because Milling not thru the thickness' EgtOutLog( sErr) else local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2) EgtOutLog( sErr) end elseif nConeCut == 2 then local sErr = 'Clean corner 30° not applid because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN30: ' .. EgtNumToString( WD.MAX_CLEAN_CRN30 , 2) EgtOutLog( sErr) end end sWarn = 'Depth reduced to mill capabilities' end end return true, sWarn end --------------------------------------------------------------------- local function MakeByMill( Proc, nRawId, b3Raw) -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- recupero e verifico l'entità curva local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then local sErr = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end -- recupero i dati della curva e del profilo local dDepth = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD) local bToolInv = ( vtExtr:getZ() < -0.1) local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') -- lettura parametri (probabile/i parametro/i Q) local nConeCut = VerifyCornerType( Proc) -- recupero la lavorazione local bTipFeed = EgtIf( nTool_ID, false, true) local sMilling = WM.FindMilling( 'FreeContour', nil, nil, nTool_ID, nil, nil, bTipFeed) if not sMilling then local sErr = 'Error : milling not found in library' if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dMillDiam = 20 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) then local 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 end end -- verifiche per affondamento if b3Aux:getDimZ() > b3Raw:getDimZ() - 1.0 then dDepth = min( dDepth, b3Raw:getDimZ()) end dDepth = dDepth + WD.CUT_EXTRA local bReducedDepth = ( dDepth > dMaxDepth) if bReducedDepth then dDepth = dMaxDepth end -- inserisco la lavorazione local sName = 'Free_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = WM.AddMachining( Proc, sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- se estrusione da sotto, inverto direzione fresa if bToolInv then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) end -- tolgo i Tabs se non passante o devo rimuovere lo sfrido if bReducedDepth or nConeCut == 1 then EgtSetMachiningParam( MCH_MP.LEAVETAB, false) end -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- assegno lato di lavoro if Proc.Grp == 0 then EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) elseif ( Proc.Grp == 3 and not bToolInv) or ( Proc.Grp == 4 and bToolInv) then EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) elseif ( Proc.Grp == 3 and bToolInv) or ( Proc.Grp == 4 and not bToolInv) then EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) end -- se lamatura affondata speciale (cliente 90480029), setto attacco e stacco al centro local bIsRecessedCounterBore = ( Proc.Box:getMax():getZ() < b3Raw:getMax():getZ() + 10 * GEO.EPS_SMALL) and ( nTool_ID == WD.RECESSED_COUNTERBORE_TOOLID or 0) and ( EgtCurveIsACircle( AuxId)) if bIsRecessedCounterBore then local _, _, _, dContourRadius = EgtCurveIsACircle( AuxId) -- setto attacco EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.TANGENT) EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) EgtSetMachiningParam( MCH_MP.LITANG, 0) EgtSetMachiningParam( MCH_MP.LIPERP, dContourRadius - 0.5 * dMillDiam) EgtSetMachiningParam( MCH_MP.LIELEV, 0) -- setto stacco EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) EgtSetMachiningParam( MCH_MP.LOTANG, 0) EgtSetMachiningParam( MCH_MP.LOPERP, dContourRadius - 0.5 * dMillDiam) EgtSetMachiningParam( MCH_MP.LOELEV, 0) -- imposto step local dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or 0 -- -- su richiesta del cliente 90480029 si usa sempre step unico a prescindere dalla geometria -- -- local dStep = EgtGetMachiningParam( MCH_MP.STEP) -- if dStep < GEO.EPS_SMALL then dStep = 0.75 * dMaxMat end -- local nStep = ceil( ( dDepth - dMaxMat) / dStep) -- dStep = max( ( dDepth - dMaxMat) / max( nStep, 1), 0) -- local dMaxElev = max( ( nStep + 1) * dStep - GEO.EPS_SMALL, 0) EgtSetMachiningParam( MCH_MP.STEP, dMaxMat) local dMaxElev = dMaxMat -- imposto elevazione e forzo attacco dal lato aperto EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( dMaxElev, 1) .. ';OutRaw=3;') end -- posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if AreSameOrOppositeVectorApprox( vtExtr, 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) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end -- se abilitata la lavorazione corner con stop macchina, ci sono almeno due facce e fresata passante per consentire eliminazione sfrido if nConeCut == 1 and Proc.Fct >= 2 and not bReducedDepth then -- gruppo ausiliario local nAddGrpId = WL.GetAddGroup( Proc.PartId) -- recupero i dati di tutte le facce local vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, b3Raw) -- se affondamento non superiore al limite if dDepth <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, dMillDiam, nAddGrpId, nil, nNewProc, 0, true) if not bMcok then return bMcok, sMcErr end else EgtErase( nNewProc) if nConeCut == 1 then local sErr = 'Clean corner 60° not applid because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2) EgtOutLog( sErr) end end elseif nConeCut == 2 then local sErr = 'Clean corner 30° is not applied on milling' EgtOutLog( sErr) elseif nConeCut == 3 then local sErr = 'Clean corner with undercut is not applied on milling' EgtOutLog( sErr) end return true end --------------------------------------------------------------------- local function MakeByMark( Proc, nRawId, b3Raw) -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- recupero e verifico l'entità curva local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then local sErr = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end -- recupero i dati della curva e del profilo local dDepth = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD) local bToolInv = ( vtExtr:getZ() < -0.1) local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') -- recupero la lavorazione local sMilling = WM.FindMilling( 'Text', nil, nil, nTool_ID) if not sMilling then local sErr = 'Error : milling not found in library' if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione local sName = 'FreeMark_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = WM.AddMachining( Proc, sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- se estrusione da sotto, inverto direzione fresa if bToolInv then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) end -- posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if AreSameOrOppositeVectorApprox( vtExtr, 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) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end return true end --------------------------------------------------------------------- local function MakeByNail( Proc, nRawId, b3Raw, vNLO) -- ingombro del pezzo local Ls = EgtGetFirstNameInGroup( Proc.PartId, 'Box') local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- recupero e verifico l'entità curva local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 if AuxId then AuxId = AuxId + Proc.Id end if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then local sErr = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end -- recupero i dati della curva e del profilo local dDepth = abs( EgtCurveThickness( AuxId)) local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) local b3Aux = EgtGetBBoxGlob( AuxId, GDB_BB.STANDARD) local bToolInv = ( vtExtr:getZ() < -0.1) local nCntData = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') or 0 if nCntData < 10 then nCntData = nCntData + 10 end local dCntPar = EgtGetInfo( Proc.Id, 'CNT_PAR', 'd') or 100 -- se presenti aree vietate alle chiodature, gestisco le geometrie local vCrvs = {} if #vNLO > 0 then -- in presenza di aree vietate non sono ammesse lavorazioni in doppio (non dovrebbe mai accadere per precedenti controlli) if Proc.Double then local sErr = 'Error : nailing in double with LockOut Area not allowed' EgtOutLog( sErr) return false, sErr end -- gruppo ausiliario local nAddGrpId = WL.GetAddGroup( Proc.PartId) -- copio la curva da lavorare vCrvs[1] = EgtCopyGlob( AuxId, nAddGrpId) -- la trimmo con tutte le aree vietate for i = 1, #vNLO do local vRes = {} for j = 1, #vCrvs do local nNewId, nCount = EgtTrimCurveWithRegion( vCrvs[j], vNLO[i], false, false) if nNewId then vRes = EgtTableAdd( vRes, nNewId, nCount) end end vCrvs = vRes end else vCrvs[1] = AuxId end -- per debug local sOut = table.concat( vCrvs, ',') EgtOutLog( 'Nailing curve : '.. ( sOut or '')) -- recupero la lavorazione local sNailing = WM.FindNailing( nCntData) if not sNailing then local sErr = 'Error : nailing not found in library' EgtOutLog( sErr) return false, sErr end for i = 1, #vCrvs do -- inserisco la lavorazione local sName = 'Nail_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_'..tostring( i) local nMchId = WM.AddMachining( Proc, sName, sNailing) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sNailing EgtOutLog( sErr) return false, sErr end EgtSetInfo( nMchId, 'Part', Proc.PartId) -- aggiungo geometria EgtSetMachiningGeometry( {{ vCrvs[i], -1}}) -- percorso da non invertire EgtSetMachiningParam( MCH_MP.INVERT, false) -- se estrusione da sotto, inverto direzione fresa if bToolInv then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) end -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, 10) -- assegno lato di lavoro EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.CENTER) -- se in doppio lungo Y, devo dimezzare opportunamente la lavorazione local dExtraDelta = 0 if Proc.Double == 2 then dExtraDelta = 0.45 * dCntPar if Proc.Delta > 0 then EgtSetMachiningParam( MCH_MP.ENDADDLEN, -Proc.DblAcc - dExtraDelta) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, -Proc.DblAcc - dExtraDelta) end end -- assegno parametri a note utente local sUserNotes = 'Par=' .. EgtNumToString( dCntPar, 0) .. ';' if Proc.Double and Proc.Double > 0 then sUserNotes = sUserNotes .. 'Dbl=' .. EgtNumToString( Proc.Double, 0) .. ';' .. 'Dlt=' .. EgtNumToString( abs( Proc.Delta) + dExtraDelta, 0) .. ';' end EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return false, sErr end end return true end --------------------------------------------------------------------- local function MakeByPocket( Proc, nRawId, b3Raw) -- recupero e verifico l'entità curva local nAddGrpId = WL.GetAddGroup( Proc.PartId) local bOpposite = false local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0 local vtExtr if AuxId then AuxId = AuxId + Proc.Id vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) if vtExtr then bOpposite = ( Proc.Grp == 4 and vtExtr:getZ() < 0) or ( Proc.Grp == 3 and vtExtr:getZ() > 0) if GetFacesExternalSide( Proc, vtExtr) ~= Proc.Grp then bOpposite = not bOpposite end end end if not AuxId or ( EgtGetType( AuxId) & GDB_FY.GEO_CURVE) == 0 then local sErr = 'Error : missing profile geometry' EgtOutLog( sErr) return false, sErr end local bPocketBotface = false -- se la curva è aperta non la svuoto if not EgtCurveIsClosed( AuxId) then bPocketBotface = true end -- cerco la faccia di fondo della superfice (deve avere direzione circa quella di estrusione della curva) local nFacet for i = 1, Proc.Fct do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) if abs( vtN * vtExtr) > 0.99 then nFacet = i - 1 break end end -- se tasca verticale si permette la svuotatura anche se passante, lavorando la faccia di fondo aggiunta local nProcTmWithAddedBottomSurfaceId if not nFacet and not bPocketBotface and Proc.AffectedFaces.Top and Proc.AffectedFaces.Bottom and AreSameOrOppositeVectorApprox( vtExtr, Z_AX()) then local nFirstLoopId, nLoopsCount = EgtExtractSurfTmLoops( Proc.Id, nAddGrpId) local dMinZ = GEO.INFINITO local nBottomLoopId = GDB_ID.NULL for i = 1, nLoopsCount do local nCurrentLoopId = nFirstLoopId + i - 1 local b3Loop = EgtGetBBoxGlob( nCurrentLoopId, GDB_BB.STANDARD) local dCurrentZ = b3Loop:getMin():getZ() if dCurrentZ < dMinZ then dMinZ = dCurrentZ nBottomLoopId = nCurrentLoopId end end local nAddedBottomSurface = EgtSurfTmByFlatContour( nAddGrpId, nBottomLoopId) local vtNAddedBottomSurface = EgtSurfTmFacetNormVersor( nAddedBottomSurface, 0) if AreOppositeVectorApprox( vtNAddedBottomSurface, Z_AX()) then EgtInvertSurf( nAddedBottomSurface) end nProcTmWithAddedBottomSurfaceId = EgtSurfTmBySewing( nAddGrpId, { nAddedBottomSurface, Proc.Id}, false) if nProcTmWithAddedBottomSurfaceId then -- ricerco la faccia di fondo della trimesh (gli id potrebbero essere cambiati) for i = 1, Proc.Fct do local vtN = EgtSurfTmFacetNormVersor( nProcTmWithAddedBottomSurfaceId, i-1, GDB_ID.ROOT) if abs( vtN * vtExtr) > 0.99 then nFacet = i - 1 break end end end -- elimino le geometrie che non servono più for i = 1, nLoopsCount do EgtErase( nFirstLoopId + i - 1) end EgtErase( nAddedBottomSurface) end if not nFacet then return MakeByMill( Proc, nRawId, b3Raw) end -- se ho creato la faccia di fondo utilizzo quella local nSurfId = nProcTmWithAddedBottomSurfaceId or Proc.Id -- se la faccia di fondo ha confini aperti, devo lavorarla direttamente local vAdj = EgtSurfTmFacetAdjacencies( nSurfId, nFacet)[1] or {} for i = 1, #vAdj do if vAdj[i] == - 1 then bPocketBotface = true break end end -- recupero i dati della curva e del profilo local dDepth = EgtIf( bPocketBotface, 0, abs( EgtCurveThickness( AuxId))) local dOriDepth = dDepth -- dati della faccia di fondo local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( nSurfId, nFacet, GDB_ID.ROOT) local dDiam = min( dH, dV) local dElev = WL.GetFaceElevation( nSurfId, nFacet, nRawId) -- gruppo ausiliario local nNewProc, nNumFacet = RemoveBottomFaceAndReorder( Proc, nAddGrpId, nFacet) -- se ho forma a L local bIsL = ( nNumFacet == 2 or WL.TestElleShape3( nNewProc, nNumFacet) or WL.TestElleShape4( nNewProc, nNumFacet) == 2) -- verifico se U local bIsU = ( nNumFacet == 3 and not WL.TestElleShape3( nNewProc, nNumFacet)) local dMiddleFacetLength = 0 if bIsU then local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( nNewProc, 1, GDB_ID.ROOT) -- prendo la linea di base if abs( dElev - dH2) < 1 and abs( dElev - dV2) > 1 then dMiddleFacetLength = dV2 elseif abs( dElev - dV2) < 1 and abs( dElev - dH2) > 1 then dMiddleFacetLength = dH2 end end if Proc.Fct < 5 and (( bIsL and not bIsU) or ( bIsU and dMiddleFacetLength > dDiam * 2)) then dDiam = dDiam * 2 end local nTool_ID = EgtGetInfo( Proc.Id, 'CNT_DATA', 'i') -- recupero la lavorazione local sPocketing = WM.FindPocketing( 'Pocket', dDiam, dDepth, nTool_ID) if not sPocketing then local sErr = 'Error : pocketing not found in library' if nTool_ID then sErr = sErr .. ' (Tool_ID=' .. tostring( nTool_ID) .. ')' end EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dMillDiam = 20 local dMaxDepth = 0 local dThDiam = 100 if EgtMdbSetCurrMachining( sPocketing) then local 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 -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( nSurfId) or tostring( nSurfId)) 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) -- aggiungo geometria if bPocketBotface then EgtSetMachiningGeometry( {{ nSurfId, nFacet}}) else EgtSetMachiningGeometry( {{ AuxId, -1}}) end -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_ZP if AreSameVectorApprox( vtExtr, 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) local sWarn = '' if bPocketBotface then local dThElev = dThDiam / 2 * sqrt( vtExtr:getX() * vtExtr:getX() + vtExtr:getY() * vtExtr:getY()) if dElev + dThElev > dMaxDepth + 10 * GEO.EPS_SMALL then dDepth = dMaxDepth - dElev - dThElev sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end else -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then dDepth = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- imposto elevazione EgtSetMachiningParam( MCH_MP.USERNOTES, 'MaxElev=' .. EgtNumToString( EgtIf( bPocketBotface, min( dElev, dMaxDepth), dMaxDepth), 1) .. ';') -- eseguo local bAppOk = EgtApplyMachining( true, false) if not bAppOk and not bPocketBotface then bPocketBotface = true EgtSetMachiningGeometry( {{ nSurfId, nFacet}}) dDepth = 0 local dThElev = dThDiam / 2 * sqrt( vtExtr:getX() * vtExtr:getX() + vtExtr:getY() * vtExtr:getY()) 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) bAppOk = EgtApplyMachining( true, false) end if not bAppOk then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- lettura parametri (probabile/i parametro/i Q) local nConeCut = VerifyCornerType( Proc) -- recupero i dati di tutte le facce local vFace, dMaxWidth vFace, dMaxWidth, nNewProc = GetFacesData( Proc, bOpposite, false, dMillDiam, dMaxDepth, (dMillDiam/2), nAddGrpId, b3Raw, nNewProc) -- se ci sono almeno due facce più quella di fondo if Proc.Fct >= 3 then -- se abilitata la lavorazione corner con stop macchina e affondamento non superiore al limite local dDepthMach = EgtIf( bPocketBotface, dDepth, ( dDepth - dOriDepth)) if nConeCut == 1 and dDepthMach <= ( WD.MAX_CLEAN_CRN60 + 20 * GEO.EPS_SMALL) then local bMcok, sMcErr = AddMillCorner( nConeCut, vFace, Proc, nRawId, b3Raw, dMillDiam, nAddGrpId, nil, nNewProc, dDepthMach) if not bMcok then return bMcok, sMcErr end else EgtErase( nNewProc) if nConeCut == 1 then local sErr = 'Clean corner 60° not applied because thickness: ' .. EgtNumToString( dThick, 2) .. ' is bigger than parameter MAX_CLEAN_CRN60: ' .. EgtNumToString( WD.MAX_CLEAN_CRN60 , 2) EgtOutLog( sErr) elseif nConeCut == 2 then local sErr = 'Clean corner 30° is not applied on pocketing' EgtOutLog( sErr) end end end return true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione function WPF.Make( Proc, nRawId, b3Raw, vNLO) -- recupero la tipologia (contorno o tasca) local bPocket = ( EgtGetInfo( Proc.Id, 'PCKT', 'i') == 1) -- se svuotatura if bPocket then return MakeByPocket( Proc, nRawId, b3Raw) -- altrimenti contorno else -- riordino le facce ReorderFaces( Proc.Id, EgtSurfTmFacetCount( Proc.Id)) -- recupero il tipo di lavorazione local nCntType = EgtGetInfo( Proc.Id, 'CNT_TYPE', 'i') or 0 -- se fresatura if nCntType == 2 then return MakeByMill( Proc, nRawId, b3Raw) -- se marcatura elseif nCntType == 10 then return MakeByMark( Proc, nRawId, b3Raw) -- se chiodatura elseif nCntType == 20 then return MakeByNail( Proc, nRawId, b3Raw, vNLO) -- altrimenti, taglio con lama e pulizia angoli con fresa else return MakeByCut( Proc, nRawId, b3Raw) end end end --------------------------------------------------------------------- return WPF